Диагностика высокой нагрузки CPU и памяти¶
«Сервер тормозит» — это не диагноз, а отправная точка. Эта статья — о стандартном наборе инструментов, позволяющем узнать, что именно потребляет CPU, память или I/O, по порядку, а не угадывая.
Как это устроено¶
Начните с top (или htop), но читайте его правильно¶
$ top -b -n 1 | head -15
top - 14:22:01 up 12 days, 3:41, 2 users, load average: 2.14, 1.98, 1.76
Tasks: 210 total, 2 running, 208 sleeping, 0 stopped, 0 zombie
%Cpu(s): 12.3 us, 4.1 sy, 0.0 ni, 81.9 id, 1.2 wa, 0.0 hi, 0.5 si, 0.0 st
MiB Mem : 16024.0 total, 528.0 free, 9216.0 used, 6280.0 buff/cache
MiB Swap: 8192.0 total, 3382.0 free, 4810.0 used. 6102.0 avail Mem
Load average — это число процессов готовых к выполнению или ожидающих непрерываемого I/O, усреднённое за 1/5/15 минут — это не процент. Load average 2.14 на 4-ядерной машине означает, что система загружена примерно вполовину от своего потолка; та же 2.14 на 1-ядерной машине означает больше чем двойную перегрузку.
Разбивка %Cpu(s) важнее единственного числа нагрузки: us (пользовательские процессы), sy (ядро/системные вызовы), wa (ожидание I/O — высокий wa при низких us/sy указывает на узкое место именно в хранилище, а не в CPU, хотя top и «инструмент по CPU»), si/hi (программные/аппаратные прерывания).
available память, а не free, — то число, которое реально важно. Linux агрессивно использует свободную RAM под дисковый кэш (buff/cache), потому что неиспользуемая RAM — потраченная впустую RAM — этот кэш мгновенно высвобождается, если приложению понадобится память. Система, показывающая «528MB free», но «6GB available», не испытывает нехватки памяти — она эффективно использует RAM.
vmstat для трендов во времени¶
$ vmstat 1 5
procs -----------memory---------- ---swap-- -----io---- -system-- ------cpu-----
r b swpd free buff cache si so bi bo in cs us sy id wa st
1 0 3485536 528292 1293700 5136604 1 2 175 1239 2 1 9 6 76 5 5
0 0 3485536 525352 1293704 5136692 0 0 0 7672 5709 9402 3 3 89 6 0
(vmstat 1 5 выводит раз в секунду, 5 раз.) Колонки, за которыми стоит следить:
r— процессы, реально выполняющиеся или готовые к выполнению прямо сейчас, конкурирующие за CPU. Если это число стабильно больше числа ядер — у вас реальная конкуренция за CPU.b— процессы заблокированные, непрерываемо ожидающие (почти всегда дисковый I/O).si/so— своп в/из. Любой устойчивый ненулевойsoозначает, что система активно выгружает память на диск — сильный сигнал реального давления на память, отличный от просто «мало свободной памяти» (которая, как выше, часто в порядке).
Поиск конкретного виновника¶
ps aux --sort=-%cpu | head -10 # топ потребителей CPU
ps aux --sort=-%mem | head -10 # топ потребителей памяти
pidstat 1 5 # CPU по процессам во времени (нужен пакет sysstat)
Сужение именно до ожидания I/O¶
Колонка %util по устройству — ключевая: близко к 100% означает, что именно это устройство — узкое место, независимо от того, насколько «простаивающим» выглядит CPU в top.
Когда нужно глубже: perf¶
sudo apt install linux-tools-common linux-tools-$(uname -r) # Debian/Ubuntu
sudo perf top # живое профилирование CPU на уровне символов
perf top показывает, какие именно функции (ядра или пользовательского пространства, если у бинарника есть символы) потребляют циклы CPU прямо сейчас — следующий уровень вглубь от «какой процесс» к «какая функция внутри этого процесса».
Различия Ubuntu/Debian и RHEL-подобных систем¶
top, vmstat, ps, free — часть procps, идентичны везде. pidstat/iostat приходят из пакета sysstat в обеих семьях, под теми же именами. Имя пакета для установки perf отличается (linux-tools-<версия-ядра> на Debian/Ubuntu против perf напрямую на RHEL-семействе), но использование идентично после установки.
Практическое задание¶
- Создайте искусственную нагрузку на CPU безопасным способом через
yes > /dev/null &(направляет бесконечный поток символовyв никуда, забивая одно ядро) и понаблюдайте за ней вtop— найдите её PID. - Убедитесь через
ps aux --sort=-%cpu | head -5, что тот же процесс наверху. - Завершите его (
kill <PID>) и убедитесь, что нагрузка возвращается к базовому уровню в течение нескольких секунд черезvmstat 1 5.
Как проверить, что всё сделано правильно¶
- Показатель
usв%Cpu(s)top должен подскочить примерно до100/<число ядер>% пока работает процессyes(например, ~25% на 4-ядерной машине для одного такого процесса), и процесс должен быть виден наверхуps aux --sort=-%cpu. - После
killколонкаrвvmstatдолжна вернуться к прежнему базовому уровню в течение пары секунд.
Типичные ошибки¶
- Трактовка
freeпамяти как важной метрики. Погоня за «почему так мало свободной памяти» на системе Linux, которая на самом деле здорова (высокийbuff/cache, высокийavailable) — очень частый паттерн впустую потраченных усилий. - Диагностика «высокой нагрузки» как «высокой загрузки CPU» без проверки
wa. Load average 8 при 90%waи 5%us— это проблема I/O, не CPU — добавление ядер CPU тут не поможет. - Использование единственного снимка
topвместо наблюдения за ним (илиvmstat) во времени. Кратковременные всплески выглядят идентично устойчивым проблемам в одном снимке.
⚠ Опасные команды¶
kill -9(SIGKILL) для процесса, держащего блокировку БД или находящегося посреди записи, может повредить данные — предпочитайте штатныйkill(SIGTERM, по умолчанию) или собственный механизм остановки приложения сначала, оставляя-9для процессов, реально не отвечающих на SIGTERM.- Запуск инструментов нагрузочного тестирования (вроде
stressили цикла, забивающего CPU, как в задании выше) прямо на продакшн-системе, без предварительного подтверждения, что у вас есть безопасный способ его остановить, может вызвать реальный простой — всегда держите наготове командуkillв другом окне перед стартом.
Связанные статьи¶
Контрольные вопросы¶
- Почему система может показывать очень мало «свободной» памяти и при этом быть совершенно здоровой?
- На что указывает высокий процент
waв top, и почему добавление ядер CPU это не исправит? - В чём разница между колонками
rиbв выводеvmstat? - Почему одного снимка
topнедостаточно для диагностики перемежающейся проблемы производительности?