Однажды наша команда решилась на эксперимент по расстрелу боевой платежной системы реальными деньгами. Это позволило бы понять, сколько сможем выдержать мы вместе с нашими партнерами. Об этом неоднозначном опыте и хочу рассказать.
К исследованию побудили два фактора: появление у нас собственного процессинга карт и предстоящая крупная распродажа одного из популярных в РФ онлайн-ритейлеров.
Идея выглядела вполне бюджетной – примерно на 125 000 р. (по 1 р. на операцию), но кто же знал, как все обернется. Особая перчинка в том, что вся информация об эксперименте долгое время была закрыта и впервые публикуется в открытом источнике.
Как оказалось, мы не одиноки – ни один из наших банков-партнеров еще полгода назад не знал своего настоящего «потолка» и решал проблемы по мере поступления. По сути, они просто добавляли новые мощности прямо во время распродаж, хотя и не всегда успешно.
Будущие жертвы
Система карточных платежей (Mastercard в нашем случае) соединяет между собой множество внешних организаций, у каждой из которых свой зоопарк систем. Под нагрузку карточных платежей попадают практически все они, поэтому сразу посмотрим на всех участников.
Ниже представлена упрощенная схема взаимодействия нескольких организаций для обеспечения возможности оплатить какой-то товар картой через сервис Яндекс.Денег:
Все ключевые участники эксперимента на одной схеме. Яндекс.Танк – это отличный инструмент Яндекса для нагрузочного тестирования и комфортного анализа производительности.
Яндекс.Деньги принимают данные пластиковой карты у пользователя (в случае с тестом передается уже заполненный шаблон формы), а дальше происходит следующее:
Заполненная форма с данными карты передается на серверы фронтенда, которые ее обрабатывают и передают данные в бэкенд, а в дальнейшем – в отвечающее за работу со счетами ядро.
Платежный сервис блокирует сумму операции на счете пользователя и параллельно отправляет информацию об операции в банк-эквайер, который далее передает сведения в Mastercard и НСПК.
- Спустя сутки НСПК присылает файл блокировок в банк-эквайер и Яндекс.Деньги, после чего список блокировок разбирается в наших микросервисах и происходит списание денег со счета пользователя.
При масштабных онлайн-распродажах таких оплат может быть сотни в секунду, поэтому достанется всем звеньям платежной цепочки. Чтобы ни у кого не было претензий, мы заранее договорились с парой дружественных банков о том, что в определенные даты будут «боевые стрельбы» и что их сотрудники будут во всеоружии на местах.
Забегая вперед, после проведения первого эксперимента из 17 000 операций оказалось, что банки используют горизонтальную модель масштабирования платежных шлюзов, добавляя новые мощности по мере необходимости. В обычной жизни они успевают отреагировать на постепенный рост нагрузки, но в стрессовом режиме этого оказалось недостаточно.
Тут есть один тонкий момент. Дело в том, что все банки и Mastercard зарабатывают на выставляемых друг другу комиссиях за переводы. Сделать такую комиссию нулевой для тестов было практически невозможно. По нашим оценкам, совокупная цифра должна была составить 0,7% по отдельному коду категории оплаты MCC.
Величина комиссии являлась минимально возможной согласованной цифрой на момент проведения эксперимента с точки зрения всех принимающих участие сторон.
Запомните этот момент – в конце статьи будет с чем сравнить.
А не расстрелять ли нам процессинг
При тестировании производительности платежных сервисов неизбежно возникает ряд нюансов и ограничений, которые вынудили нас выйти с экспериментом на продакшн:
Производительность ключевых микросервисов (например, связанных с шифрованием карточных данных) ограничена лицензией.
Расположение микросервисов тоже ограничено лицензией. То есть сервер с купленной лицензией нельзя даже перенести в тестовую среду.
- Никто из наших банков-партнеров ранее ничего подобного не проводил и свою емкость не исследовал, поэтому просить мудрого совета было не у кого. Здесь выручило тесное сотрудничество с Mastercard и крупицы знаний из личного опыта отдельных людей.
В качестве подготовительных действий, мы также отключили дополнительную защиту платежа 3DSecure (SMS-коды), сняли лимиты на число и сумму операций на каждом этапе платежа, а также договорились со службами безопасности участников, чтобы они не били тревогу.
Тем важнее становился проект для Яндекс.Денег, так как кроме практической пользы можно было сделать нечто полезное для всей российской банковской отрасли – результаты и методика исследования могут пригодиться не только нам. Кроме того, мне лично всегда было любопытно, как поведет себя наш процессинг, если его как следует «расстрелять».
Радиус поражения
Как вы понимаете, никто не согласовал бы команде даже потенциальную остановку сервиса. Даже на несколько секунд.
Поэтому расстрел предстояло сделать бережным и прогнозируемым:
В качестве нагрузочной операции выбрали пополнение счета кошелька с банковской карты, которая привязана к другому кошельку. Эта достаточно простая операция влечет за собой массу транзакций между Яндекс.Деньгами, банком-эквайром, платежной системой и НСПК. Что и требуется для эксперимента.
Участвующий в эксперименте банк предоставил отдельный терминал для проведения платежей с оговоренным кодом MCC. На этом этапе каждая тестовая операция начинает стоить реальных денег, так как к MCC привязана определенная комиссия.
- Команда исследователей проводила нагрузочные стрельбы в несколько подходов, поддерживая оперативную связь с банками и собственными коллегами по всей системе, чтобы можно было приостановить поток по первому же «горшочек, не вари!».
MCC код (Merchant Category Code) — представляет собой 4-значный номер, присваиваемый платежными системами VISA, Mastercard и др. для классификации деятельности торговой точки в операции оплаты по банковским картам. Для владельца такой торговой точки важно получить как можно более выгодный MCC и платить меньшую комиссию платежной системе.
Все эти меры гарантировали хороший уровень отказоустойчивости платежного сервиса для пользователей даже при пиковых нагрузках.
Общая схема эксперимента: многопоточное пополнение кошельков с банковских карт других кошельков.
Для эксперимента мы согласовали уровень подаваемой интенсивности в 20 RpS (Requests per Second, число запросов в секунду). Для достижения большей производительности можно добавлять новые модули, но в схеме эксперимента присутствовал только один.
Яндекс.Деньги сотрудничают с несколькими банками-партнерами, но на масштабный эксперимент с реальными деньгами согласился только один из них.
На графике виден рост производительности на модуле процессинга при росте входной интенсивности, с провалом в центре как раз в момент проседания производительности нашего процессинга.
Кроме того, тесты вызвали некоторые проблемы в нашем бэкенде и ядре системы, создав массу блокировок по карточным счетам. Блокировки – это нормальная ситуация для любой карточной операции, так как перед реальным списанием деньги просто блокируются на счету пользователя и запись об этом попадает в общий файл Mastercard.
Такой файл каждый банк-эквайер ежедневно получает от Mastercard каждый раз в одно и то же время по согласованию и далее его разбирает. Так вот, после экспериментов файл с обычным размером 20 МБ увеличился в 5 раз и стал весить 104 МБ. На отработку такого списка потребовалось больше ресурсов, то есть пришлось переписать отдельные модули микросервисов, которые обрабатывали файл блокировок.
Что ж, мы немного оптимизировали запросы к БД, снизив нагрузку на процессор, и выпустили больше карт для снижения числа блокировок на одну карту.
Продолжаем обстрел
Вторая волна эксперимента проходила уже более ровно и спокойно, несмотря на более чем вдвое возросшее число обрабатываемых платежей.
График уже более равномерный, что говорит об успешности принятых мер. RpS равняется 20, так как это максимальное согласованное для эксперимента значение.
После окончания потока в 24 778 операций объем блокировок для каждой карты продолжил расти, что приводило к замедлениям при проведении платежей: перед каждым списанием процессингу приходилось считывать заново весь список блокировок конкретной карты. Решение — увеличить число карт с 50 до 10 050, что позволило для каждой сократить список блокировок с 200 до 1 при аналогичном количестве операций.
Следующая волна тестов принесла 50 000 операций, а списания подгрузились в базу процессинга за 40 минут, после чего нужно было их еще и обработать. Файл блокировок продолжал угрожающе расти с каждым экспериментом. А ведь ключевая БД процессинга работает на Oracle с ограничением в 4 ГБ на файл. До предела еще далеко, но становилось некомфортно.
В ходе отдельного эксперимента мы оценили производительность обработки списаний. За сутки провели тесты с интенсивностью 15 блокировок в секунду и последующим потоком списаний. Файл со списаниям пришел к нам в 18:00 следующего дня с задержкой в 1,5 часа, и наш процессинг обработал все 1 135 000 записей за 2 часа 10 минут. Для контраста, обычный разбор среднестатистического списка блокировок занимает десяток минут.
Проблемы возникли также с производительностью антифрод-машины и фронтенд-балансировщика запросов. Дело было в том, что балансировщик не проверял логическую доступность сервиса на узле, ограничиваясь только его присутствием в сети.
Кроме того, массированный обстрел повсеместно привел к росту размера логов, что дополнительно проверило на прочность нашу систему сбора логов на EHK (Elasticsearch/Heka/Kibana), о которой недавно рассказывали.
Кульминацией стал эксперимент на двое суток с суммарным числом операций 1 400 000, во второй день которого одновременно происходили две вещи:
Проходили тестовые стрельбы с платежами.
- Разбирался файл блокировок предыдущего дня объемом 3,1 ГБ.
Две эти операции нагрузили процессинг по полной в рамках существующих лицензионных ограничений 20 RpS.
Боевые стрельбы закончились через два дня на отметке 3 157 800 проведенных операций. Однако как следует отпраздновать успех и полюбоваться цифрами нам не дали.
Привет от Mastercard
Нам выставили счет в €157 890 в качестве комиссии за проведенные операции, что немного не вписывалось в оговоренные 0,7% с 125 000 р.
При заказе терминала под тестовые операции мы указали неверный MCC код, из-за чего и получилось невероятная комиссия.
А вот и причина безобразия – мы выбрали не тот код MCC для терминала эквайринга, через который проходили все тестовые стрельбы. Поэтому за операцию на 1 р. платили 4 р. комиссии. Узнать об этой проблеме в ходе эксперимента не представлялось возможным, так как Mastercard выставил счет через неделю.
Недоразумение обошлось нам в 2 месяца напряженной работы по ручному урегулированию вопроса с Mastercard. Фактически мы подняли логи всего эксперимента, по которому выполнялся поиск и изменение операций в Mastercard. Лишнее подтверждение, что без подробных логов никуда.
Несмотря на давность эксперимента и незначительные финансовые убытки от его проведения, опыт однозначно положительный. Более того, подобные боевые стрельбы стали регулярными, а полученные данные позволи серьезно увеличить производительность карточных операций.
Конечно же, все персонажи и числа в статье были творчески переосмыслены из соображений безопасности, но фантазировали мы не слишком бурно и сохранили соотношения полученных по эксперименту данных.