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

Как определить причину замедления системы при увеличенном трафике?

2.0 Middle🔥 141 комментариев
#Другое

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

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

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

Как определить причину замедления системы при увеличенном трафике

Систематический подход к диагностике

Замедление под нагрузкой может быть вызвано многими причинами. Нужно провести систематическое расследование:

Шаг 1: Мониторинг системных ресурсов

Сначала проверьте базовые метрики:

# CPU утилизация
top
htop
ps aux --sort=-%cpu | head -10

# Память
free -h
wmem
ps aux --sort=-%mem | head -10

# Диск
df -h
iostat -x 1

# Сетевое соединение
netstat -an | grep ESTABLISHED | wc -l
ss -s

Что ищем:

  • CPU 100% → проблема в коде приложения
  • Memory swap > 0 → недостаточно RAM
  • Disk I/O утилизация высокая → проблемы с БД или файловой системой
  • Network connections растут → memory leak в приложении

Шаг 2: Анализ JVM метрик

// Получить информацию о JVM
Runtime runtime = Runtime.getRuntime();
long maxMemory = runtime.maxMemory() / 1024 / 1024;  // МБ
long totalMemory = runtime.totalMemory() / 1024 / 1024;
long freeMemory = runtime.freeMemory() / 1024 / 1024;
long usedMemory = totalMemory - freeMemory;

System.out.println("Max: " + maxMemory + "MB");
System.out.println("Total: " + totalMemory + "MB");
System.out.println("Used: " + usedMemory + "MB");
System.out.println("Free: " + freeMemory + "MB");

Строка запуска JVM с логами:

java -Xmx4g -Xms4g \
  -XX:+PrintGCDetails \
  -XX:+PrintGCDateStamps \
  -XX:+PrintGCTimeStamps \
  -Xloggc:gc.log \
  -XX:+UnlockDiagnosticVMOptions \
  -XX:G1SummarizeRSetStatsPeriod=1 \
  -jar application.jar

Анализируйте gc.log:

  • Если GC паузы часты и долгие → проблема с heap
  • Если Old generation быстро растет → memory leak

Шаг 3: Профилирование приложения

3.1 JFR (Java Flight Recorder) — встроенный профайлер

# Запустить приложение с JFR
java -XX:StartFlightRecording=duration=60s,filename=recording.jfr -jar app.jar

# Открыть в JDK Mission Control
jmc recording.jfr

Что анализировать:

  • Hot methods — какие методы потребляют CPU
  • Memory allocation — какие объекты создаются
  • Thread analysis — deadlocks или blocked потоки
  • I/O analysis — долгие операции с файлами/сетью

3.2 async-profiler

# Установка
wget https://github.com/async-profiler/async-profiler/releases/download/v3.0/async-profiler-3.0-linux-x64.tar.gz
tar xzf async-profiler-3.0-linux-x64.tar.gz

# Запуск профилирования
./profiler.sh -d 30 -f /tmp/profile.html PID

# Анализ горячих методов
./profiler.sh -d 30 -o flamegraph -f /tmp/flamegraph.html PID

Шаг 4: Анализ логов приложения

// Добавить логирование с временем выполнения
import lombok.extern.slf4j.Slf4j;

@Slf4j
public class PerformanceMonitor {
    public static void main(String[] args) {
        long startTime = System.nanoTime();
        
        // Ваш код
        performDatabaseQuery();
        
        long elapsedTime = System.nanoTime() - startTime;
        log.info("Выполнено за {} мс", elapsedTime / 1_000_000);
    }
}

Что ищем в логах:

  • Медленные запросы к БД
  • Ошибки соединения
  • Thread pool exhaustion
  • Частые исключения

Шаг 5: Анализ БД

-- PostgreSQL: найти медленные запросы
SELECT query, mean_time, stddev_time, calls 
FROM pg_stat_statements 
ORDER BY mean_time DESC 
LIMIT 10;

-- MySQL: включить slow query log
SET GLOBAL slow_query_log = 'ON';
SET GLOBAL long_query_time = 0.5;

-- Анализ индексов
EXPLAIN SELECT * FROM users WHERE id = 123;
EXPLAIN ANALYZE SELECT * FROM large_table WHERE condition = true;

Типичные проблемы:

  • Отсутствие индексов
  • N+1 queries (запрос за каждую строку)
  • Невидимые левые джойны
  • Блокировки

Шаг 6: Анализ потоков

# Получить thread dump
jps -l  # Найти PID Java процесса
jstack PID > threads.txt

# Анализ
grep "java.lang.Thread.State" threads.txt | sort | uniq -c

Что ищем:

  • BLOCKED потоки → deadlock
  • WAITING потоки → ждут lock или condition
  • RUNNABLE потоки → нормально
// Программно вывести информацию о потоках
ThreadMXBean threadMXBean = ManagementFactory.getThreadMXBean();
long[] threadIds = threadMXBean.getAllThreadIds();

for (long threadId : threadIds) {
    ThreadInfo threadInfo = threadMXBean.getThreadInfo(threadId);
    System.out.println(threadInfo.getThreadName() + ": " + 
                      threadInfo.getThreadState());
    
    // Проверка deadlock
    long[] deadlockedThreads = threadMXBean.findDeadlockedThreads();
    if (deadlockedThreads != null) {
        System.out.println("DEADLOCK DETECTED!");
    }
}

Шаг 7: Нагрузочное тестирование

# Apache JMeter
jmeter -n -t test.jmx -l results.jtl -j jmeter.log

# Apache Bench
ab -n 10000 -c 100 http://localhost:8080/api/endpoint

# wrk
wrk -t12 -c400 -d30s http://localhost:8080/

Анализируйте:

  • Response time (p50, p95, p99)
  • Throughput (requests per second)
  • Error rate
  • GC pauses during test

Шаг 8: Типичные причины и решения

ПричинаПризнакиРешение
Memory LeakHeap растет, GC не помогаетПрофайл память, найти утечку
N+1 QueriesDB load высокийДобавить batch fetch, JOIN
Нет индексовМедленные запросыEXPLAIN ANALYZE, добавить индексы
Thread pool exhaustionОчередь растет, timeoutУвеличить pool size
DeadlockПотоки BLOCKEDАнализ thread dump
GC паузыБольшие паузы, full GCНастроить heap size, GC algo
Network bottleneckLatency растетПроверить пропускную способность
Неэффективный алгоритмCPU 100%Профайл, оптимизировать код

Пример полной диагностики

@Slf4j
public class PerformanceDiagnostics {
    public void diagnoseSlowness() {
        // 1. Системные ресурсы
        Runtime runtime = Runtime.getRuntime();
        log.info("Memory: {}/{} MB", 
            (runtime.totalMemory() - runtime.freeMemory()) / 1024 / 1024,
            runtime.maxMemory() / 1024 / 1024);
        
        // 2. GC информация
        MemoryMXBean memBean = ManagementFactory.getMemoryMXBean();
        log.info("Heap: {}", memBean.getHeapMemoryUsage());
        log.info("Non-heap: {}", memBean.getNonHeapMemoryUsage());
        
        // 3. Потоки
        ThreadMXBean threadBean = ManagementFactory.getThreadMXBean();
        log.info("Thread count: {}", threadBean.getThreadCount());
        
        // 4. Классы
        ClassLoadingMXBean classBean = ManagementFactory.getClassLoadingMXBean();
        log.info("Loaded classes: {}", classBean.getLoadedClassCount());
    }
}

Контрольный список

  1. Проверьте CPU, память, диск, сеть
  2. Включите GC логирование и проанализируйте
  3. Используйте JFR или async-profiler
  4. Проанализируйте медленные запросы к БД
  5. Проверьте thread dump на deadlocks
  6. Запустите нагрузочное тестирование
  7. Измеряйте эффект каждого изменения

Важные моменты

  • Не рассчитывайте на везение — используйте инструменты
  • Измеряйте перед и после изменений
  • Оптимизируйте в порядке приоритета:
    1. IO (БД, сеть)
    2. Алгоритмы
    3. JVM tuning
    4. Кэширование
Как определить причину замедления системы при увеличенном трафике? | PrepBro