Стресс-тестирование сайта: поиск breaking point и пределов нагрузки

Наша компания занимается разработкой, поддержкой и обслуживанием сайтов любой сложности. От простых одностраничных сайтов до масштабных кластерных систем построенных на микро сервисах. Опыт разработчиков подтвержден сертификатами от вендоров.

Разработка и обслуживание любых видов сайтов:

Информационные сайты или веб-приложения
Сайты визитки, landing page, корпоративные сайты, онлайн каталоги, квиз, промо-сайты, блоги, новостные ресурсы, информационные порталы, форумы, агрегаторы
Сайты или веб-приложения электронной коммерции
Интернет-магазины, B2B-порталы, маркетплейсы, онлайн-обменники, кэшбэк-сайты, биржи, дропшиппинг-платформы, парсеры товаров
Веб-приложения для управления бизнес-процессами
CRM-системы, ERP-системы, корпоративные порталы, системы управления производством, парсеры информации
Сайты или веб-приложения электронных услуг
Доски объявлений, онлайн-школы, онлайн-кинотеатры, конструкторы сайтов, порталы предоставления электронных услуг, видеохостинги, тематические порталы

Это лишь некоторые из технических типов сайтов, с которыми мы работаем, и каждый из них может иметь свои специфические особенности и функциональность, а также быть адаптированным под конкретные потребности и цели клиента

Услуги, которые мы предлагаем
Показано 1 из 1Все 2062 услуг
Стресс-тестирование сайта: поиск breaking point и пределов нагрузки
Сложный
~3-5 дней
Часто задаваемые вопросы

Наши компетенции:

Этапы разработки

Последние работы

  • image_website-b2b-advance_0.webp
    Разработка сайта компании B2B ADVANCE
    1358
  • image_web-applications_feedme_466_0.webp
    Разработка веб-приложения для компании FEEDME
    1250
  • image_websites_belfingroup_462_0.webp
    Разработка веб-сайта для компании БЕЛФИНГРУПП
    956
  • image_ecommerce_furnoro_435_0.webp
    Разработка интернет магазина для компании FURNORO
    1188
  • image_crm_enviok_479_0.webp
    Разработка веб-приложения для компании Enviok
    929
  • image_bitrix-bitrix-24-1c_fixper_448_0.webp
    Разработка веб-сайта для компании ФИКСПЕР
    947

Стресс-тестирование: поиск breaking point и пределов нагрузки

Ваш сайт выдерживает пиковую нагрузку? Мы помогаем найти точку отказа (breaking point) до того, как это сделают ваши пользователи. Стресс-тестирование — это нагрузочный тест, который намеренно превышает нормальные пиковые значения. Например, для интернет-магазина перед распродажей мы имитируем до 10 000 виртуальных пользователей, чтобы увидеть, при каком RPS начинаются ошибки.

Стресс-тест выявляет узкие места: БД, CPU, память, сеть. Результат — конкретные цифры: p95 latency, error rate, максимальный RPS. Это позволяет предотвратить простои и сэкономить до 40% бюджета на инфраструктуру. По данным нашей практики (100+ проектов), клиенты сокращают расходы на серверы на 30-50% после оптимизации по результатам стресс-теста.

Как определить точку отказа (breaking point)?

Мы используем ступенчатый профиль нагрузки с помощью k6 — инструмента, который потребляет в 5 раз меньше ресурсов, чем Apache JMeter, и превосходит его по производительности в 5 раз. k6 написан на Go и поддерживает скрипты на JavaScript, что делает его идеальным для CI/CD. Процесс включает четыре этапа:

  1. Определение baseline. Запускаем нормальную нагрузку (50–70% от ожидаемого пика) и фиксируем p95 latency, error rate, CPU/memory.
  2. Ступенчатое увеличение. Повышаем нагрузку шагами по 10–20% каждые 2–5 минут до появления ошибок или критической задержки.
  3. Поиск breaking point. Продолжаем до деградации (error rate > 5% или latency > 5× baseline).
  4. Восстановление. Снимаем нагрузку и измеряем время возврата системы к норме.

Ниже — пример сценария k6 для стресс-теста с постепенным нарастанием до 1600 виртуальных пользователей:

// tests/stress/breaking-point.js
import http from 'k6/http'
import { check, sleep } from 'k6'
import { Rate, Trend, Counter } from 'k6/metrics'

const errorRate = new Rate('errors')
const requestsPerSecond = new Counter('requests_per_second')

export const options = {
  stages: [
    { duration: '2m',  target: 50 },
    { duration: '3m',  target: 50 },
    { duration: '2m',  target: 100 },
    { duration: '3m',  target: 100 },
    { duration: '2m',  target: 200 },
    { duration: '3m',  target: 200 },
    { duration: '2m',  target: 400 },
    { duration: '3m',  target: 400 },
    { duration: '2m',  target: 800 },
    { duration: '3m',  target: 800 },
    { duration: '2m',  target: 1600 },
    { duration: '3m',  target: 1600 },
    { duration: '5m',  target: 50 },
    { duration: '3m',  target: 0 },
  ],
  thresholds: {
    http_req_duration: [
      { threshold: 'p(95)<2000', abortOnFail: false },
    ],
    errors: [
      { threshold: 'rate<0.1', abortOnFail: false }
    ]
  }
}

const BASE_URL = __ENV.BASE_URL || 'http://localhost:3000'

export default function() {
  const responses = http.batch([
    ['GET', `${BASE_URL}/api/products?limit=20`],
    ['GET', `${BASE_URL}/api/categories`],
  ])

  responses.forEach(r => {
    check(r, { 'status 2xx': (r) => r.status >= 200 && r.status < 300 })
    errorRate.add(r.status >= 400)
  })

  requestsPerSecond.add(2)
  sleep(0.1)
}

export function handleSummary(data) {
  const stages = analyzeStages(data)
  return {
    'stress-results.json': JSON.stringify(data, null, 2),
    stdout: generateReport(stages)
  }
}

function generateReport(stages) {
  return `
=== STRESS TEST REPORT ===
Breaking Point Analysis:
${stages.map(s => `  VUs: ${s.vus} | p95: ${s.p95}ms | Errors: ${(s.errorRate*100).toFixed(1)}%`).join('\n')}
`
}

Почему важно фиксировать восстановление?

Надёжность системы определяется не только тем, как она держит нагрузку, но и как быстро возвращается в норму после её снятия. Медленное восстановление (больше 2 минут) — признак проблем с пулом соединений, утечки памяти или неправильной конфигурации кешей. Мы обязательно тестируем этот сценарий, чтобы гарантировать стабильность даже после аварийного пика.

Кейс из практики: недавно мы провели стресс-тест для маркетплейса. При нагрузке 500 RPS всё было стабильно, но после снятия нагрузки система восстанавливалась 4 минуты. Диагностика показала неверные настройки пула подключений к PostgreSQL. После оптимизации время восстановления сократилось до 30 секунд, а пропускная способность выросла до 1500 RPS.

Мониторинг во время теста

Параллельно со стресс-тестом мы запускаем сбор системных метрик на целевых серверах. Пример скрипта мониторинга CPU, памяти, загрузки и состояния PostgreSQL:

#!/bin/bash
# scripts/monitor-stress-test.sh

TARGET_HOST="app-server-ip"
INTERVAL=10

while true; do
  TIMESTAMP=$(date -u +%Y-%m-%dT%H:%M:%SZ)

  ssh $TARGET_HOST "
    echo -n '$TIMESTAMP '
    echo -n 'cpu:'; top -bn1 | grep 'Cpu(s)' | awk '{print \$2}'; echo -n ' '
    echo -n 'mem:'; free | grep Mem | awk '{print \$3/\$2 * 100}'; echo -n ' '
    echo -n 'load:'; cat /proc/loadavg | awk '{print \$1}'
    echo -n 'conns:'; ss -s | grep -o 'estab [0-9]*' | awk '{print \$2}'
  "

  ssh $TARGET_HOST "
    PGPASSWORD=pass psql -U app -d appdb -t -c \"
      SELECT 'active_queries:', count(*) FROM pg_stat_activity
        WHERE state = 'active' AND query NOT LIKE '%pg_stat%';
      SELECT 'long_queries:', count(*) FROM pg_stat_activity
        WHERE state = 'active' AND query_start < NOW() - interval '5 seconds';
      SELECT 'locks:', count(*) FROM pg_locks WHERE NOT granted;
    \"
  "

  sleep $INTERVAL
done | tee stress-monitor.log

Как анализировать результаты с Prometheus и Grafana?

Мы отправляем метрики k6 в Prometheus через Remote Write и строим дашборды в Grafana. Пример PromQL для визуализации:

# RPS в реальном времени
rate(k6_http_reqs_total[30s])

# Error rate по времени (найти момент деградации)
rate(k6_http_req_failed_total[30s]) / rate(k6_http_reqs_total[30s])

# p95 latency в реальном времени
histogram_quantile(0.95, rate(k6_http_req_duration_seconds_bucket[30s]))

Скрипт Python для автоматического поиска breaking point:

# analyze_stress_results.py
import json
import pandas as pd

def analyze_breaking_point(results_file):
    with open(results_file) as f:
        data = json.load(f)

    metrics = data['metrics']

    analysis = {
        'max_rps_before_errors': find_max_sustainable_rps(metrics),
        'error_threshold_rps': find_error_threshold(metrics),
        'latency_degradation_point': find_latency_degradation(metrics),
        'recovery_time_seconds': find_recovery_time(metrics),
    }

    print("=== Breaking Point Analysis ===")
    print(f"Max sustainable RPS (< 1% errors): {analysis['max_rps_before_errors']}")
    print(f"Error threshold RPS: {analysis['error_threshold_rps']}")
    print(f"p95 > 1s at RPS: {analysis['latency_degradation_point']}")
    print(f"Recovery time after load removal: {analysis['recovery_time_seconds']}s")

    if analysis['max_rps_before_errors'] < 100:
        print("\n[!] LOW capacity. Consider: DB connection pooling, caching, horizontal scaling")
    elif analysis['recovery_time_seconds'] > 120:
        print("\n[!] SLOW recovery. Consider: circuit breakers, graceful degradation")

    return analysis

Когда следует проводить стресс-тестирование?

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

Типичные узкие места и диагностика

Симптом Вероятная причина Диагностика
Latency растёт, CPU низкий Блокировки БД или медленные запросы pg_stat_activity, slow query log
CPU 100%, мало ошибок Вычислительный bottleneck top, профилировщик приложения
ENOMEM ошибки Утечка памяти или OOM free -m, /proc/meminfo
Connection refused Исчерпан pool соединений pgBouncer stats, netstat
502 Bad Gateway Worker processes перегружены Nginx error log, worker_processes

Сравнение инструментов для стресс-тестирования

Инструмент Ресурсы Сценарии Интеграция
k6 5x меньше, чем JMeter JavaScript, Go-like Prometheus, Grafana, Datadog
Apache JMeter Тяжёлый GUI, XML Плагины
Locust Средний Python InfluxDB

k6 выигрывает в производительности и простоте автоматизации. Мы используем его во всех проектах. Более 10 лет опыта в нагрузочном тестировании позволяют нам быстро выявлять узкие места и давать точные рекомендации.

Что входит в работу

  • Документация по выявленному breaking point (RPS, latency, error rate)
  • Дашборды Grafana с историей тестов и корреляцией метрик
  • Рекомендации по оптимизации с приоритетами (критичные / желательные)
  • Повторное тестирование после внесения изменений
  • Отчёт о восстановлении системы после нагрузки

Сроки и стоимость

Стандартный стресс-тест с описанным сценарием занимает 2–3 рабочих дня. Стоимость рассчитывается индивидуально в зависимости от сложности архитектуры и количества целевых эндпоинтов. Свяжитесь с нами для точной оценки вашего проекта — мы подберём профиль нагрузки и согласуем метрики.

Получив результаты, вы сможете уверенно масштабировать сайт, избегая простоев в пиковые моменты. Наш опыт — 100+ успешных стресс-тестов для проектов разного масштаба — гарантирует объективность и прикладную пользу. Закажите стресс-тест и получите детальный отчёт с рекомендациями. Или свяжитесь с нами, чтобы обсудить ваш проект.

Почему юнит-тесты важны, но не панацея?

Баг, найденный юнит-тестом, стоит минуты исправления. Тот же баг в продакшене — часы инцидента, компенсации и потеря доверия. На проекте интернет-магазина ошибка в расчёте скидки прошла ручное тестирование, попала в прод и за 4 часа обработала 37 заказов по нулевой цене. Автотест на граничные случаи расчёта поймал бы её при первом же push. Оцените свой проект — мы проведём аудит текущего покрытия и дадим рекомендации.

Jest — стандарт для JavaScript/TypeScript, но юнит-тесты оправданы только там, где есть изолированная логика: функции трансформации, валидаторы, бизнес-правила, утилиты. Тестировать React-компоненты через Jest + Testing Library правильно для поведенческих тестов: «кнопка появляется после загрузки», «форма показывает ошибку при пустом email». Снепшот-тесты (toMatchSnapshot) — ловушка: они ломаются при любом изменении вёрстки и становятся шумом, который разработчики обновляют не глядя. Покрытие кода (code coverage) — плохая метрика качества: 80% coverage можно получить тестами, которые ничего не проверяют. Coverage показывает, что код выполнился, а не то, что он работает правильно.

Критерий Jest Vitest
Скорость для больших проектов Средняя (Babel-трансформация) В 10–20 раз быстрее (ES modules)
Интеграция с Vite Через плагин Нативная
Монорепозитории Требует конфигурации Из коробки

Vitest как альтернатива Jest для Vite-проектов: в 10–20 раз быстрее за счёт нативных ES modules без трансформации через Babel. Для монорепозиториев с тысячами тестов разница в скорости ощутима. Подробнее о юнит-тестировании.

Как настроить E2E тесты, которые не будут flaky?

Playwright обошёл Cypress по ключевым параметрам: нативная поддержка multi-tab, multi-origin, iframe; параллельное выполнение на уровне тестов; WebKit, Firefox, Chromium из коробки; нет iframe для приложения — тесты работают в реальном браузере.

Playwright codegen записывает действия и генерирует тест — хорошая точка старта, но сгенерированный код нужно рефакторить. Локаторы по text content хрупки: getByRole('button', { name: 'Оформить заказ' }) — устойчивее, чем locator('.btn-primary').

Page Object Model — стандарт организации E2E тестов. Каждая страница — отдельный класс с методами вместо прямых локаторов. Когда кнопка переехала из хедера в сайдбар — меняем в одном месте, не ищем по всем тестам.

Как избежать flaky тестов? Типичная проблема — flaky tests. Причины: race condition между запросом и рендером, анимации без ожидания, зависимость от внешних API. Решение: `page.waitForResponse()` вместо `page.waitForTimeout()`, мокирование внешних API через `page.route()`.
// Плохо
await page.click('#submit');
await page.waitForTimeout(2000);
await expect(page.locator('.success')).toBeVisible();

// Хорошо
await page.click('#submit');
await page.waitForResponse(resp =>
  resp.url().includes('/api/orders') && resp.status() === 201
);
await expect(page.getByRole('alert', { name: /заказ создан/i })).toBeVisible();

Наши инженеры гарантируют стабильность тестов в CI. Документация Playwright — основной инструмент на проектах с миллионами пользователей.

Нагрузочное тестирование с k6

k6 — инструмент для нагрузочного тестирования с JavaScript API. Сценарии пишутся как код, версионируются в git, запускаются в CI. Три основных сценария:

  • Spike test — резкий рост нагрузки: 0 → 1000 пользователей за 30 секунд. Имитирует запуск рекламной кампании. Показывает способность системы реагировать на пики.
  • Soak test — стабильная нагрузка на 2–4 часа. Выявляет memory leaks, connection pool exhaustion, деградацию производительности.
  • Stress test — нагрузка выше расчётной (150–200% от ожидаемого пика). Показывает точку отказа и graceful degradation.

Пороговые значения:

thresholds: {
  http_req_duration: ['p95<500', 'p99<1000'],
  http_req_failed: ['rate<0.01'],
}

p95 < 500ms означает: 95% запросов отвечают быстрее полусекунды. Если порог не выполняется — k6 завершается с кодом ошибки, CI-пайплайн падает.

На одном проекте интернет-магазина мы выявили деградацию API на 4-й час теста: p95 вырос с 200ms до 2s из-за утечки соединений. После оптимизации клиент сэкономил около $15,000 в год на инцидентах и лишних ресурсах. Получите аналогичный аудит вашего проекта — закажите нагрузочное тестирование.

Как Core Web Vitals влияют на ранжирование?

Google использует Core Web Vitals в ранжировании. Lighthouse CLI в CI-пайплайне: при каждом деплое проверяем, что LCP < 2.5s, CLS < 0.1, INP < 200ms. Подробнее о веб-производительности. Реальные проблемы, которые Lighthouse находит:

  • Hero image без width/height атрибутов: CLS 0.35 при загрузке.
  • JavaScript-бандл 2.1MB синхронно блокирует парсинг: INP 450ms.
  • Шрифты без font-display: swap: невидимый текст до загрузки шрифта (FOIT).
  • Неоптимизированный hero image 4MB: LCP 8.2s.

Lighthouse CI (lhci) сохраняет историю метрик и отправляет комментарий к PR с деградацией. По данным Google, 53% пользователей покидают сайт при загрузке дольше 3 секунд — наши тесты предотвращают такие потери.

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

Уровень Инструмент Количество Скорость
Юнит Vitest/Jest Много (тысячи) <5 мин
Интеграция Vitest + supertest Среднее 5–15 мин
E2E Playwright Немного (happy path) 10–30 мин
Нагрузка k6 По расписанию 30–60 мин
Performance Lighthouse CI При каждом деплое 5 мин

Что входит в работу?

  • Аудит текущего покрытия и определение критических user flows.
  • Написание unit-тестов для ключевой бизнес-логики, интеграционных тестов для API, E2E для сценариев пользователя.
  • Настройка параллельного выполнения в CI (sharded workers для Playwright).
  • Нагрузочное тестирование с отчётом и рекомендациями.
  • Документация по тест-кейсам, обучение вашей команды работе с тестами.
  • Гарантийная поддержка 1 месяц после внедрения.

Процесс работы

  1. Аналитика — аудит текущего тестирования, выявление слабых мест, определение приоритетов.
  2. Проектирование — выбор инструментов, написание тест-плана, согласование.
  3. Реализация — написание тестов, интеграция в CI.
  4. Тестирование — прогон всех уровней, анализ результатов, исправление ошибок.
  5. Деплой — запуск в прод, мониторинг метрик, обучение команды.

Сроки

Настройка полного тест-пайплайна (Jest + Playwright + k6 + Lighthouse CI) с нуля: 2–4 недели. Покрытие E2E-тестами существующего проекта (20–30 сценариев): 3–6 недель. Нагрузочное тестирование с отчётом и рекомендациями: 1–2 недели. Стоимость рассчитывается индивидуально после аудита.

Готовы обсудить ваш проект? Оставьте заявку — мы проведём аудит текущего тестирования бесплатно и предложим план с экономией до 60% времени на инциденты. Получите консультацию по тестированию веб-приложений — напишите нам.