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

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

1.0 Junior🔥 71 комментариев
#Тестирование

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

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

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

# Нагрузочное тестирование (Load Testing)

Нагрузочное тестирование — это вид тестирования производительности, направленный на определение поведения системы при нормальных и пиковых нагрузках. Это тестирование проверяет, как система справляется с предполагаемым количеством пользователей и запросов.

Основные цели

  1. Выявить узкие места — какие компоненты медленнее всего
  2. Измерить метрики производительности — время отклика, пропускная способность
  3. Проверить стабильность — система остаётся стабильной при длительной нагрузке
  4. Определить максимальные возможности — при какой нагрузке система начинает деградировать
  5. Оптимизировать ресурсы — сколько серверов нужно для поддержки нагрузки

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

1. Load Test (базовое нагрузочное тестирование)

Количество пользователей
     ^
     |
100  |        ___________
     |       /
50   |      /
     |_____/________________> Время

Система получает постоянную нагрузку (например, 100 пользователей одновременно).

2. Stress Test (стресс-тестирование)

Количество пользователей
     ^
     |                /
500  |               / \
     |              /   \
250  |_____________/     \___ система падает
     |________________________> Время

Нагрузка плавно увеличивается до тех пор, пока система не упадёт.

3. Soak Test (долговременное тестирование)

Система работает под постоянной умеренной нагрузкой длительное время (часы, дни).

4. Spike Test (пиковое тестирование)

Количество пользователей
     ^
     |    |      |      |
200  |    |      |      |
     | ___|______|______|___ > Время
100  |/

Резкие скачки нагрузки, как во время черной пятницы.

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

JMeter (Apache JMeter)

// Симуляция через GUI или в коде
public class JMeterExample {
    public static void main(String[] args) throws Exception {
        // Создание плана тестирования
        // - Thread Group с 100 потоками
        // - HTTP Request Sampler
        // - Listeners для сбора результатов
    }
}

Gatling (для Java/Scala)

import io.gatling.core.Predef._
import io.gatling.http.Predef._

class UserSimulation extends Simulation {
  val httpProtocol = http
    .baseUrl("http://localhost:8080")
    .acceptHeader("application/json")

  val scn = scenario("Users")
    .exec(http("get users")
      .get("/api/users")
      .check(status.is(200)))

  // 100 пользователей, увеличение на 10 каждую секунду
  setUp(
    scn.inject(
      rampUsers(100) during (10 seconds)
    ).protocols(httpProtocol)
  )
}

Spring Boot в тестах

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.web.servlet.MockMvc;

@SpringBootTest
@AutoConfigureMockMvc
public class LoadTestExample {
    @Autowired
    private MockMvc mockMvc;
    
    @Test
    public void loadTestGetUsers() throws Exception {
        // Симуляция 1000 запросов
        for (int i = 0; i < 1000; i++) {
            mockMvc.perform(get("/api/users")
                .param("page", "1")
                .param("size", "10"))
                .andExpect(status().isOk());
        }
    }
}

Пример нагрузочного теста с JUnit и многопоточностью

import org.junit.jupiter.api.Test;
import java.util.concurrent.*;

public class LoadTestingExample {
    private static final int NUM_THREADS = 100;
    private static final int REQUESTS_PER_THREAD = 100;
    private UserService userService;
    
    @Test
    public void loadTestUserService() throws InterruptedException {
        ExecutorService executor = Executors.newFixedThreadPool(NUM_THREADS);
        CountDownLatch latch = new CountDownLatch(NUM_THREADS);
        long startTime = System.currentTimeMillis();
        
        for (int i = 0; i < NUM_THREADS; i++) {
            executor.submit(() -> {
                try {
                    for (int j = 0; j < REQUESTS_PER_THREAD; j++) {
                        User user = userService.getUserById(1L);
                        assertNotNull(user);
                    }
                } finally {
                    latch.countDown();
                }
            });
        }
        
        // Ждём завершения всех потоков
        latch.await(10, TimeUnit.MINUTES);
        executor.shutdown();
        
        long endTime = System.currentTimeMillis();
        long totalTime = endTime - startTime;
        long totalRequests = (long) NUM_THREADS * REQUESTS_PER_THREAD;
        
        System.out.println("Total Requests: " + totalRequests);
        System.out.println("Total Time: " + totalTime + "ms");
        System.out.println("Requests/sec: " + (totalRequests * 1000 / totalTime));
    }
}

Метрики для анализа

МетрикаОписаниеПример
Response TimeВремя ответа (min, avg, max, p95, p99)avg: 150ms, p99: 500ms
ThroughputЗапросов в секунду1000 req/sec
Error RateПроцент ошибок0.5% ошибок
CPU UsageЗагруженность процессора85%
Memory UsageИспользование памяти2GB из 4GB
Connection PoolСостояние пула соединений95/100 active
Database ConnectionsСоединения к БД80/100

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

public class LoadTestResultsAnalysis {
    private List<Long> responseTimes = new ArrayList<>();
    
    public void analyzeResults() {
        Collections.sort(responseTimes);
        
        long min = responseTimes.get(0);
        long max = responseTimes.get(responseTimes.size() - 1);
        long avg = responseTimes.stream()
            .mapToLong(Long::longValue)
            .average()
            .orElse(0);
        
        // Percentiles
        int p95Index = (int) (responseTimes.size() * 0.95);
        int p99Index = (int) (responseTimes.size() * 0.99);
        
        long p95 = responseTimes.get(p95Index);
        long p99 = responseTimes.get(p99Index);
        
        System.out.println("Min: " + min + "ms");
        System.out.println("Max: " + max + "ms");
        System.out.println("Avg: " + avg + "ms");
        System.out.println("P95: " + p95 + "ms");
        System.out.println("P99: " + p99 + "ms");
    }
}

Шаги проведения нагрузочного теста

  1. Определить требования — сколько пользователей, какие сценарии
  2. Подготовить тестовое окружение — как можно ближе к production
  3. Создать тест-сценарии — реалистичные пути пользователей
  4. Запустить базовый тест — установить baseline
  5. Увеличивать нагрузку — постепенно добавлять пользователей
  6. Собирать метрики — время ответа, ошибки, ресурсы
  7. Анализировать результаты — выявить узкие места
  8. Оптимизировать — исправить проблемы
  9. Повторить тесты — убедиться в улучшении

Рекомендации

  • Тестируй в окружении, приближенном к production
  • Используй реалистичные данные
  • Проводи несколько прогонов для стабильных результатов
  • Мониторь не только приложение, но и сервер (CPU, memory, I/O)
  • Начни с простых сценариев, постепенно их усложняй

Нагрузочное тестирование — критически важно для обеспечения надёжности и масштабируемости приложения.