← Назад к вопросам
Как определить причину замедления системы при увеличенном трафике?
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 Leak | Heap растет, GC не помогает | Профайл память, найти утечку |
| N+1 Queries | DB load высокий | Добавить batch fetch, JOIN |
| Нет индексов | Медленные запросы | EXPLAIN ANALYZE, добавить индексы |
| Thread pool exhaustion | Очередь растет, timeout | Увеличить pool size |
| Deadlock | Потоки BLOCKED | Анализ thread dump |
| GC паузы | Большие паузы, full GC | Настроить heap size, GC algo |
| Network bottleneck | Latency растет | Проверить пропускную способность |
| Неэффективный алгоритм | 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());
}
}
Контрольный список
- Проверьте CPU, память, диск, сеть
- Включите GC логирование и проанализируйте
- Используйте JFR или async-profiler
- Проанализируйте медленные запросы к БД
- Проверьте thread dump на deadlocks
- Запустите нагрузочное тестирование
- Измеряйте эффект каждого изменения
Важные моменты
- Не рассчитывайте на везение — используйте инструменты
- Измеряйте перед и после изменений
- Оптимизируйте в порядке приоритета:
- IO (БД, сеть)
- Алгоритмы
- JVM tuning
- Кэширование