SharksCode: найкращі практики підготовки до пікових навантажень

Одного ранку до нашої команди звернувся клієнт з повідомленням про спрацювання системного сповіщення (алерта). Ми негайно розпочали аналіз ситуації. Виявилося, що мікросервіс гейміфікації, який зазвичай функціонує на двох окремих сегментах (POD), раптово масштабувався до десяти, але не демонстрував ознак зменшення масштабу (зворотного скейлінгу). Хоча трафік залишався стабільно високим, жодних маркетингових акцій чи органічного зростання користувачів, що могло б пояснити таке різке збільшення навантаження, не спостерігалося.

Аналіз логів та реферерів (джерел трафіку) не виявив жодних відхилень від норми. Оскільки сервіс розташований на тому ж домені, що й основний продукт компанії, його трафік сприймався як внутрішній. Причина аномалії стала очевидною лише після нашого власного дослідження основного продукту, зокрема, перегляду меню. Виявилося, що нещодавно було додано новий віджет, який відображав кількість спроб користувача. Хоча інтеграція цієї функції була узгоджена, одна специфічна деталь, що спричинила проблему, не була врахована в документації. Цей віджет здійснював виклик відповідного ендпоінту (кінцевої точки доступу сервісу) при кожному завантаженні сторінки, навіть коли у користувача не було жодних доступних нагород, і віджет мав би перебувати у стані порожнього відображення.

Ми оперативно застосували тимчасове рішення, встановивши механізм кешування на Cloudflare з часом життя (TTL) у 3 секунди для зазначеного ендпоінту. Це негайно призвело до значного зменшення навантаження. Це рішення було призначене як тимчасовий захід до того часу, поки розробники фронтенду не внесуть зміни, додавши умову, яка б запобігала надсиланню запитів, якщо жодних нагород немає. Важливо зазначити, що жодних інцидентів на стороні кінцевих користувачів не виникло, оскільки система автоматичного масштабування (HPA) спрацювала належним чином, а сповіщення надійшло до того, як проблема могла спричинити негативні наслідки для користувачів.

Цей випадок яскраво ілюструє реалії роботи з високомасштабованими (highload) системами. Підготовка до пікових навантажень — це не просто збільшення ресурсів перед очікуваною подією. Це комплексний процес, що охоплює архітектуру системи, бази даних, інтеграційні механізми, моніторинг та готовність оперативно виявляти нетипову поведінку системи ще до того, як її помітять користувачі. У цій партнерській статті ми детальніше розповімо про те, як саме в компанії SharksCode організовано цей процес.

Партнер проєкту? SharksCode: найкращі практики підготовки до пікових навантажень 9 SharksCode: найкращі практики підготовки до пікових навантажень 10

Зміст

  • 1 З якими піками ми працюємо
  • 2 Що ми тестуємо перед піком
  • 3 Підготовка до піку по днях
    • 3.1 За 2–3 дні до піку
    • 3.2 За ~24 години до події
    • 3.3 Останні кілька годин перед піком
    • 3.4 Що відбувається в момент піку
  • 4 Які метрики ми дивимось у реальному часі
  • 5 Як система і команда реагують на інциденти

З якими піками ми працюємо

Наші клієнти створюють цифрові платформи, де різкі сплески трафіку є невід’ємною частиною їхньої бізнес-моделі. Найчастіше наша підготовка зосереджується на таких сценаріях:

  • Масштабні спортивні події на платформах клієнтів, зокрема, футбольні матчі, кіберспортивні змагання та ставки в реальному часі (live betting).
  • Запуск джекпот- (jackpot) або бонусних кампаній, що залучають значну кількість користувачів.
  • Проведення партнерських та реферальних акцій, що стимулюють користувальницьку активність.
SharksCode: найкращі практики підготовки до пікових навантажень 11
SharksCode: найкращі практики підготовки до пікових навантажень 12

Під час великих спортивних подій, таких як популярний live-матч, платформа клієнта може одночасно обслуговувати близько 50 000 сесій, генерувати до 10 000 запитів на секунду (RPS) до API та витримувати різкі сплески навантаження на запис. Ці піки, хоч і короткочасні, є надзвичайно інтенсивними, тому ми заздалегідь моделюємо їх для забезпечення безперебійної роботи.

Сценарії пікових навантажень у наших клієнтів завжди індивідуальні. Для одних це мільйони RPS, для інших – лише 500 користувачів, але з виконанням складних транзакцій. Тому ми не орієнтуємося на абстрактні цифри, а натомість фокусуємося на готовності самої системи до граничного для неї рівня навантаження.

Що ми тестуємо перед піком

Тестування починається з відтворення реальних дій користувачів, а не синтетичних симуляцій. Це включає такі процеси, як авторизація (логін), верифікація, здійснення серії ставок та інші типові операції. Кожен такий користувальницький сценарій являє собою каскад дій з певною послідовністю, і саме цей ланцюжок ми відтворюємо в наших тестах.

Критичність окремих сценаріїв визначається на основі трьох ключових факторів: бізнес-метрики (показники, що відображають успішність бізнесу), історичні дані (визначення ендпоінтів, які генерують 70–80% реального трафіку) та критичність самих транзакцій (де втрата або дублювання запиту може завдати шкоди репутації платформи).

Для проведення тестів ми використовуємо два основні інструменти:

  • k6 – для швидких, повторюваних тестів, які легко інтегруються в CI/CD (безперервна інтеграція/безперервна доставка) процеси та Grafana (система моніторингу);
  • Locust – коли необхідно змоделювати складні користувацькі сценарії (user flows) або масштабувати генерацію трафіку за допомогою розподілених агентів.
SharksCode: найкращі практики підготовки до пікових навантажень 13
SharksCode: найкращі практики підготовки до пікових навантажень 14

Ми приділяємо особливу увагу тестуванню API (затримка та пропускна здатність), баз даних (кількість з’єднань, блокування, відставання реплікації), черг повідомлень (Kafka/RabbitMQ) та систем інтеграції, зокрема з платіжними провайдерами. Це пов’язано з тим, що переважна більшість інцидентів виникає як ланцюгова реакція затримок, а не внаслідок падіння одного окремого сервісу.

Готовність системи до пікового навантаження оцінюється за чіткими цільовими рівнями сервісу (SLO): затримка на рівні 95-го перцентилю (p95 latency) має бути меншою за 200 мс, рівень помилок (error rate) – меншим за 0,5%, завантаження CPU/RAM – меншим за 80%, а пропускна здатність (throughput) – щонайменше 80% від очікуваного пікового значення. Ми працюємо за моделлю “бюджету помилок” (error budget), і якщо він вичерпаний, випуск нових версій продукту блокується.

Існують також аспекти, які ми свідомо не тестуємо, наприклад, тривалі навантаження або рідкісні граничні випадки (edge cases). Витрати на такі тести не виправдовують потенційної користі. Натомість ми покладаємося на синтетичний моніторинг та глибинне спостереження за системою в реальному часі (production observability).

Підготовка до піку по днях

За 2–3 дні до піку

За кілька днів до запланованого пікового навантаження ми запускаємо остаточні тести навантаження на конфігурації, максимально наближеній до продуктивного середовища. Проводимо перевірку потужності (capacity), зокрема, чи достатньо ресурсів у кластері та чи не досягнуті ліміти окремих вузлів. Вводиться “заморозка” змін: жодні зміни в коді або конфігурації не впроваджуються, окрім випадків надзвичайної критичності. Окремо проводяться тести відмовостійкості (failover) та перевірка резервних копій (бекапів). Усі ці процедури чітко задокументовані в посібнику (runbook), оскільки на цьому етапі будь-які імпровізації неприпустимі.

За ~24 години до події

Приблизно за добу до пікового навантаження ми тестуємо самі механізми сповіщень (алерти): перевіряємо, чи Grafana коректно надсилає повідомлення до PagerDuty, та чи функціонує канал сповіщень без збоїв. Переглядаємо дашборди, проводимо “сухий прогін” (dry-run) чергових інженерів (on-call), відпрацьовуємо ланцюжок ескалації – хто і кому передає відповідальність за інцидент, якщо первинний інженер не відповідає. Це, на перший погляд, банальні процедури, але саме вони часто призводять до збоїв системи в найневідповідніший момент, якщо їх не перевірити заздалегідь.

Останні кілька годин перед піком

Коли до настання пікового навантаження залишаються лічені години, наше головне завдання – мінімізувати кількість непередбачуваних факторів. У цей час DevOps-інженери займаються “попереднім розігрівом” (preheat-scaling): заздалегідь встановлюють мінімальну кількість POD на рівень, що відповідає очікуваному навантаженню, аби уникнути затримок, пов’язаних з реакцією HPA. Ці 30–60 секунд, що витрачаються на масштабування під час піку, можуть призвести до реальних помилок для користувачів.

Паралельно ми перевіряємо можливості масштабування баз даних. Для Aurora це включає запас за інстанс-класом та навантаженням на read replicas (репліки для читання). Для Atlas – налаштування автоматичного масштабування та ліміти рівня обслуговування (tier). Краще заздалегідь збільшити ресурси, а потім зменшити їх, ніж стикатися з деградацією продуктивності під навантаженням.

Обов’язково проводимо перегляд поточних інцидентів, таких як незакриті баги, нестабільні сервіси, недавні розгортання (деплої), які ще не пройшли перевірку реальним трафіком. Якщо будь-який з цих аспектів викликає сумніви, ми приймаємо рішення про відкат змін або готуємо альтернативний план дій. Також проводиться фінальна перевірка систем моніторингу та сповіщень.

В останні години перед піком ми зосереджуємося виключно на дисципліні. Чим менше несподіванок, тим спокійнішою буде наша робота.

Що відбувається в момент піку

У момент максимального навантаження кожен член команди чітко знає свою зону відповідальності, що запобігає провалам у координації. DevOps-інженери контролюють інфраструктуру (стан кластера, процеси масштабування, використання ресурсів), команда бекенду моніторить стан сервісів, аналізує логи та час відповіді, а адміністратори баз даних (DBA) стежать за показниками баз даних: повільні запити (slow queries), пул з’єднань (connection pool), реплікація.

Організація чергувань (on-call) здійснюється за допомогою Grafana OnCall з ротацією між основним та резервним інженером, а також ескалацією відповідальності до Solution Architect або CTO. Під час великих подій чергування подвоюється: один інженер не може охопити всі потенційні ризики, тому другий інженер виступає в ролі страхуючого. Комунікація відбувається в окремому каналі інциденту, куди автоматично надходять сповіщення, і де команда обмінюється контекстом події в реальному часі.

Які метрики ми дивимось у реальному часі

Під час пікового навантаження ми дотримуємося чіткої ієрархії моніторингу, послідовно аналізуючи показники.

Перший рівень – симптоми бізнесу. Рівень помилок (error rate) та час відгуку (latency) на рівні API. Ці метрики є першими індикаторами, що щось пішло не так з точки зору користувача, а не лише інфраструктури.

Другий рівень – бази даних. Активні з’єднання, повільні запити (slow queries), відставання реплікації (replication lag). Бази даних першими страждають від високого навантаження, а зовнішні симптоми проявляються пізніше. Якщо реагувати лише на показники API, реакція буде запізнілою.

Третій рівень – CPU та RAM. Ці показники важливі, але вони є радше індикаторами для запуску процесів масштабування. POD’и можуть споживати 90% CPU і при цьому працювати нормально, або ж використовувати мало ресурсів, але затримуватися в очікуванні з’єднання з базою даних. Тому ці метрики аналізуються в сукупності з першими двома рівнями.

Під час пікових навантажень ми використовуємо такі інструменти: Grafana з Prometheus як основним джерелом даних (з окремими дашбордами для API, БД та черг), Kibana для аналізу логів, та Datadog з кастомними дашбордами для бізнес-метрик.

Як система і команда реагують на інциденти

Резервування та механізми стійкості закладені на кожному рівні системи:

  • Kubernetes – автоматичне масштабування POD’ів та вузлів кластера.
  • Бази даних – Aurora з read replica та автоматичним переключенням у разі збою (failover), а також Atlas з replica set.
  • Istio (сервісна сітка) – застосування механізмів circuit breakers (розрив ланцюга) та політик повторних спроб (retry-policies).
  • Cloudflare – використовується як CDN (мережа доставки контенту) та швидкий інструмент кешування в екстрених ситуаціях.

У разі відмови основного компонента, переключення на резервний відбувається автоматично, без необхідності ручного втручання. Проте, автоматизація – це лише частина рішення. Алгоритм дій для інженера, який реагує на інцидент, виглядає наступним чином:

  1. Оцінити масштаб проблеми. Визначити, скільки користувачів зачеплено, які сервіси деградують, чи є фінансові втрати.
  2. Стабілізувати систему, а не одразу ремонтувати. Якщо існує швидке рішення, таке як відкат останнього розгортання, масштабування ресурсів, або активація резервного механізму (fallback), його слід застосувати першим.
  3. Визначення першопричини (root cause) відкласти на потім, коли система буде стабілізована. Спроби одночасно гасити пожежу та розбиратися в її причинах лише погіршать ситуацію.

Найшвидший час вирішення інциденту, який ми зафіксували, становив 4 хвилини – від звернення клієнта до повного усунення проблеми. Під час пікового навантаження було зафіксовано сплеск трафіку на API, але система відреагувала оперативно: спрацювали circuit breakers та автоматичне масштабування POD’ів. Успіху сприяла автоматизація в Istio та заздалегідь підготовлені runbooks.

Ключові уроки роботи з highload-системами:

  1. Моніторимо бізнес-метрики, а не лише інфраструктуру. Раніше ми фокусувалися на показниках CPU, RAM, кількості POD’ів. Якщо ці метрики були в нормі, здавалося, що все працює. Проте, CPU може бути завантажений лише на 30%, але користувачі вже не можуть здійснити оплату через вичерпаний пул з’єднань. Зараз ми отримуємо сповіщення про рівень помилок (error rate), затримку критичних ендпоінтів, затримку в чергах (queue lag). Інфраструктурні метрики стали другорядними.
  2. “Полювання на продуктивність” (Performance safari). Раз на спринт розробник аналізує метрики свого сервісу: дашборди, логи, профілі запитів, щоб виявити потенційні слабкі місця ще до того, як вони проявляться на продакшені.
  3. Під час інтеграцій обговорюємо поведінку системи в усіх можливих станах. Історія з віджетом гейміфікації, яку ми згадували на початку, саме про це. Недостатньо погодити API, необхідно ретельно перевірити відповідність коду діаграмам послідовності та розглянути різні сценарії: що відбувається, коли дані відсутні? Коли функція неактивна? Коли користувач не має доступу? Саме ці, здавалося б, очевидні випадки найчастіше спричиняють проблеми.
  4. Рецензування коду (code review) важливіше за будь-яку попередню підготовку. Більшість проблем під навантаженням пов’язані не з інфраструктурою, а з кодом: запити типу N+1, відсутність індексів, запити без таймауту, неналежна обробка помилок. Звичка ставити собі запитання “що буде при навантаженні x2, x5, x10?” під час кожного запиту на злиття коду (merge request) є ефективнішою за load-тести.
  5. Завжди повинен існувати швидкий шлях до відступу. Це може бути відкат розгортання (rollback), функціональний прапорець (feature flag) або резервний механізм (fallback). Highload-система – це не та, яка ніколи не виходить з ладу. Це та, яка передбачувано реагує на збої та швидко відновлюється.

Партнер проєкту? SharksCode: найкращі практики підготовки до пікових навантажень 15 SharksCode: найкращі практики підготовки до пікових навантажень 16

SharksCode
Олександр Кирильченко
Павло Фаринюк

Думка ЧАС НОВИН: Цей детальний розбір демонструє, що ефективна робота з highload вимагає не лише технічної експертизи, але й глибокого розуміння бізнес-процесів та культури безперервного вдосконалення. Підхід, що акцентує на проактивному виявленні проблем та швидкому реагуванні, є ключовим для забезпечення стабільності в умовах динамічного цифрового середовища.

Інформація підготовлена на основі матеріалів: itc.ua

No votes yet.
Please wait...

Залишити відповідь

Ваша e-mail адреса не оприлюднюватиметься. Обов’язкові поля позначені *