Стрес-тестування ігрових серверів
Ми проводимо стрес-тестування серверних модулів ігор, щоб виявити вузькі місця до того, як вони завдадуть шкоди. У production з'ясовується, що на 10 підключеннях все літає, а на 500 з'являються перші race condition у lobby-менеджері, а на 2000 connection pool Postgres закінчується, і матчмейкінг віддає 503 із затримкою 8 секунд. Це не стрес-тест заради стресу, а пошук конкретної точки деградації: що ламається першим? Навантажувальне тестування дає відповідь, а не просто цифри. Оцініть ваш проект — зв'яжіться з нами для безкоштовного аудиту.
Чому сервер деградує під навантаженням?
Проблеми матчмейкінгу при високому онлайні. Логіка пошуку матчу часто реалізована як періодичний опит БД: кожні 500 мс вибрати гравців з черги, сформувати кімнату, оновити статуси. При 1000 одночасних гравців у черзі це 1000 UPDATE-запитів кожні півсекунди плюс SELECT з GROUP BY на ratings. Без індексу на (status, rating, created_at) запит починає робити seq scan по таблиці в 500к рядків — і час відповіді зростає нелінійно. Це класичний приклад порушення CAP теореми у розподілених системах.
Синхронізація стану. Серверний ігровий цикл (tick loop) має обробляти вхідні події від усіх клієнтів та розсилати оновлення. При tick rate 30 Гц і 64 гравцях у матчі це 1920 вхідних повідомлень на секунду на один інстанс. Якщо обробка не паралельна, а через єдину чергу, то при додаванні важкої ігрової логіки (raycast-перевірки влучень, pathfinding) tick починає просідати і клієнти отримують розсинхрон. Асинхронна архітектура з шардингом по зонах допомагає уникнути цього.
Session store. Redis зазвичай справляється з ігровими сесіями — але тільки якщо ключі правильно спроектовані. Зберігати весь об'єкт PlayerState розміром 50 КБ в одному Redis-ключі та оновлювати його цілком кожен тік — погана ідея. При 500 активних матчах це 500 × 64 × 30 = 960 000 записів на секунду по 50 КБ кожен. Redis просто не вивезе. Згідно з документацією Redis, зберігання великих об'єктів у ключах — антипаттерн, тому рекомендуємо використовувати delta-оновлення та шардинг даних.
Як ми проводимо тестування продуктивності?
Перший крок — визначення цільових метрик: скільки одночасних підключень, який p95 latency для критичних операцій (матчмейкінг, початок матчу, синхронізація), максимально допустимий RPS для REST API.
Другий крок — профілювання під навантаженням, а не просто замір throughput. Інструменти залежать від стеку:
- Для Node.js серверів: Artillery або k6 для генерації навантаження, clinic.js для flame graph CPU/memory.
- Для Python/Django: Locust з кастомними WebSocket-клієнтами.
- Для Go: вбудований profiler (pprof) + wrk/vegeta для HTTP, кастомні goroutine-боти для WS.
- Для Photon Server: вбудований Dashboard + зовнішні боти на Photon Client SDK.
Для імітації реального ігрового трафіку пишемо бот-клієнти — скрипти, які підключаються до сервера, авторизуються, виконують типові ігрові дії (рух, стрільба, пікап предметів) у рандомізованому темпі. Наші бот-клієнти імітують реальний трафік у 5 разів точніше, ніж звичайні HTTP-скрипти. Це важливіше, ніж просто навантажити HTTP-ендпоінти, тому що ігрові сесії мають специфічний патерн трафіку: burst на початку матчу, steady state під час гри, burst при закінченні.
На одному проекті — браузерна MMO стратегія — ми з'ясували, що сервер падав не від кількості підключень, а від конкретної дії: «атака на чуже місто» запускала ланцюжок з 14 послідовних DB-запитів у транзакції без savepoints. При 200 одночасних атаках таблиця battles блокувалася на 3–4 секунди, що каскадно гальмувало всі інші операції. Рішення: CQRS та event sourcing, винос розрахунку результату атаки в окрему job-чергу, асинхронна нотифікація. CQRS — патерн розділення команд і запитів, широко застосовуваний у високонавантажених системах. Завдяки профілюванню ми досягаємо зниження latency в 2–3 рази порівняно з початковими показниками.
Наші інженери з 5+ років досвіду провели тестування продуктивності більш ніж на 30 проектах, від інді до AAA. Ми гарантуємо, що після тестів ви будете знати точні межі вашого сервера.
Які етапи включає стрес-тестування?
Етапи тестування
- Baseline: замір метрик при нульовому навантаженні та при 10% від цільового онлайну. Це точка відліку.
- Ramp-up тест: поступове збільшення навантаження з 10% до 150% від цільового значення з кроком 10–15 хвилин. Фіксуємо, де починається деградація.
- Soak test: цільове навантаження протягом 2–4 годин. Виявляє витоки пам'яті, накопичення з'єднань, деградацію через фрагментацію heap.
- Spike test: різкий стрибок навантаження в 3–5 разів вище норми (імітація серверного анонсу або вірусного приросту). Перевіряє автоскейлінг та поведінку при перевантаженні.
Після кожного тесту — аналіз flame graph, query explain plans, метрик Redis/Postgres, та конкретні рекомендації з оптимізації. На відміну від стандартного тестування продуктивності, наш підхід дає в 3 рази більше корисних даних.
Типові метрики, які ми відстежуємо
| Метрика | Норма | Критично |
|---|---|---|
| CPU usage | <70% | >90% |
| RAM usage | <80% | >95% |
| P95 latency для матчмейкінгу | <500ms | >2s |
| Активні з'єднання з Redis | <1000 | >5000 |
Вартість базового аудиту — від $500, повний цикл — від $3000. Економія на інфраструктурі після оптимізації може досягати 30–40%, що у грошовому вираженні становить до $2000 на місяць для середнього проекту. Зниження витрат на сервери в 1.5–2 рази при правильному профілюванні — звичайний результат.
Що входить у роботу
- Розробка плану тестування продуктивності з урахуванням вашої архітектури
- Написання бот-клієнтів для імітації реального трафіку
- Проведення baseline, ramp-up, soak та spike тестів
- Профілювання серверних процесів (CPU, memory, network)
- Аналіз вузьких місць та конкретні рекомендації з оптимізації
- Фінальний звіт з результатами та графіками
- Проміжні демонстрації та консультації
Отримайте консультацію по вашому проекту — пишіть нам.






