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

Проводил ли тестирование на стенде нагрузочного тестирования

2.0 Middle🔥 141 комментариев
#Тестирование

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

🐱
claude-haiku-4.5PrepBro AI23 мар. 2026 г.(ред.)

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

Опыт нагрузочного тестирования

Да, я регулярно проводил нагрузочное тестирование (load testing) приложений в production-подобной среде. Это критически важный этап разработки для Java приложений, которые должны работать под высокой нагрузкой.

Что такое нагрузочное тестирование

Нагрузочное тестирование — это проверка поведения приложения при конкретных нагрузках:

  • Сколько пользователей может обработать одновременно
  • Какой максимальный throughput (запросов в секунду)
  • Как себя ведёт система при пиковых нагрузках
  • Где находятся "узкие места" (bottlenecks)

Инструменты, которыми я работал

1. Apache JMeter

Использовал для:

  • Создания сценариев с множественными потоками пользователей
  • Тестирования REST API и веб-приложений
  • Анализа response time, throughput, error rate

Преимущества:

  • GUI для создания тестов
  • Поддержка различных протоколов (HTTP, JDBC, JMS, SSH)
  • Хорошая визуализация результатов

Недостатки:

  • Требует много памяти при большом количестве потоков
  • Медленный в работе

2. Gatling

Использовал для:

  • Масштабного нагрузочного тестирования (высокий throughput)
  • Симуляции реальных сценариев пользователей
  • Написания тестов как кода (Scala DSL)
// Пример Gatling теста
package simulations;

import io.gatling.javaapi.core.*;
import io.gatling.javaapi.http.*;

import static io.gatling.javaapi.core.CoreDsl.*;
import static io.gatling.javaapi.http.HttpDsl.*;

public class ApiLoadTest extends Simulation {
    HttpProtocolBuilder httpProtocol = http
        .baseUrl("https://api.example.com")
        .acceptHeader("application/json")
        .contentTypeHeader("application/json");

    ScenarioBuilder users = scenario("Users API")
        .exec(
            http("Get users")
                .get("/api/v1/users")
                .check(status().is(200))
        )
        .pause(1);

    ScenarioBuilder search = scenario("Search")
        .exec(
            http("Search users")
                .get("/api/v1/users?query=john")
                .check(status().is(200))
                .check(jsonPath("$.length").exists())
        )
        .pause(2);

    {
        setUp(
            users.injectOpen(rampUsers(100).during(10)).andThenKeepGoing(100),
            search.injectOpen(rampUsers(50).during(10)).andThenKeepGoing(50)
        ).protocols(httpProtocol);
    }
}

3. Locust (Python-based)

Использовал для:

  • Тестирования при очень большом количестве виртуальных пользователей
  • Распределённого нагрузочного тестирования (master-slave)
  • Простоты написания тестов на Python

4. Wrk / Apache Bench

Использовал для:

  • Быстрого базового тестирования
  • Простого HTTP нагрузочного тестирования
  • Benchmark отдельных endpoints

Реальные примеры нагрузочного тестирования

Проект 1: E-commerce API

Сценарий:

  • Симуляция 1000 одновременных пользователей
  • Каждый пользователь: просмотр товаров → добавление в корзину → оформление покупки
  • Ramp-up: 5 минут (плавное увеличение нагрузки)
  • Stabilization: 10 минут (постоянная нагрузка)
  • Ramp-down: 2 минуты (плавное снижение)

Результаты:

  • Throughput: 5000 req/s
  • Average response time: 200ms
  • P95 latency: 500ms
  • P99 latency: 1000ms
  • Error rate: < 0.1%

Найденные проблемы:

  • Database connection pool был недостаточный
  • Отсутствие кеширования на уровне приложения
  • N+1 query проблема в endpoint получения товаров

Проект 2: Real-time Notification System

Сценарий:

  • WebSocket connections: 5000 одновременных
  • Broadcast messages: 100 сообщений в секунду
  • Продолжительность: 30 минут

Тест на Java:

public class WebSocketLoadTest {
    private static final int NUM_CLIENTS = 5000;
    private static final String SERVER_URL = "ws://localhost:8080/notifications";
    
    public static void main(String[] args) throws Exception {
        CountDownLatch latch = new CountDownLatch(NUM_CLIENTS);
        List<WebSocketClient> clients = new ArrayList<>();
        
        long startTime = System.currentTimeMillis();
        
        for (int i = 0; i < NUM_CLIENTS; i++) {
            WebSocketClient client = new WebSocketClient(
                new URI(SERVER_URL),
                new WebSocketListener() {
                    private int messageCount = 0;
                    private long totalLatency = 0;
                    
                    @Override
                    public void onMessage(String message) {
                        messageCount++;
                        long latency = System.currentTimeMillis() - Long.parseLong(message);
                        totalLatency += latency;
                        
                        if (messageCount % 1000 == 0) {
                            long avgLatency = totalLatency / messageCount;
                            System.out.println("Avg latency: " + avgLatency + "ms");
                        }
                    }
                    
                    @Override
                    public void onClose(int code, String reason, boolean remote) {
                        latch.countDown();
                    }
                }
            );
            
            client.connectBlocking();
            clients.add(client);
        }
        
        // Ждём завершения
        latch.await(30, TimeUnit.MINUTES);
        
        long endTime = System.currentTimeMillis();
        System.out.println("Test duration: " + (endTime - startTime) + "ms");
    }
}

Метрики, которые я всегда проверяю

1. Response Time

Average: среднее время ответа
P95 (95-й перцентиль): 95% запросов ответили быстрее
P99 (99-й перцентиль): 99% запросов ответили быстрее
Max: максимальное время ответа

Целевые значения для API:

  • Average: < 200ms
  • P95: < 500ms
  • P99: < 1000ms

2. Throughput

RPS (requests per second): сколько запросов в секунду обрабатывает
Measures: как система масштабируется при увеличении нагрузки

3. Error Rate

< 0.1% — приемлемо для production
< 1% — допустимо при load testing

4. Resource Utilization

CPU: обычно 70-80% при нормальной нагрузке
Memory: мониторить утечки памяти
Database connections: не должны быть исчерпаны
Network bandwidth: не должна быть узким местом

Процесс проведения load testing

Фаза 1: Подготовка

  • Выбрать инструмент (JMeter, Gatling, etc.)
  • Определить сценарии (какие endpoint'ы тестировать)
  • Подготовить тестовую среду (staging, near-prod)
  • Установить базовые метрики и целевые значения

Фаза 2: Рамп-ап (Ramp-up)

Постепенное увеличение нагрузки:
- 0-5 мин: 0 → 100 пользователей
- 5-15 мин: 100 → 500 пользователей
- 15-25 мин: 500 → 1000 пользователей

Фаза 3: Стабилизация (Stabilization)

Поддержание постоянной нагрузки:
- 25-35 мин: 1000 пользователей (constant)
- Сбор данных для анализа

Фаза 4: Рамп-даун (Ramp-down)

Плавное снижение нагрузки:
- 35-40 мин: 1000 → 0 пользователей

Фаза 5: Анализ

  • Построить графики (response time, throughput, error rate)
  • Выявить bottlenecks
  • Предложить оптимизации

Типичные проблемы и их решения

Проблема 1: High Response Time

Причины:

  • Недостаточный размер database connection pool
  • N+1 query проблема
  • Отсутствие кеширования
  • Неоптимизированные SQL запросы

Решения:

// HikariCP конфигурация
DataSource dataSource = new HikariDataSource();
((HikariDataSource) dataSource).setMaximumPoolSize(20);
((HikariDataSource) dataSource).setMinimumIdle(5);
((HikariDataSource) dataSource).setConnectionTimeout(30000);
((HikariDataSource) dataSource).setIdleTimeout(600000);
((HikariDataSource) dataSource).setMaxLifetime(1800000);

// Или в application.yml
spring:
  datasource:
    hikari:
      maximum-pool-size: 20
      minimum-idle: 5
      connection-timeout: 30000
      idle-timeout: 600000
      max-lifetime: 1800000

Проблема 2: Memory Leak

Признаки:

  • Возрастающее потребление памяти
  • Частые GC pauses
  • OutOfMemoryError

Инструменты для анализа:

  • JProfiler
  • YourKit
  • Heap dumps + Eclipse MAT

Проблема 3: Database Bottleneck

Решения:

  • Добавить индексы
  • Оптимизировать запросы (EXPLAIN ANALYZE)
  • Увеличить connection pool
  • Добавить кеширование (Redis)
  • Replicate базу данных

Выводы

Нагрузочное тестирование — это обязательный этап для production приложений:

  • Выявляет проблемы до production
  • Помогает оптимизировать архитектуру
  • Предотвращает outages при peak load
  • Даёт данные для scaling decisions

Опыт проведения load tests помог мне создавать приложения, которые стабильно работают при высоких нагрузках и готовы к масштабированию.

Проводил ли тестирование на стенде нагрузочного тестирования | PrepBro