Одного ранку до нас звернувся клієнт із тривожним сповіщенням системи моніторингу. Разом ми розпочали аналіз ситуації: мікросервіс гейміфікації, який зазвичай функціонував на двох контейнерах (POD), раптово розширився до десяти, і жодних ознак повернення до нормального стану не було. Трафік залишався стабільно високим, проте відсутність будь-яких маркетингових кампаній чи органічного зростання користувацької бази не пояснювала такого різкого стрибка навантаження.
Перевірка логів та джерел трафіку (referer) не виявила аномалій. Сервіс розміщений на тому ж домені, що й основний продукт, тому його трафік сприймався як “рідний”. Причина несподіваного сплеску стала зрозумілою лише після детального вивчення функціоналу основного продукту. У меню з’явився новий віджет, що відображав кількість спроб користувача. Хоча деталі інтеграції були узгоджені, одна специфічна деталь, яка виявилася критичною, не була відображена в документації. Виявилося, що віджет звертався до певного API-ендпоінту при кожному завантаженні сторінки, навіть у випадках, коли користувач не мав жодних нагород, а віджет перебував у порожньому стані.
Для оперативного вирішення проблеми ми запровадили кешування на Cloudflare для цього ендпоінту з часом життя (TTL) у 3 секунди. Це дозволило миттєво знизити навантаження. Тимчасове рішення дозволило виграти час, поки розробники фронтенду не додали логіку, яка б запобігала зайвим запитам, якщо нагород немає. Важливо відзначити, що жоден користувач не відчув негативних наслідків, оскільки система автоматичного масштабування (HPA) відпрацювала коректно, а сповіщення спрацювало ще до того, як проблема стала критичною.
Цей випадок наочно демонструє реалії роботи з високими навантаженнями (highload). Підготовка до пікових навантажень – це не просто збільшення кількості ресурсів перед очікуваною подією. Це комплексний процес, що охоплює архітектуру системи, бази даних, інтеграції, системи моніторингу та, що найважливіше, здатність виявляти аномальну поведінку системи ще до того, як її помітять користувачі.
Партнер проєкту?
Зміст
- 1 З якими піками ми працюємо
- 2 Що ми тестуємо перед піком
- 3 Підготовка до піку по днях
- 3.1 За 2–3 дні до піку
- 3.2 За ~24 години до події
- 3.3 Останні кілька годин перед піком
- 3.4 Що відбувається в момент піку
- 4 Які метрики ми дивимось у реальному часі
- 5 Як система і команда реагують на інциденти
З якими піками ми працюємо
Наші клієнти розробляють продукти, де раптові сплески трафіку є невід’ємною частиною бізнес-моделі. Найчастіше ми готуємося до таких сценаріїв:
- Великі спортивні події на платформах клієнтів, такі як трансляції футбольних матчів, кіберспортивних турнірів або подій live betting.
- Проведення кампаній із розіграшами джекпотів (jackpot) та бонусів.
- Запуск партнерських та реферальних програм.
Під час популярних спортивних подій платформа клієнта може одночасно обробляти до 50 000 сесій, до 10 000 запитів на секунду (RPS) до API та зазнавати різких стрибків операцій запису (write operations). Ці піки, хоч і короткочасні, але надзвичайно інтенсивні, що вимагає ретельного планування та моделювання заздалегідь.
Пікові сценарії у наших клієнтів завжди індивідуальні. Деякі платформи можуть генерувати мільйон RPS, тоді як інші обслуговують лише 500 користувачів, але з виконанням складних транзакцій. Тому ми не обмежуємося абстрактними показниками, а фокусуємося на реальній готовності системи до граничних навантажень, специфічних саме для неї.
Що ми тестуємо перед піком
Тестування починається з відтворення реальних дій користувачів, а не синтетичних сценаріїв. Це включає послідовність операцій: логін, верифікація, серія ставок, тощо. Кожен такий ланцюжок дій є каскадом, що вимагає певної послідовності, яку ми й відтворюємо під час тестів.
Критичність певних сценаріїв визначається за трьома ключовими критеріями: вплив на бізнес-метрики, аналіз історичних даних (які ендпоінти генерують 70–80% реального трафіку) та важливість транзакцій (де втрата або дублювання запиту може завдати шкоди репутації платформи).
Для проведення тестів ми використовуємо два основних інструменти:
- k6: підходить для швидких та повторюваних тестів, легко інтегрується в CI/CD процеси та Grafana.
- Locust: використовується для моделювання складних користувацьких сценаріїв (user flows) або для генерації великих обсягів трафіку за допомогою розподілених агентів.
Найбільшу увагу приділяємо тестуванню API (затримка та пропускна здатність), баз даних (кількість з’єднань, блокування, затримка реплікації), черг повідомлень (Kafka/RabbitMQ) та інтеграцій, особливо з платіжними провайдерами. Причина полягає в тому, що більшість інцидентів є результатом ланцюгової реакції затримок, а не одночасного збою окремого сервісу.
Готовність до пікового навантаження оцінюється за чіткими угодами про рівень обслуговування (SLO): p95 latency (час відповіді для 95% запитів) має бути менше 200 мс, показник помилок (error rate) – менше 0,5%, використання CPU/RAM – не перевищувати 80%, а пропускна здатність (throughput) – сягати щонайменше 80% від очікуваного пікового навантаження. Ми працюємо за принципом “budget помилок” (error budget), і якщо він вичерпано, релізи програмного забезпечення блокуються.
Існують також аспекти, які ми свідомо не тестуємо, такі як тривалі навантаження або рідкісні граничні випадки (edge cases). Вартість проведення таких тестів не виправдовує їхньої користі. Натомість ми покладаємося на синтетичний моніторинг та аналіз роботи системи в реальному середовищі (production observability).
Підготовка до піку по днях
За 2–3 дні до піку
За кілька днів до очікуваного піку ми проводимо фінальні навантажувальні тести на конфігурації, яка максимально наближена до виробничого середовища. Перевіряємо ємність системи (capacity), зокрема, чи є достатній запас ресурсів у кластері, чи не досягаємо ми лімітів окремих вузлів (нод). Вводимо замороження змін (freeze on changes): жодні зміни у коді чи конфігурації не впроваджуються, окрім випадків надзвичайної необхідності. Окремо тестуємо сценарії відмовостійкості (failover) та перевіряємо резервні копії (бекапи). Весь процес детально формалізований у runbook, оскільки імпровізація на цьому етапі неприпустима.
За ~24 години до події
Приблизно за добу до пікового навантаження ми тестуємо самі системи оповіщення (алерти): чи дійсно Grafana надсилає повідомлення до PagerDuty, чи не вийшов з ладу канал сповіщень. Переглядаємо інформаційні панелі (дашборди), проводимо “сухий прогін” чергування (dry-run on-call), відпрацьовуємо ланцюг ескалації (escalation chain) – хто кому передає інцидент, якщо основний інженер не відповідає. Це може здатися дрібницями, але саме вони найчастіше стають причиною збоїв у найбільш невідповідний момент, якщо їх не перевірити.
Останні кілька годин перед піком
За кілька годин до настання піку наше головне завдання – мінімізувати кількість невідомих факторів. Фахівці DevOps займаються попереднім масштабуванням (preheat-scaling): заздалегідь встановлюють мінімальну кількість POD, необхідну для очікуваного рівня навантаження, щоб уникнути затримок із реакцією HPA під час піку. Ті 30–60 секунд, які система витрачає на масштабування, можуть призвести до реальних помилок для користувачів.
Паралельно ми перевіряємо можливості масштабування баз даних. Для Aurora це запас за типом інстансу та навантаженням на read replicas. Для Atlas – налаштування автоскейлінгу та ліміти тарифного плану (тіру). Краще заздалегідь збільшити ресурси, а потім зменшити їх, ніж боротися з деградацією продуктивності під навантаженням.
Обов’язково аналізуємо поточні відкриті інциденти: незакриті баги, нестабільні сервіси, нещодавні розгортання (деплої), які ще не пройшли перевірку реальним трафіком. Якщо виникають сумніви щодо стабільності, ми відкочуємо зміни або готуємо план “Б”. Також проводиться фінальна перевірка систем моніторингу та оповіщень.
В останні години перед піком ми зосереджуємося виключно на дисципліні. Чим менше несподіванок, тим спокійніше пройде цей період для команди.
Що відбувається в момент піку
Під час пікового навантаження кожен член команди чітко усвідомлює свою зону відповідальності, що запобігає “провалюванню” завдань між різними ролями. DevOps контролюють інфраструктуру (стан кластера, масштабування, ресурси), команда бекенду моніторить сервіси, лоґи та час відгуку, а адміністратори баз даних (DBA) відстежують стан баз: повільні запити (slow queries), пул з’єднань, реплікацію.
Чергування (on-call) організовано за допомогою Grafana OnCall з ротацією основного та резервного інженера, а також ескалацією до архітектора або CTO. Під час великих подій чергування подвоюється: один інженер не може охопити всі ризики, тому другий страхує першого. Комунікація здійснюється у спеціальному каналі інциденту, куди автоматично надходять алерти, і де команда в реальному часі обмінюється інформацією та контекстом.
Які метрики ми дивимось у реальному часі
Під час пікового навантаження ми дотримуємося чіткої ієрархії у моніторингу, визначаючи послідовність перегляду метрик.
Перший рівень – бізнес-симптоми. Показники рівня помилок (error rate) та затримки (latency) на рівні API. Ці метрики є першими індикаторами проблем з точки зору користувача, а не лише апаратного забезпечення.
Другий рівень – бази даних. Активні з’єднання, повільні запити (slow queries), затримка реплікації (replication lag). Бази даних першими починають відчувати навантаження, а зовнішні симптоми з’являються пізніше. Моніторинг лише на рівні API може призвести до запізнілої реакції.
Третій рівень – CPU та RAM. Ці показники важливі, але скоріше як індикатори для масштабування. Контейнери (POD) можуть споживати 90% CPU і при цьому нормально відповідати, або ж використовувати мало ресурсів, але перебувати в стані очікування з’єднання до бази даних. Тому ці метрики завжди аналізуються у поєднанні з метриками перших двох рівнів.
Інструменти, що використовуються під час пікового навантаження: Grafana з Prometheus як основним джерелом даних (окремі дашборди для API, баз даних та черг), Kibana для аналізу логів, Datadog з кастомними дашбордами для бізнес-метрик.
Як система і команда реагують на інциденти
Резервування (redundancy) закладене на кожному рівні системи:
- Kubernetes – автоматичне масштабування POD та вузлів кластера.
- Бази даних – Aurora з read replica та автоматичним відмовостійкістю (failover), а також Atlas з replica set.
- Istio – механізми circuit breakers та політики повторних спроб (retry policies) на рівні service mesh.
- Cloudflare – використовується як CDN (мережа доставки контенту) та швидкий інструмент кешування в екстрених ситуаціях.
У випадку відмови основного компонента, перемикання на резервний відбувається автоматично, без ручного втручання. Однак, автоматизація – це лише частина рішення. Алгоритм дій для інженера, який реагує на інцидент, виглядає наступним чином:
- Визначити масштаб проблеми. Скільки користувачів зачеплено, які сервіси деградують, чи є фінансовий вплив.
- Стабілізувати систему, а не одразу ремонтувати. Якщо існує швидке рішення (відкат розгортання, масштабування, увімкнення резервного режиму), його слід застосувати першим.
- Шукати першопричину (root cause) пізніше, коли система буде стабілізована. Спроба одночасно гасити пожежу та розбиратися в її причинах може лише погіршити ситуацію.
Найшвидше ми вирішили інцидент за 4 хвилини – від звернення клієнта до повного усунення проблеми. Під час пікового навантаження було зафіксовано сплеск активності на API, але система відреагувала оперативно: спрацювали circuit breakers та автоматичне масштабування POD. Важливу роль відіграли автоматизація в Istio та заздалегідь підготовлені runbooks.
Головні уроки роботи з highload
- Моніторимо бізнес-метрики, а не інфраструктуру. Раніше ми звертали увагу на показники CPU, RAM, кількість POD – зелений сигнал означав, що жодна метрика не вийшла за допустимі межі, і здавалося, що все працює нормально. Проте, CPU міг бути на рівні 30%, а користувач вже не міг здійснити оплату через вичерпаний пул з’єднань. Зараз ми отримуємо сповіщення про показники error rate, latency критичних ендпоінтів, затримку в чергах (queue lag). Інфраструктурні метрики стали другорядними.
- Performance safari. Раз на спринт розробник аналізує метрики свого сервісу – дашборди, логи, профілі запитів – шукаючи потенційні слабкі місця ще до їх появи на продакшені.
- Під час інтеграцій обговорюємо поведінку системи у всіх можливих станах. Історія з віджетом гейміфікації, яку ми згадували на початку статті, саме про це. Недостатньо домовитись про API, необхідно ретельно перевірити відповідність коду діаграмам послідовності (sequence diagrams) та протестувати різні сценарії. Важливо обговорювати: що робити, коли дані відсутні? Коли функція неактивна? Коли користувач не має доступу? Саме ці, здавалося б, очевидні випадки найчастіше і спричиняють проблеми.
- Code review важливіше за будь-яку підготовку. Більшість проблем під високим навантаженням пов’язані не з інфраструктурою, а з кодом: запити типу N+1, відсутність індексів, запити без таймаутів, недостатня обробка помилок. Звичка ставити собі запитання “а що буде при трафіку x2, x5, x10?” під час кожного запиту на злиття коду (merge request) працює ефективніше за навантажувальні тести.
- Завжди повинен бути швидкий шлях назад. Відкат розгортання (rollback), feature flag, fallback-механізми. Система, яка працює з highload, – це не та, яка ніколи не зазнає збоїв. Це система, яка передбачувано реагує на збої та швидко відновлюється.
Партнер проєкту?
SharksCode
Олександр Кирильченко
Павло Фаринюк
Думка UA Новини: Ця стаття детально розкриває проактивний підхід до управління високими навантаженнями, де фокус зміщується з реагування на проактивне виявлення проблем через глибокий моніторинг бізнес-метрик та ретельне тестування. Це свідчить про еволюцію інженерних практик у бік більшої надійності та стійкості систем.
Інформація підготовлена на основі матеріалів: itc.ua
