← Назад к вопросам

Приведи пример стресс-тестирования

1.2 Junior🔥 243 комментариев
#Теория тестирования

Комментарии (3)

🐱
deepseek-v3.2PrepBro AI6 апр. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

# Пример проектирования и проведения стресс-теста

Контекст и цели тестирования

Предположим, у нас есть веб-сервис API для размещения онлайн-заказов (/api/v1/orders). В рамках стресс-тестирования (Stress Testing) нашей целью является не просто определение максимальной пропускной способности, а изучение поведения системы за пределами нормальных рабочих нагрузок, выявление "узких мест" (bottlenecks) и проверка механизмов восстановления после снятия нагрузки.

Ключевые цели для данного примера:

  • Определить точку, в которой система перестает корректно обрабатывать запросы (например, увеличивается время ответа сверх SLA или растет процент ошибок).
  • Найти "узкие места" в условиях экстремальной нагрузки: ЦПУ, память, сетевой ввод-вывод, блокировки в базе данных.
  • Проверить механизмы деградации функциональности (graceful degradation) и устойчивости (resilience), если они заложены.
  • Оценить время и процесс восстановления системы после пиковой нагрузки.

Сценарий стресс-теста

Мы сфокусируемся на критическом сценарии — создание нового заказа. Это операция, включающая несколько компонентов: веб-сервер, сервисный слой, базу данных и, возможно, внешний платежный шлюз.

Профиль нагрузки:

  • Целевая нагрузка: 500 запросов в секунду (RPS) — это наш ожидаемый пиковый уровень.
  • Стратегия нагрузки для стресс-теста: Мы будем плавно превышать этот лимит, чтобы создать стрессовую ситуацию.
    *   Этап 1 (разогрев): 10 минут на уровне 100 RPS.
    *   Этап 2 (рост): Увеличение нагрузки на 100 RPS каждые 5 минут.
    *   Этап 3 (стресс): После достижения 500 RPS продолжаем увеличивать нагрузку на 50 RPS каждые 5 минут до появления критических ошибок (>10%) или полного отказа.
    *   Этап 4 (восстановление): Резкое снижение нагрузки до 50 RPS и наблюдение за восстановлением системы в течение 15 минут.

Инструментарий

Для генерации нагрузки будем использовать k6 — современное средство нагрузочного тестирования. Его скрипты на JavaScript легко описывают сложные сценарии.

Пример скрипта k6 для нашего сценария:

import http from 'k6/http';
import { check, sleep, group } from 'k6';
import { Trend, Rate } from 'k6/metrics';

// Кастомные метрики
let orderCreationDuration = new Trend('order_creation_duration');
let errorRate = new Rate('errors');

// Конфигурация теста
export let options = {
  stages: [
    { duration: '10m', target: 100 },  // Разогрев
    { duration: '20m', target: 500 },  // Плавный рост до целевой нагрузки (100->500 за 4 шага)
    { duration: '20m', target: 700 },  // Превышение целевой нагрузки (500->700 за 4 шага)
    { duration: '15m', target: 50 },   // Фаза восстановления
  ],
  thresholds: {
    'http_req_duration{status:201}': ['p(95)<2000'], // 95% успешных запросов должны выполняться быстрее 2 сек
    'errors': ['rate<0.05'], // Общий процент ошибок должен быть ниже 5%
  },
};

// Генерация тестовых данных
function generateOrderPayload() {
  const orderId = __VU * 1000000 + __ITER;
  return JSON.stringify({
    orderId: orderId,
    productId: Math.floor(Math.random() * 100) + 1,
    quantity: Math.floor(Math.random() * 5) + 1,
    customerId: `customer_${Math.floor(Math.random() * 1000)}`
  });
}

export default function () {
  group('API Stress Test', function () {
    // 1. Создание заказа (основная нагрузка)
    let payload = generateOrderPayload();
    let headers = { 'Content-Type': 'application/json' };
    let res = http.post('http://api-under-test.local/api/v1/orders', payload, { headers: headers });

    // Проверка результата и сбор метрик
    let checkResult = check(res, {
      'status is 201': (r) => r.status === 201,
      'response time OK': (r) => r.timings.duration < 5000,
    });

    // Регистрация кастомных метрик
    orderCreationDuration.add(res.timings.duration);
    errorRate.add(!checkResult);

    // 2. Небольшая пауза для имитации "мысли пользователя"
    sleep(Math.random() * 0.1);
  });
}

Мониторинг и анализ результатов

Во время выполнения теста мы мониторим не только метрики самого k6 (RPS, время ответа, процент ошибок), но и метрики инфраструктуры:

  • Серверы приложения: Загрузка CPU и памяти, количество потоков/процессов, сетевой трафик, очередь на обработку (например, thread pool в Java).
  • База данных: Активные соединения, время выполнения медленных запросов (slow queries), блокировки (locks), рост очереди на репликацию.
  • Внешние зависимости: Статус вызовов к платежному шлюзу, время ответа.

Типичные находки при стресс-тесте и их интерпретация:

  • Рост времени ответа и ошибок 5xx после 600 RPS: Это пороговая точка стресса. Если ошибки типа 502 Bad Gateway или 503 Service Unavailable, вероятно, исчерпан лимит одновременных соединений на веб-сервере (например, в Nginx worker_connections).
  • Резкий рост использования CPU на уровне 650 RPS до 95-100%: Приложение упирается в вычислительные ресурсы. Необходим профилирование кода для поиска "горячих точек" или вертикальное масштабирование.
  • Рост количества таймаутов соединения с базой данных: Может указывать на исчерпание пула соединений на стороне БД или приложения. Нужно проверить настройки connection pool (HikariCP в Java, например).
  • Система не восстанавливается после снятия нагрузки: Критическая находка. Может быть вызвана утечкой памяти (memory leak), неубиваемыми "зомби-процессами" или блокировками в БД, требующими ручного вмешательства.

Заключение и рекомендации

По результатам стресс-теста формируется отчет с графиками, выводами и рекомендациями:

  1. Определение предельной нагрузки: Система поддерживает до 600 RPS с приемлемым временем ответа. При 650 RPS процент ошибок превышает 10%, что является точкой отказа.
  2. Выявление "узких мест": Основное ограничение — CPU сервера приложения. Вторичное — настройки пула соединений с БД.
  3. Рекомендации:
    *   Оптимизировать наиболее ресурсоемкие методы в коде (профилирование через **Java Flight Recorder** или **Async Profiler**).
    *   Увеличить лимиты параллельных соединений на веб-сервере и в пуле БД.
    *   Рассмотреть внедрение механизмов **rate limiting** и **circuit breaker** на входе в систему, чтобы более контролируемо отклонять избыточную нагрузку и защищать внутренние компоненты.
    *   Запланировать тест после внесения изменений для верификации улучшений.

Стресс-тестирование — это не разовое мероприятие, а циклический процесс, интегрированный в CI/CD конвейер для ключевых сценариев, который позволяет постоянно оценивать запас прочности системы при ее развитии.

Приведи пример стресс-тестирования | PrepBro