Нагрузочное тестирование и стресс-профили
Краткое резюме
Нагрузочное тестирование — это системная проверка производительности и устойчивости под реалистичными и экстремальными сценариями. Основа успеха: корректная модель трафика (open vs closed), зафиксированные SLO, чистая метрика (latency/throughput/ошибки/насыщение), репрезентативные данные, автоматизация и повторяемость. Результат — не «цифра RPS», а решение: где узкие места, сколько стоит производительность, где порог отказа и как его сдвинуть.
SLO/SLI и целевые метрики
SLO (пример): p95 API ≤ 250 мс, p99 ≤ 600 мс; ошибка ≤ 0.3% / 30 дней.
SLI: latency (p50/p95/p99), throughput (RPS/CPS/QPS), saturation (CPU/heap/GC/FD/conn), ошибки (5xx, timeouts), очереди (depth/lag), DB (locks, slow queries), кэш (hit-ratio).
Буджеты ошибок и Saturation-триггеры (например, CPU > 75% или queue depth > X → деградация).
Виды тестов
1. Baseline/Benchmark — одиночный сервис/эндпойнт, «идеальные» условия.
2. Load — реалистичный «рабочий день» + ramp-up/ramp-down.
3. Stress — наращиваем нагрузку до деградации и фиксации breakpoint.
4. Spike — резкий скачок (x2–x10 за секунды/минуты).
5. Soak/Endurance — длительный прогон (8–72 ч): утечки памяти, дрейф латентности.
6. Capacity — ступенчатая нагрузка для построения кривой производительности и планирования емкости.
7. Degradation/Chaos-mix — нагрузка + частичные отказы (замедленная БД, падение кэша, «схлопнутый» аплинк).
Модели трафика: Open vs Closed
Open model (реалистичнее для интернета): пользователи приходят с интенсивностью λ (Poisson-подобный поток). Если система тормозит, запросы накапливаются, а не «замораживаются».
Closed model: фиксированное число виртуальных пользователей (VU) с think-time. При росте задержки RPS искусственно падает — осторожно с выводами.
Рекомендация: для фронтовых API используйте open model (k6 `arrival-rate`), для внутренних синхронных сценариев — комбинируйте с closed.
Профили нагрузки (шаблоны)
«Обычный день»: базовый фон + дневные колебания.
«Пик-ивент»: 10–30 мин до старта (прогрев), резкий spike на старте, плато, хвост.
«Турнир/стрим»: лесенка ступеней, повторные пики в интервалах.
«Деградация инфраструктуры»: половина кэша пуста, один регион выключен, увеличение латентности PSP.
«Failover»: трафик перетекает на резерв за 1–5 мин; проверяем авто-скейл/HPA/Retry-штормы.
Данные и подготовка окружения
Тестовые данные: реалистичный кардиналитет (провайдеры, валюты, страны), «грязные» поля, распределения запросов (Pareto/Zipf).
Секреты/PII: анонимизация; ключи/PSP — sandbox.
Окружение: выделенный perf-стенд, изоляция от интеграций (mock/стабы), фиксированные версии.
Наблюдаемость: метрики (Prometheus), логи (Loki/ELK), трассы (OTel). Фиксируйте build-id в ответах.
Антишторма ретраев и идемпотентность
Ретраи только для идемпотентных операций; ставьте retry-budget (напр., ≤ 10% от трафика).
Exponential backoff + jitter; «collapsing» идентичных GET.
Для платежей — идемпотентные ключи и явные статусы.
Защита от thundering herd: кэш-локи, SWR, локальные семафоры.
Инструменты и паттерны
k6 (скриптовый, open-model, хорошие отчетности), Locust (Python-сценарии), Gatling (Scala), JMeter (широкий спектр протоколов).
Протоколы: HTTP/1.1/2/3, gRPC, WebSocket, TCP/UDP; сервер-пуш не тестируйте «как GET».
Генерация трафика: горизонтальное масштабирование генераторов, контроль сетевого узкого места.
Съем профилей: pprof/async-profiler/ebpf под нагрузкой, трассы OTel.
javascript import http from 'k6/http';
import {check, sleep} from 'k6';
export const options = {
scenarios: {
warmup: { executor: 'ramping-arrival-rate', startRate: 50, timeUnit: '1s',
preAllocatedVUs: 200, stages: [ { target: 200, duration: '5m' } ] },
spike: { executor: 'constant-arrival-rate', rate: 1200, timeUnit: '1s',
preAllocatedVUs: 2000, startTime: '6m', duration: '3m' }
},
thresholds: {
http_req_failed: ['rate<0. 3%'],
http_req_duration: ['p(95)<250', 'p(99)<600']
}
};
export default function () {
const res = http. get(`${__ENV. BASE_URL}/api/v1/catalog? c=${Math. floor(Math. random()1000)}`);
check(res, { 'status is 200': (r) => r. status === 200 });
sleep(Math. random()0. 9) ;//think time (for closed parts of the script)
}
Методика проведения
1. Гипотеза → какие узкие места вероятны (CPU, БД, кэш, сеть, TLS, GC).
2. Профиль → сценарии/маршруты, доли трафика, модели (open/closed), данные.
3. Прогрев → кэш/коннекты/TLS/интерпретаторы.
4. Нарастание → ступени до целевой интенсивности.
5. Плато → сбор стабильных метрик и трасс.
6. Стресс/спад → поиск точки излома, наблюдение за авто-скейлом.
7. Разбор → корреляция метрик, flamegraph, отчет и план изменений.
8. Репруф → повтор через пайплайн CI (Regression Perf).
Анализ результатов
Кривая «нагрузка → задержка/ошибки»: ищем колено (capacity).
Breakdown латентности: сеть (DNS/TLS/connect), прокси, приложение, БД, внешние вызовы.
Сатурация: CPU > 75–85%, GC pause>p95, I/O-ожидания, очередь задач.
Эластичность: время реакции автоскейла (HPA/KEDA), «холодный старт», прогрев кэша.
Стоимость: $/1000 RPS при целевом SLO, прогноз бюджета на пик.
Инженерные практики
Индикаторы деградации: «хвосты» p99, рост очередей, падение hit-ratio, рост попыток ретраев.
Исключайте конфаундеры: лимиты файловых дескрипторов, sysctl, conn-pool, `reuseport`, TLS-цепочки, OCSP.
БД: индексы/планы/кэш запросов, пул соединений, батч-операции, backpressure на продьюсеров.
Кэши: размер/eviction-политика, горячие ключи, репликации.
Сеть/edge: HTTP/2/3, resumption≥70%, Brotli, CDN-ключ кэша, tiered-cache.
Наблюдаемость под нагрузкой
Метрики: системные (CPU/mem/IO), runtime (GC/heap), сетевые (RTT/loss/ECN), L7 (p95/99, 5xx/429), очереди, кластеры БД/кэш.
Трейсы: включить семплирование на «хвосты» (tail-based), пометки build-id/канарейки.
Логи: агрегация ошибок с ограничением объема (чтобы не «заDOSили» лог-пайплайн).
Эксперименты: feature-flags и конфиги должны фиксироваться в отчете.
Автоматизация и CI/CD
Perf-jobs в CI (smoke 3–5 мин, nightly 30–60 мин, weekly soak).
Границы допуска: латентность/ошибки/ресурсы → «ломаем билд» при регрессии.
Артефакты: графики, flamegraphs, профили, JSON-отчеты (k6/jtl).
Версионирование данных и сценариев, PR-ревью перф-скриптов.
Специфика для iGaming/финтех
Турниры/матчи: spike + plateau; прогрев TLS/DNS/CDN, повышенные лимиты пулов, «серые» маршруты для ботов.
Платежи/PSP: sandbox-лимиты, идемпотентность, строгие таймауты; проверка degrade-mode (кэш справочников, очереди).
Джекпоты/ивенты: атомарность и последовательность, отсутствие дублей, нагрузка на RNG/лидерборды.
Антифрод/AML: нагрузка на правила/ML-скоринг, backpressure, дедупликация событий.
Регуляторика: логирование метрик и версий при пиках, отчеты для аудита.
Чек-лист запуска
- Зафиксированы SLO/SLI и «красные линии» (ошибка/латентность/сатурация).
- Сценарии и профили нагрузки утверждены (open/closed, spike/soak/stress).
- Данные реалистичны, PII замаскированы, интеграции — sandbox/mock.
- Наблюдаемость готова: метрики/трейсы/логи, теги релиза.
- Конфиги систем (ulimit/sysctl/pools) задокументированы.
- План авто-скейла/подогрева кэша и rollback-критерии.
- Пороговые алерты и план связи команд (on-call).
- Отчетный шаблон (графики, выводы, действия) подготовлен.
Типичные ошибки
Тест closed-model выдает «зеленый» результат, а прод падает (нельзя игнорировать open-модель).
Нерепрезентативные данные (одна валюта/один провайдер) → ложные выводы.
Нулевая подготовка: холодные кэши/TLS/коннекты → завышенная латентность на старте.
Ретраи без лимитов → шторм и каскадные падения.
Одинаковые профили для всех сервисов → пропуск реальных «горячих точек».
Отсутствие soak-прогонов → утечки памяти и дрейф не видны.
Непрозрачные результаты: нет трасс/флеймграфов → невозможно локализовать узкое место.
Мини-плейбуки
Определение предельной пропускной способности (breakpoint)
1. Ступени по 10–20% нагрузки каждые 5–10 мин. 2) Фиксируем момент, где p95 резко растет и ошибки > SLO. 3) Снимаем профили CPU/БД/кэша. 4) План оптимизаций и повтор.
Обуздание штормов ретраев
1. Ограничить retry-budget и включить backoff+jitter. 2) Ввести request-collapsing/SWR. 3) Разрешить «деград-режим» (ограниченный функционал). 4) Перепроверить идемпотентность.
Пик-ивент (турнир) — пред-план
1. Прогреть CDN/DNS/TLS/пулы. 2) Увеличить target HPA, заготовить резерв. 3) Отдельные rate-лимиты для ботов. 4) Дашборды «пик-режима», мост связи on-call.
Soak-ночь
1. 8–12 часов стабильной нагрузки. 2) Мониторим heap/FD/conn/GC-pauses. 3) Сверяем дельту p95 и hit-ratio. 4) Фиксируем утечки и дрейф.
Итог
Нагрузочное тестирование — это процесс принятия инженерных решений, а не «гонка за RPS». Моделируйте реальные профили (особенно open-модель), фиксируйте SLO, снимайте метрики и трассы, ищите колено производительности и считайте стоимость производительности. Автоматизируйте прогоны, держите анти-шторма ретраев и планируйте пиковые события — так платформа будет предсказуемой и устойчивой в самые напряженные моменты.