Зачем нужна количественная оценка производительности при обновлениях
Обновление ядра Linux с 5.15 до 6.1 снизило IOPS случайного чтения на 18% на тестовом стенде с NVMe-диском. Причина - изменение параметров планировщика ввода-вывода по умолчанию. Без цифр администратор заметил бы проблему только через недели, когда пользователи начали бы жаловаться на «тормоза». Субъективное восприятие - плохой советчик. «Медленнее» или «быстрее» без цифр - это мнение, а не факт. Количественная оценка переводит разговор в плоскость измеряемых величин: запросов в секунду, миллисекунд задержки, мегабайт пропускной способности.
Методология базируется на создании baseline - эталонного замера производительности до внесения изменений. Baseline фиксирует состояние системы в конкретной точке: версии пакетов, конфигурационные файлы, метрики под нагрузкой. После обновления вы повторяете тесты в тех же условиях и сравниваете цифры. Отклонение более 5% - повод для расследования.
Методика применима к любому компоненту стека: обновление ОС, переход на новую версию PostgreSQL или MySQL, смена веб-сервера с Nginx 1.24 на 1.26, замена SATA SSD на NVMe. В каждом случае вы получаете объективный ответ: стало лучше, хуже или без изменений. Это основа для принятия решения - внедрять обновление в продакшен или откатывать.
Риски обновлений без замеров реальны. Патч безопасности может включить программную защиту от Spectre/Meltdown, которая режет производительность CPU на 5-15%. Новая версия СУБД меняет план выполнения запросов - и время ответа API вырастает с 50 до 200 мс. Без baseline вы теряете точку отсчета и не можете доказать, что проблема именно в обновлении. Подробнее о типичных сценариях деградации и методах восстановления - в статье про восстановление производительности после обновлений.
Методология нагрузочного тестирования: от baseline до сравнения
Методология состоит из шести этапов. Каждый обязателен - пропуск любого шага ставит под сомнение достоверность результата.
- Определение целевых метрик. Выбираете, что измеряете: задержку (latency), пропускную способность (throughput), количество операций в секунду (IOPS). Набор метрик зависит от подсистемы, которую обновляете.
- Создание идентичных условий. Фиксируете версии пакетов, конфигурационные файлы, параметры тестовой нагрузки. Отключаете фоновые задачи - cron, systemd timers, агенты мониторинга.
- Снятие baseline-замеров. Прогоняете тесты минимум три раза, усредняете результаты. Сохраняете полный вывод инструментов в отдельный файл.
- Проведение обновления. Устанавливаете новые пакеты, меняете конфигурацию, перезагружаете сервис.
- Повторные замеры. Запускаете те же тесты с теми же параметрами. Прогоняете трижды, усредняете.
- Сравнение и анализ отклонений. Вычисляете процент расхождения по каждой метрике. При падении более 5% ищете причину.
Три прогона - минимум. Одиночный замер может попасть на пик фоновой активности и исказить картину. Усреднение сглаживает случайные выбросы. Результаты сохраняйте в текстовые файлы с датой и версией ПО в имени - это упростит анализ через полгода, когда понадобится сравнить не два, а пять последовательных обновлений.
Какие метрики собирать и как их интерпретировать
Метрики делятся по подсистемам. Для каждой есть ключевой показатель и допустимый порог отклонения после обновления.
| Подсистема | Ключевая метрика | Инструмент | Допустимое отклонение |
|---|---|---|---|
| CPU | events per second, задержка (95-й перцентиль) | sysbench cpu | <5% |
| Память | пропускная способность, MiB/sec | sysbench memory | <5% |
| Диски | IOPS, задержка (clat), пропускная способность | fio | <10% для задержки, <5% для IOPS |
| Сеть/HTTP | запросы в секунду, задержка, p99 | wrk | <5% |
Для CPU важен не только средний показатель events per second, но и распределение задержек. Среднее может остаться прежним, а 99-й перцентиль - вырасти вдвое. Это означает, что 1% запросов обрабатывается значительно медленнее. В веб-приложениях такие выбросы приводят к таймаутам и ошибкам 502/504.
Для дисковой подсистемы порог по задержке выше - 10%. Дисковый ввод-вывод чувствителен к состоянию кеша страниц, фрагментации и фоновым процессам вроде journald. Если задержка выросла на 7%, а IOPS упали на 2%, это повод перепроверить тест, но не причина для отката обновления. Если задержка выросла на 25% - откатывайте и разбирайтесь.
Базовые метрики CPU, памяти, дисков и сети, которые нужно отслеживать в операционной системе до и во время тестов, разобраны в руководстве по мониторингу производительности сервера. Там же - пороговые значения для top, iostat и ss.
Обеспечение воспроизводимости: контроль среды и фоновых процессов
Главный враг воспроизводимости - неконтролируемая фоновая активность. Вот что нужно сделать перед каждым тестом.
Отключите cron и systemd timers. Команда systemctl stop cron (или crond) и systemctl mask cron предотвратит запуск периодических задач во время теста. Не забудьте вернуть обратно: systemctl unmask cron && systemctl start cron.
Остановите агенты мониторинга. Zabbix Agent, Node Exporter, Telegraf потребляют CPU и генерируют дисковый ввод-вывод. systemctl stop zabbix-agent node_exporter telegraf.
Зафиксируйте версии ПО. Сохраните вывод dpkg -l или rpm -qa в файл. После обновления вы точно будете знать, какие пакеты изменились.
Используйте одинаковые файлы-образы для fio. Если тестируете диск, создайте файл фиксированного размера до теста: fio --filename=testfile --size=10G --rw=write --bs=1M --numjobs=1 --iodepth=1 --end_fsync=1 --name=prepare. Этот же файл используйте для всех последующих тестов.
Документируйте условия. Записывайте: версию ядра (uname -r), модель CPU (lscpu), объем памяти (free -h), модель диска (lsblk -o NAME,MODEL,SIZE), версии ключевых пакетов. Через три месяца вы не вспомните, на каком ядре снимали baseline.
Инструменты бенчмаркинга: sysbench, fio и wrk
Три инструмента покрывают основные подсистемы сервера. sysbench - CPU, память и базы данных. fio - дисковая подсистема. wrk - HTTP-серверы. Каждый дает воспроизводимую нагрузку и численные метрики.
sysbench: тестирование CPU, памяти и баз данных
Установка на Debian/Ubuntu: apt install sysbench. На RHEL/CentOS: yum install sysbench (требуется EPEL).
Тест CPU. sysbench вычисляет простые числа до заданного лимита. Это чистая арифметическая нагрузка без обращения к памяти и диску. Команда:
sysbench cpu --cpu-max-prime=20000 --threads=4 run
Параметр --cpu-max-prime задает верхнюю границу поиска простых чисел. Чем выше значение, тем дольше тест. --threads=4 загружает 4 ядра. Ключевая метрика в выводе - events per second. Это количество вычислений в секунду. Выше - лучше. Также смотрите latency - общее время выполнения одного события (вычисления).
Пример вывода:
CPU speed:
events per second: 1245.32
General statistics:
total time: 10.0004s
total number of events: 12456
Latency (ms):
min: 3.12
avg: 3.21
max: 5.43
95th percentile: 3.45
Тест памяти. Измеряет пропускную способность при чтении и записи блоков разного размера:
sysbench memory --memory-block-size=1M --memory-total-size=10G run
Метрика - MiB transferred per second. Сравнивайте до и после обновления.
Тест базы данных. sysbench умеет генерировать OLTP-нагрузку на MySQL и PostgreSQL. Перед тестом нужно подготовить таблицы:
sysbench oltp_read_write --db-driver=mysql --mysql-host=localhost --mysql-user=root --mysql-password=pass --mysql-db=testdb --tables=4 --table-size=100000 prepare
Затем запустить тест:
sysbench oltp_read_write --db-driver=mysql --mysql-host=localhost --mysql-user=root --mysql-password=pass --mysql-db=testdb --tables=4 --table-size=100000 --threads=8 --time=60 run
Ключевые метрики: transactions per second (TPS), queries per second (QPS), задержка на уровне 95-го перцентиля. После завершения теста очистите таблицы: sysbench ... cleanup.
fio: гибкая оценка дисковой подсистемы
fio (Flexible I/O Tester) - стандарт для бенчмаркинга дисков. Установка: apt install fio или yum install fio.
fio моделирует различные паттерны ввода-вывода через параметры:
--rw- тип нагрузки:read(последовательное чтение),write(последовательная запись),randread(случайное чтение),randwrite(случайная запись),randrw(смешанная случайная нагрузка);--bs- размер блока:4kимитирует нагрузку баз данных,1M- потоковое чтение/запись;--iodepth- глубина очереди ввода-вывода: 1 для одиночных запросов, 32-64 для серверных нагрузок;--numjobs- количество параллельных потоков.
Тест случайного чтения блоками 4k (типичная нагрузка PostgreSQL):
fio --filename=testfile --size=10G --rw=randread --bs=4k --iodepth=32 --numjobs=4 --runtime=60 --time_based --group_reporting --name=randread
Разбор параметров: файл 10G создается заранее (см. раздел про воспроизводимость), случайное чтение блоками по 4 килобайта, глубина очереди 32, четыре параллельных потока, тест длится 60 секунд.
Ключевые метрики в выводе:
read: IOPS=245k, BW=957MiB/s (1004MB/s)(56.1GiB/60001msec)
clat (usec): min=12, max=1023, avg=45.32, stdev=12.45
lat (usec): min=12, max=1023, avg=45.40, stdev=12.46
IOPS - операции ввода-вывода в секунду. BW - пропускная способность. clat (completion latency) - время от отправки запроса до его завершения подсистемой ввода-вывода. Это главная метрика для оценки отзывчивости диска. lat включает еще и время в очереди.
Тест последовательного чтения блоками 1M (потоковая нагрузка):
fio --filename=testfile --size=10G --rw=read --bs=1M --iodepth=16 --numjobs=1 --runtime=60 --time_based --group_reporting --name=seqread
Здесь важен BW - сколько мегабайт в секунду диск способен выдать при линейном чтении.
wrk: нагрузочное тестирование HTTP-серверов
wrk - легковесный генератор HTTP-нагрузки. Установка из исходников: git clone https://github.com/wg/wrk && cd wrk && make && cp wrk /usr/local/bin/. Требуются пакеты build-essential и libssl-dev.
Параметры:
-t- количество потоков (обычно равно числу ядер CPU);-c- количество одновременных HTTP-соединений;-d- длительность теста (например,30s);--latency- выводить распределение задержек.
Базовый тест Nginx на локальном хосте:
wrk -t4 -c100 -d30s --latency http://localhost/
4 потока, 100 одновременных соединений, тест 30 секунд. Вывод:
Running 30s test @ http://localhost/
4 threads and 100 connections
Thread Stats Avg Stdev Max +/- Stdev
Latency 1.23ms 456.78us 12.34ms 85.23%
Req/Sec 20.12k 1.45k 25.67k 72.10%
Latency Distribution
50% 1.12ms
75% 1.45ms
90% 1.89ms
99% 3.45ms
2410234 requests in 30.02s, 1.92GB read
Requests/sec: 80291.23
Transfer/sec: 65.45MB
Главная метрика - Requests/sec. Это количество HTTP-запросов, которое сервер способен обработать за секунду при заданном уровне параллелизма. Latency Distribution показывает задержку на разных перцентилях. 99-й перцентиль (p99) критичен - если он вырос с 3 до 50 мс после обновления, 1% пользователей получает заметную задержку.
Для нагрузочного тестирования веб-приложений и сравнения разных сред выполнения полезно ознакомиться с объективными тестами Docker, Kubernetes и LXC, где разобраны накладные расходы каждой технологии.
Пошаговый алгоритм: от подготовки до принятия решения
Разберем конкретный сценарий: обновление Nginx с версии 1.24 до 1.26 на сервере под управлением Ubuntu 22.04. Алгоритм универсален и применим к любому компоненту.
Шаг 1. Фиксируем текущее состояние.
nginx -v > baseline_nginx_version.txt
cp /etc/nginx/nginx.conf baseline_nginx.conf
cp -r /etc/nginx/sites-available baseline_sites/
Шаг 2. Отключаем фоновые процессы.
systemctl stop cron
systemctl stop zabbix-agent
Шаг 3. Снимаем baseline wrk. Тестируем трижды с паузой 10 секунд между прогонами:
for i in 1 2 3; do
wrk -t4 -c100 -d30s --latency http://localhost/ > baseline_wrk_run_$i.txt
sleep 10
done
Усредняем Requests/sec из трех файлов. Допустим, получили 80291, 79800, 80450. Среднее: 80180 req/sec.
Шаг 4. Обновляем Nginx.
apt update && apt install -y nginx
Проверяем, что конфигурация не перезаписалась:
diff baseline_nginx.conf /etc/nginx/nginx.conf
Шаг 5. Повторяем тесты. Те же три прогона с теми же параметрами. Получаем: 76500, 76100, 76300. Среднее: 76300 req/sec.
Шаг 6. Сравниваем. Падение: (80180 - 76300) / 80180 * 100% = 4.8%. Это в пределах допустимых 5%. Обновление можно оставлять.
Если бы падение составило 12%, алгоритм действий такой: проверить changelog Nginx на предмет изменений в дефолтных параметрах (worker_connections, keepalive_timeout, sendfile), сравнить системные логи на предмет ошибок, при необходимости откатить пакет через apt install nginx=1.24.0-....
Для CPU и дисков алгоритм аналогичен. Для CPU используете sysbench cpu, для дисков - fio с профилем, соответствующим вашей нагрузке. Все результаты сохраняете в директорию с датой и версией ПО.
Анализ результатов и типичные проблемы после обновления
Самые частые причины падения производительности после обновлений:
- Смена планировщика ввода-вывода. Ядро 6.1+ переключило планировщик по умолчанию с mq-deadline на kyber. Для NVMe это дало прирост, для SATA SSD - падение на 10-15% при смешанной нагрузке. Проверьте:
cat /sys/block/sda/queue/scheduler. Вернуть можно черезecho mq-deadline > /sys/block/sda/queue/scheduler. - Новые параметры TCP по умолчанию. Изменение
tcp_congestion_controlили размера буферов влияет на пропускную способность сети. Проверьте черезsysctl net.ipv4.tcp_congestion_control. - Митигации уязвимостей CPU. Обновление микрокода или ядра может включить защиту от Spectre/Meltdown/Downfall. Проверьте:
grep . /sys/devices/system/cpu/vulnerabilities/*. Еслиmitigationпоявилось там, где раньше былоnot affected- это причина падения производительности CPU. - Изменение конфигурации по умолчанию. Пакетный менеджер мог заменить ваш конфигурационный файл на новый с другими параметрами. Всегда делайте diff до и после обновления.
Системные логи - первый источник для диагностики. journalctl -xe -p 3 покажет ошибки за последний час. dmesg -T | tail -50 - сообщения ядра. Если там появились строки о переключении режима работы диска или сетевой карты - это вероятная причина.
Интеграция нагрузочного тестирования в процесс эксплуатации
Разовое тестирование перед обновлением лучше, чем ничего. Регулярное тестирование - это страховка от незаметной деградации. Внедрите три практики.
Автоматизация скриптами. Оберните команды sysbench, fio и wrk в shell-скрипт с параметрами: целевой хост, длительность, количество прогонов. Скрипт сохраняет результаты в директорию с временной меткой и выводит сводку: среднее, минимум, максимум, отклонение от предыдущего замера. Запускайте его перед каждым плановым обновлением.
CI/CD pipeline. Если вы используете Ansible для развертывания конфигураций Nginx, добавьте шаг с wrk в pipeline. Статья про автоматизированную настройку и проверку кеша Nginx содержит готовые плейбуки и скрипты тестирования, которые можно адаптировать под свой pipeline. После применения конфигурации pipeline автоматически прогоняет wrk и сравнивает Requests/sec с эталонным значением. Падение ниже порога - pipeline падает с ошибкой, обновление не идет в продакшен.
Периодический прогон baseline. Раз в месяц запускайте тесты на продуктовом сервере в часы минимальной нагрузки. Сохраняйте результаты в базу данных (например, InfluxDB) и стройте графики в Grafana. Тренд на понижение IOPS в течение трех месяцев при неизменной нагрузке - сигнал о деградации железа или постепенном захламлении файловой системы.
Хранение истории замеров. Текстовые файлы с результатами занимают килобайты. Храните их вместе с конфигурациями в Git-репозитории. При расследовании инцидента вы всегда сможете определить, после какого именно изменения упала производительность. Это превращает процесс обновлений из лотереи в управляемый и предсказуемый.
Нагрузочное тестирование - не разовая акция, а дисциплина. Включите его в регламент обновлений наравне с резервным копированием и проверкой логов. Это окупается первым же предотвращенным инцидентом.