Як «полювання на лимони» перевантажило монобанк і чи можна було до цього підготуватися. Погляд спільноти
16 жовтня в monobank стався масштабний збій у роботі застосунку. Причиною стала гра «Полювання на лимони», яку банк запустив на честь досягнення 10 мільйонів клієнтів. Через надмірне навантаження система не витримала, і користувачі тимчасово втратили доступ до банківських послуг.
Як потім зазначив засновник mono Олег Гороховський, навантаження на всі сервіси зросло у сім разів, а технічна команда «практично не спала».
В обговоренні на DOU користувачі ділилися думками щодо збою в застосунку. Хтось поставився до цього з гумором, а дехто обурився через те, що не міг сплатити податки чи переказати кошти.
DOU вирішив запитати думку технічних фахівців, чому система не витримала, як mono могла підготуватися до навантаження та що варто робити у таких випадках.
Чому стався збій
DevOps-інженер Всеволод Поляков зазначає, що архітектура monobank є цілком нормальною для його масштабів і звичайного використання. За його словами, навіть під час «лимонного самоддосу» система витримала навантаження без каскадних збоїв, що свідчить про запас міцності й адекватні архітектурні рішення.
Його версія така — команда не підготувалася до такої кількості користувачів у системі:
Всеволод Поляков DevOps-інженер
Проблема суто в комунікації маркетингу й технічної команди, тобто не були заздалегідь протестовані сценарії, коли велика кількість легітимних користувачів генерує таку кількість запитів по всіх можливих сторінках.
Director of Engineering Артур Шевченко додає, що кількість запитів на секунду (RPS) зросла у десятки, а можливо, й у сотні разів, унаслідок чого почали виникати архітектурні та інфраструктурні «вузькі місця», а механізми автоскейлінгу не спрацювали належним чином.
Артур Шевченко Director of Engineering
Ймовірно, з’явилися hot spot’и — багато однакових запитів до тих самих ендпоїнтів чи екранів. Можливо, бракувало ізоляції, і так званий ігровий трафік ішов тим самим шляхом, що й критичні банківські функції. Або не вистачало глобальних rate-limit’ів чи механізмів backpressure. А на клієнтському боці, ймовірно, діяли постійні агресивні retry чи polling, які лише множили навантаження. Звісно, це лише гіпотези. Але, базуючись на досвіді пікових навантажень, саме там зазвичай і з’являються ботлнеки.
Co-founder і CTO в SHALB Володимир Цап теж вважає, що проблема почалася з планування. Навантажувальне тестування, на його думку, або не проводилося, або дало хибні результати:
«Відповідно не було деталізації впливу на інфраструктуру при запуску фічі. Це продуктова та процесуальна проблема», — пояснює експерт.
На його думку, «лимони» можна було розкласти у застосунку так, щоб більшість операцій виконувалась на клієнті, з мінімальними зверненнями до сервера.
«Я майже впевнений, що все почало „втикатися“ в авторизацію чи базу даних або в черги. Для моделювання можна уповільнювати трафік, губити підключення, додавати sleep у запити до бази даних — є багато способів», — додає Всеволод Поляков.
Експерти вважають, що зазвичай ціна таких ситуацій — репутація. Ще один результат — команда отримала стрес-тест на продакшені.
Володимир Цап Co-founder і CTO в SHALB
В Україні не більше як десяток сервісів з такою кількістю користувачів. В кожного свої «слабкі місця» і «промахи», падіння сервісу — це неминуче, головне мати план «Б».
Що радять розробники
На думку Всеволода Полякова, головний висновок для інших компаній — комунікація між маркетингом і технічною командою має бути послідовною та детальною, а ризики маркетингових акцій повинні бути пропрацьовані заздалегідь.
«На місці технічного директора я б провів аудит системи оцінки ризиків і переглянув модель передбачення навантаження. Схоже, ніхто не поставив питання: „Що буде, якщо сотні тисяч людей одночасно клацатимуть усі сторінки з частотою
1-3 запити на секунду?“ Після такого питання будь-яку акцію, ймовірно, переробили б, бо навіть підготовка до подібного випробування коштує дорого», — вважає експерт.
Він додає — коли у момент «outage» все починає зависати, а зупинити процес неможливо, залишається тільки спостерігати. Тому корисно мати систему, яка може тимчасово призупиняти запити від найактивніших користувачів і швидко зменшувати трафік, щоб полегшити масштабування.
Всеволод Поляков ділиться кількома практичними порадами:
- Підкласти кеш для зменшення навантаження на базу даних.
- Додати read-репліки для баз даних, щоб розподілити запити.
- Вивести частину сторінок у статично згенеровані, зокрема сторінки про страхування, старі дані про транзакції, обмін валют чи контакти підтримки.
- Переглянути модульність і автономність елементів застосунку, щоб збій одного модуля не впливав на інші.
- Перевірити незалежність сервісів і їхній скейлінг — розділити відповідальність між компонентами.
- Додати хаос-тестування для перевірки стійкості системи в умовах збоїв.
- Установити обмеження (rate-limit) на кількість запитів до бази даних від одного користувача.
Артур Шевченко зазначає, що в подібних випадках варто заздалегідь проводити performance-тести й орієнтуватися на метрики latency p95/p99, error rate, saturation і RPS на кожному рівні системи. Для бази даних і кешу — стежити за connection pool’ами, slow queries, lock waits і hit ratio.
Під час тестів, за його словами, слід моделювати стрибки навантаження у
«Я схиляюся до думки, що окремий (логічний чи фізичний) кластер для таких івентів точно зменшив би ризики, але я не знаю, наскільки це відповідало їхнім ресурсам і дедлайнам. Може, пан Гороховський сказав це за день: „Розмістити лимони в кількості 50 — терміново!“, і хлопці побігли пушити в прод „лимонну гарячку“», — жартує Шевченко.
Також, на його думку, могли б допомогти окремі gateway або ratelimiter’и, власні кеші чи пули з’єднань, а також доступ лише read-only через черги. Але, як він уточнює, це лише один із можливих варіантів, а не готове рішення.
Що ще радить Шевченко:
- Відокремлювати віральні акції від критичної функціональності.
- Використовувати rate limiterʼи, backoff+jitter у клієнті, edge-кеш, але розуміти, що в усіх можуть бути свої компроміси.
- Проводити performance-тестування, а також негативне тестування взаємодії компонентів, коли окремі сервіси падають, недоступні чи не можуть масштабуватися.
Експерт наголошує, що це лише припущення, що ґрунтуються на наслідках. Для глибшого аналізу потрібно знати контекст розробки та умови, у яких була команда.
Ми також звернулися до команди mono за технічними деталями та поділимося інформацією, щойно її отримаємо.
Всеволод Поляков DevOps-інженер
Артур Шевченко Director of Engineering
Володимир Цап Co-founder і CTO в SHALB