Что действительно влияет на производительность Linux-сервера
Производительность Linux-сервера улучшается после устранения конкретного узкого места. Сначала измеряют задержки и загрузку ресурсов, затем меняют одну связанную группу параметров: приоритеты процессов, лимиты, управление памятью, дисковую очередь, сетевые буферы или расписание фоновых задач.
Заметный эффект чаще дают корректно выбранные CPU- и I/O-приоритеты, достаточный лимит файловых дескрипторов, подходящая стратегия работы со swap и dirty pages, настройка очередей под тип накопителя и устранение конкуренции между основным сервисом и backup. Массовое копирование готового sysctl-рецепта без измерений часто не меняет результат или увеличивает задержки.
Профиль нагрузки определяет подход. Веб-сервис обычно упирается в число workers, backlog, файловые дескрипторы и сетевые задержки. База данных чувствительна к latency диска, fsync, памяти и блокировкам. Файловый сервер зависит от последовательной пропускной способности, page cache и очереди накопителя. Контейнерный хост требует контроля cgroups v2, CPU limits, memory pressure и конкуренции между контейнерами.
| Тип нагрузки | Что проверить первым | Настройки, которые могут дать эффект |
|---|---|---|
| HTTP reverse proxy или API | p95/p99 latency, число workers, backlog, file descriptors, retransmits | LimitNOFILE, CPUWeight, somaxconn, qdisc, сетевые очереди |
| Реляционная база данных | await, fsync latency, memory pressure, swap, lock wait | page cache, dirty pages, I/O priority, память, лимиты соединений |
| Файловое хранилище | throughput, queue depth, await, cache hit rate, тип операций | read-ahead, scheduler, I/O weight, расписание backup |
| Контейнерный хост | CPU steal, PSI, cgroup limits, memory.events, I/O wait | CPUQuota, CPUWeight, MemoryMax, IOWeight, TasksMax |
Версия ядра, systemd, драйвер накопителя, объем RAM, виртуализация и архитектура приложения меняют результат. Для отдельного тестового стенда можно использовать облачный сервер с управляемыми ресурсами, например VDS или VPS в Timeweb Cloud, но итоговую конфигурацию проверяют на том же типе оборудования и под тем же сценарием нагрузки, что используется в production.
Практические шаблоны sysctl и сценарии для веб-сервисов, контейнеров и баз данных собраны в руководстве по разгону Linux-серверов для DevOps. В этой статье акцент сделан на методике выбора параметров и проверке их фактического эффекта.
Диагностика: как найти узкое место до тюнинга
Любое изменение начинайте с baseline, то есть зафиксированного состояния системы. Снимите показатели в обычный период и во время реального пика. Одного запуска top недостаточно: он показывает моментальный срез, а причина задержек может проявляться только при заполнении очереди, росте swap или пересечении нескольких фоновых задач.
Какие метрики снять перед изменениями
Минимальный baseline должен связывать ресурсы операционной системы с метриками приложения. Запишите загрузку CPU по user, system, iowait и steal, load average, число runnable-задач, доступную память, активность swap, PSI для CPU, памяти и I/O, задержку диска, throughput, сетевые ошибки, retransmits, dropped packets, p95/p99 latency и error rate сервиса.
Команды для первичной проверки:
uptime
top
vmstat 1 10
free -h
swapon --show
pidstat -dur 1 10
iostat -xz 1 10
ss -s
ss -lnt
ip -s link
sysctl -a
systemctl show app.service
cat /proc/1234/limits
cat /proc/pressure/cpu
cat /proc/pressure/memory
cat /proc/pressure/io
uptime и load average показывают длину общей очереди задач, но не говорят, какой ресурс занят. Сравнивайте load average с числом логических CPU и выводом vmstat. Поле r указывает на очередь выполняемых задач, b помогает заметить процессы, ожидающие I/O.
В top ищите раздельно user, system, iowait и steal. Высокий steal на виртуальной машине указывает на конкуренцию за CPU на гипервизоре. Увеличение system может быть связано с сетью, большим количеством системных вызовов или контейнерной нагрузкой.
free -h используйте для оценки поля available, а не только free. Linux заполняет свободную RAM page cache, поэтому небольшое значение free само по себе не означает дефицит памяти. В vmstat поля si и so показывают движение страниц через swap. PSI показывает время, когда задачи ожидали освобождения ресурса, и помогает увидеть давление, которое не всегда заметно по средней загрузке.
iostat -xz дает значения await, r/s, w/s, aqu-sz и %util. Сопоставляйте их с p95/p99 приложения. Высокий throughput при приемлемой latency может быть нормальным режимом. Низкий throughput и растущий await чаще указывают на насыщение накопителя, неподходящий queue depth или конкуренцию процессов.
Для расширенного чек-листа по CPU, памяти, диску и сети используйте руководство по метрикам производительности Linux-сервера. Метрики приложения при этом остаются главным критерием: сервер может выглядеть свободным, пока запросы ждут блокировку, connection pool или медленный SQL.
Как отличить CPU-, memory-, I/O- и network-bound нагрузку
- CPU-bound. Высокие user или system, заполненная очередь
rвvmstat, низкий iowait и рост latency при увеличении числа запросов. Проверьте CPU utilization по ядрам, affinity, количество workers и CPU steal. - Memory-bound. Падает
available, растут PSI memory, swap in/out и частота reclaim. Приложение может замедляться при формально невысокой средней загрузке CPU. - I/O-bound. Увеличиваются iowait, await и aqu-sz, процессы находятся в состоянии ожидания диска. Причиной может быть накопитель, контроллер, файловая система, fsync или фоновая запись dirty pages.
- Network-bound. Растут retransmits, dropped packets, receive errors, очереди
Recv-QиSend-Q. Низкая скорость может быть связана с RTT, ограничением виртуального интерфейса, провайдером или qdisc.
Смешанная нагрузка встречается чаще чистой. Например, база данных может создавать очередь диска, после чего workers начинают занимать CPU в ожидании таймеров и повторных запросов. Если одна операция SQL стабильно медленная, connection pool исчерпан или контейнер получил жесткий CPU limit, изменение sysctl не устранит причину.
Безопасный цикл тюнинга Linux-сервера
Настройка должна быть воспроизводимым экспериментом. Определите гипотезу, сохраните исходные значения, измените один параметр или связанную группу, запустите одинаковую нагрузку, сравните метрики, проверьте перезапуск и подготовьте откат.
Временные и постоянные изменения
Временные параметры ядра можно проверить через sysctl -w. Они действуют до перезагрузки и подходят для контролируемого эксперимента:
sysctl -n vm.swappiness
sysctl -w vm.swappiness=10
sysctl -n net.core.somaxconn
Постоянные значения храните в отдельном файле, например /etc/sysctl.d/90-performance.conf, а затем применяйте командой sysctl --system. Сначала проверьте, что параметр существует в текущем ядре, и зафиксируйте фактическое значение после применения.
sysctl -a 2>/dev/null > /root/sysctl-before.txt
sysctl --system
sysctl -n vm.swappiness
systemctl show app.service -p CPUWeight -p IOWeight -p LimitNOFILE
Для systemd-сервиса создайте drop-in через systemctl edit app.service. Сервисные параметры могут потребовать перезапуска, а некоторые настройки ядра или драйвера требуют перезагрузки. Проверяйте итоговую конфигурацию через systemctl show, а не по содержимому только что измененного файла.
Откат выполняйте сохраненным значением. Для drop-in можно использовать systemctl revert app.service, после чего перезапустить сервис и проверить его состояние через systemctl status app.service. Runtime-изменения возвращайте отдельной командой sysctl -w.
Как доказать, что настройка помогла
Сравнивайте один и тот же сценарий, длительность теста, размер данных, число клиентов и режим прогрева кэша. Записывайте throughput, p95/p99 latency, error rate, CPU steal, iowait, await, сетевые потери и потребление памяти.
Настройка полезна, если целевая метрика улучшилась, а побочные показатели не вышли за допустимые пределы. Увеличение throughput ценой резкого роста p99 или swap не дает рабочего результата. Единичный удачный запуск тоже недостаточен: повторите тест несколько раз и проверьте поведение после перезапуска сервиса и хоста.
Проверяйте версию ядра, systemd, дистрибутива, драйвера накопителя и контейнерного runtime. Один и тот же параметр может иметь другую область действия или отсутствовать в другой версии.
Управление приоритетами процессов Linux
Приоритеты меняют распределение дефицитного ресурса между процессами. Они не создают дополнительные CPU-циклы, дисковую пропускную способность или память. Поэтому приоритеты помогают, когда критичный сервис конкурирует с backup, архивированием, компиляцией или batch-задачей.
nice и renice для CPU-нагрузки
Значение nice находится в диапазоне от -20 до 19. Чем меньше число, тем выше относительный приоритет планирования CPU. Значение 0 используется по умолчанию. Повышать приоритет, то есть уменьшать nice, обычно может root или процесс с нужным правом. Обычный пользователь может увеличить nice и снизить влияние своей задачи.
nice -n 10 /usr/local/bin/backup
renice 10 -p 1234
ps -o pid,ni,stat,cmd -p 1234
Для backup, архивирования и компиляции обычно начинают с положительного nice, например 10 или 15, и проверяют p95 основного сервиса. Критичному сервису не задавайте отрицательный nice без измерений: это может вытеснить системные процессы и ухудшить общую стабильность.
renice меняет значение уже запущенного процесса. Дочерние процессы могут получить отдельное значение, а supervisor или systemd способен перезаписать параметры при перезапуске. Поэтому ручная команда подходит для короткого эксперимента, а постоянную политику задавайте на уровне unit или контейнера.
ionice и приоритет дисковых операций
ionice управляет классом и приоритетом I/O. Класс idle передает дисковый ресурс процессу только при отсутствии конкуренции. Класс best-effort использует приоритет от 0 до 7, где меньшее значение дает больше предпочтения. Класс realtime применять осторожно: процесс может вытеснить критичные операции и увеличить latency.
ionice -c 3 /usr/local/bin/backup
ionice -c 3 -p 1234
ionice -c 2 -n 6 -p 1234
ionice -p 1234
На HDD эффект от разграничения I/O часто заметнее из-за ограниченной механики и длинной очереди. SSD и NVMe имеют меньшую задержку, но backup все равно способен занять пропускную способность и очередь устройства. На некоторых I/O-моделях, драйверах и файловых системах влияние ionice ограничено, поэтому проверяйте его через iostat и latency приложения.
Высокий await может сохраняться при низком приоритете процесса, если накопитель уже насыщен, контроллер выполняет сборку мусора или storage ограничивает IOPS. В таком случае ionice меняет очередность, но не устраняет аппаратное ограничение.
systemd и cgroups v2 для постоянных ограничений
Для сервисов удобнее задавать политику в systemd drop-in. В системах с cgroups v2 параметры CPU и I/O применяются ко всей группе процессов unit, включая дочерние процессы.
[Service]
CPUWeight=200
IOWeight=50
CPUQuota=200%
Nice=5
CPUWeight задает относительный вес при конкуренции за CPU. CPUQuota=200% ограничивает группу примерно двумя CPU, но точное поведение зависит от scheduler и нагрузки. IOWeight распределяет вес дискового ресурса, если контроллер I/O доступен и storage поддерживает нужную модель.
systemctl edit backup.service
systemctl daemon-reload
systemctl restart backup.service
systemctl show backup.service -p CPUWeight -p CPUQuotaPerSecUSec -p IOWeight
systemctl status backup.service
Для Docker используйте ограничения runtime, например --cpus, --cpu-shares или параметры Compose, поддерживаемые вашей версией. CPU shares в cgroups задают относительный вес, а CPU limit задает потолок. Проверьте итоговые значения внутри контейнера и на хосте: контейнер может показывать доступную квоту иначе, чем физическая машина.
Настройка лимитов в Linux
Ошибки с лимитами часто выглядят как внезапные отказы при свободных CPU и RAM. Сервис исчерпывает file descriptors, процессы, потоки или соединения, после чего начинает возвращать ошибки.
Почему ulimit не меняет лимит сервиса
ulimit показывает ограничения текущей shell-сессии. Сервис, запущенный через systemd, получает окружение unit и не обязан наследовать значение из интерактивного терминала. При запуске через PAM, Docker или другой supervisor действует отдельная цепочка ограничений.
ulimit -n
ulimit -u
systemctl show app.service -p LimitNOFILE -p LimitNPROC -p TasksMax
cat /proc/1234/limits
Для systemd задайте параметры в drop-in:
[Service]
LimitNOFILE=65536
LimitNPROC=8192
TasksMax=8192
/etc/security/limits.conf и файлы в /etc/security/limits.d работают через PAM. Они влияют на сессии, которые проходят через соответствующий PAM-модуль. Для systemd-unit этот файл часто не меняет фактическое значение. Проверяйте лимит у PID работающего сервиса в /proc/1234/limits.
В контейнере задавайте лимиты через runtime, например --ulimit nofile=65536:65536, и сверяйте их внутри контейнера. Ограничение cgroup TasksMax контролирует число задач группы и может остановить рост процессов даже при высоком LimitNPROC.
Как выбрать nofile и nproc без завышения
Для nofile посчитайте максимальное число клиентских соединений, upstream-сокетов, listening sockets, файлов журналов, временных файлов и внутренних дескрипторов. Добавьте запас, подтвержденный нагрузочным тестом. У веб-сервера значение часто зависит от числа workers и модели событий, поэтому копирование числа 100000 без расчета ничего не доказывает.
nproc учитывает процессы и потоки, которые видит выбранный механизм лимитов. Учитывайте workers, helper-процессы, потоки runtime и запас для аварийных операций. Большой лимит не ускоряет приложение и может позволить утечке процессов быстрее исчерпать CPU и память.
После изменения проверьте ошибки приложения, число открытых дескрипторов, число потоков и фактический отказ при достижении предела. Превышение лимита должно быть диагностируемым событием, а не поводом бесконечно увеличивать значение.
Оптимизация кэширования Linux и управление памятью
Linux использует свободную RAM для page cache. Кэш ускоряет повторное чтение файлов и снижает обращения к диску, поэтому большой buff/cache в free -h обычно означает эффективное использование памяти. Ориентир для дефицита, поле available, PSI memory, swap activity и поведение приложения.
Page cache, available memory и очистка кэша
Регулярная очистка page cache редко ускоряет сервер. Она удаляет полезные данные, после чего приложение снова читает их с диска. Это увеличивает I/O и может поднять latency.
free -h
cat /proc/meminfo
sync
echo 3 > /proc/sys/vm/drop_caches
free -h
drop_caches подходит для диагностического сравнения, когда нужно отделить эффект page cache от скорости накопителя. Запускать его по расписанию в production не следует. Перед тестом фиксируйте latency и прогревайте кэш одинаковым способом.
Swap, swappiness и OOM killer
Проверяйте swap через free -h, swapon --show, vmstat и PSI memory. Параметр vm.swappiness не означает процент заполнения RAM. Он влияет на относительную готовность ядра вытеснять анонимные страницы по сравнению с reclaim page cache.
sysctl vm.swappiness
free -h
swapon --show
vmstat 1 10
cat /proc/pressure/memory
Отключение swap не дает универсального ускорения. При кратком memory pressure swap может сохранить работающий сервис, а без него ядро быстрее придет к OOM killer. При чувствительности к latency полезно снизить активность swap, но значение проверяют на конкретном объеме RAM и профиле нагрузки.
OOM killer завершает процесс, когда ядро или memory cgroup не может удовлетворить запрос памяти. Ищите записи в журнале ядра, проверяйте memory limit контейнера и контролируйте PSI. Если OOM возникает из-за неверного лимита cgroup, изменение глобального vm.swappiness проблему не решит.
Dirty pages и задержки записи
Запись сначала попадает в page cache как dirty pages. Параметры vm.dirty_background_ratio или vm.dirty_background_bytes задают порог, после которого фоновые потоки начинают активнее сбрасывать данные на диск. vm.dirty_ratio или vm.dirty_bytes задают верхний порог, после которого процесс записи может ждать освобождения page cache.
Используйте либо ratios, либо bytes. Ratios зависят от объема RAM: на большой машине они способны создать слишком крупный burst записи. Bytes позволяют ограничить объем dirty pages более предсказуемо, но требуют учета скорости storage.
sysctl vm.dirty_background_ratio
sysctl vm.dirty_ratio
sysctl vm.dirty_background_bytes
sysctl vm.dirty_bytes
cat /proc/meminfo | grep Dirty
cat /proc/meminfo | grep Writeback
В качестве экспериментальной точки для хоста с большой RAM иногда проверяют vm.dirty_background_bytes=268435456 и vm.dirty_bytes=1073741824. Эти числа не подходят как универсальный рецепт: для медленного HDD верхний порог может создавать длинную паузу записи, а для быстрых NVMe слишком маленький порог снизит throughput. Сравнивайте await, p99 записи, fsync latency и объем dirty pages.
Тюнинг Linux-сервера для дисковой подсистемы
Диск настраивают под реальный профиль: случайное чтение, случайная запись, последовательный поток, синхронные операции или смешанная нагрузка. Планировщик и queue depth, которые полезны для HDD, могут увеличить задержки на NVMe. Синтетический тест без совпадения с профилем приложения дает ограниченную информацию.
I/O scheduler для HDD, SSD и NVMe
Проверьте доступные и текущие планировщики:
cat /sys/block/sda/queue/scheduler
cat /sys/block/nvme0n1/queue/scheduler
Название активного варианта обычно выделено квадратными скобками. На HDD часто сравнивают bfq и mq-deadline, если они доступны. Для SATA SSD и NVMe встречаются none и mq-deadline. Конкретный набор зависит от версии ядра, драйвера и устройства.
none передает запросы ниже по стеку с минимальной дополнительной обработкой. mq-deadline помогает ограничивать задержки отдельных запросов. bfq может быть полезен при конкуренции интерактивных и фоновых операций, но его поддержка и эффект зависят от устройства.
Временная смена выполняется через sysfs:
echo mq-deadline > /sys/block/sda/queue/scheduler
cat /sys/block/sda/queue/scheduler
После перезагрузки значение может вернуться. Для постоянного применения используйте механизм, принятый в вашем дистрибутиве, и проверяйте его после старта системы. Не меняйте scheduler на рабочем диске без окна наблюдения и плана возврата.
Очередь устройства, read-ahead и файловая система
Проверьте параметры очереди и read-ahead:
cat /sys/block/sda/queue/nr_requests
cat /sys/block/sda/queue/read_ahead_kb
blockdev --getra /dev/sda
findmnt -no TARGET,SOURCE,FSTYPE,OPTIONS
Большой read-ahead помогает последовательному чтению файлов и потоковой обработке. Для случайного доступа он может расходовать память и читать ненужные блоки. Увеличение nr_requests дает смысл при достаточной глубине очереди и пропускной способности storage, но способно повысить p99 latency.
Mount options выбирайте вместе с требованиями файловой системы и надежности данных. noatime может уменьшить лишние metadata writes, если приложению не нужен access time. Асинхронный discard подходит только при поддержке устройства и ядра. Отключение write barriers или изменение поведения fsync допустимо лишь при подтвержденной защите от потери питания и проверке восстановления.
Проверка через fio и iostat
Для безопасного теста используйте отдельный раздел, тестовый файл или стенд. Команда ниже создает нагрузку на уже подготовленный файл и подходит только для контролируемого окружения:
fio --name=read-test --filename=/srv/test/fio.data --rw=randread --bs=4k --size=4G --iodepth=32 --numjobs=4 --runtime=60 --time_based --direct=1
Параметры rw, bs, numjobs, iodepth и runtime должны соответствовать рабочей нагрузке. Сравнивайте random read, random write, sequential read и sequential write отдельными тестами. Для fsync используйте отдельный сценарий с пониманием риска нагрузки.
Не запускайте destructive-тест с записью на рабочий раздел: fio может перезаписать данные. Даже read-тест создает I/O и способен увеличить latency пользователей.
iostat -xz 1
pidstat -d 1
cat /sys/block/sda/queue/scheduler
Результаты fio сопоставляйте с iostat и метриками приложения. Высокий IOPS в fio не доказывает ускорение базы данных, если реальный workload использует другую глубину очереди, fsync и размер блока. Примеры настройки storage для разных профилей собраны в руководстве по глубокой настройке Linux-серверов.
Сетевые очереди и буферы Linux
Сетевой тюнинг начинают с потерь, очередей и задержки. Механическое увеличение всех net.core-буферов расходует память и маскирует проблему на NIC, виртуальном интерфейсе, провайдере или в приложении.
Очередь входящих соединений и somaxconn
Для TCP-сервиса нужно разделять backlog приложения, net.core.somaxconn и SYN backlog. Приложение передает значение backlog в listen, а ядро ограничивает его системным параметром. net.ipv4.tcp_max_syn_backlog относится к очереди полуоткрытых TCP-соединений.
sysctl net.core.somaxconn
sysctl net.ipv4.tcp_max_syn_backlog
ss -lnt
ss -s
В выводе ss -lnt поле Recv-Q у listening socket показывает текущую очередь ожидающих соединений, а Send-Q часто отражает установленный backlog. Рост очереди и отказы при всплеске подключений могут указывать на медленный accept, малое число workers или исчерпание file descriptors.
Проверяйте увеличение somaxconn только вместе с настройкой web-сервера и реальным тестом. Очередь сгладит короткий всплеск, но не исправит сервис, который обрабатывает соединения медленнее входящего потока.
TCP-буферы, retransmits и сетевые потери
Проверьте статистику интерфейса и сокетов:
ss -s
ip -s link
ethtool -S eth0
sysctl net.ipv4.tcp_rmem
sysctl net.ipv4.tcp_wmem
sysctl net.core.rmem_max
sysctl net.core.wmem_max
tcp_rmem и tcp_wmem задают минимальный, начальный и максимальный размер TCP-буфера. Автонастройка учитывает RTT, скорость канала и объем доступной памяти. Большой канал с высоким RTT требует большего окна, но на локальной сети с малым RTT увеличение буфера может не дать эффекта.
Если растут retransmits, receive errors или dropped packets, ищите причину в кабеле, NIC, драйвере, виртуальном свитче, MTU, перегрузке интерфейса и провайдере. Изменение TCP-буферов не исправляет физические потери. Не отключайте TCP timestamps и не меняйте congestion control без сравнения throughput, p95 latency и retransmits.
Когда нужен tc, а не sysctl
sysctl задает глобальные параметры сетевого стека. tc управляет очередью конкретного интерфейса, shaping и AQM.
tc qdisc show dev eth0
tc -s qdisc show dev eth0
ip -s link show dev eth0
fq подходит для многих серверных TCP-сценариев, а fq_codel помогает контролировать bufferbloat при заполнении очереди. Выбор проверяют по latency, drops, throughput и загрузке интерфейса. Для UDP, потоковой передачи и контейнерных сетей нужны отдельные тесты: одна qdisc не подходит всем протоколам и профилям.
Фоновые задачи: как освободить ресурсы в часы пик
Backup, индексация, сканирование, сжатие логов и batch-обработка часто создают предсказуемые пики. Найдите их расписание, сопоставьте с p95 сервиса и перенесите тяжелые операции в окно низкого трафика или на отдельный storage.
systemd timers и cron под контролем
systemctl list-timers --all
crontab -l
systemctl list-unit-files --type=timer
journalctl -u backup.service --since today
Для timer можно добавить случайную задержку, чтобы одинаковые задачи на группе серверов не стартовали одновременно:
[Timer]
RandomizedDelaySec=15min
Для фонового service задайте мягкий CPU- и I/O-профиль:
[Service]
Nice=10
IOSchedulingClass=idle
CPUQuota=50%
IOWeight=20
RuntimeMaxSec=2h
Ограничение длительности защищает от зависшей batch-задачи, но требует обработки частичного результата и повторного запуска. Проверьте журнал после изменения и убедитесь, что backup завершает работу до следующего окна.
Для cron оценивайте соседние задания в одном расписании. anacron может запустить пропущенную задачу после включения хоста, поэтому после простоя возможен неожиданный пик. На нескольких серверах добавляйте разнос по времени и контролируйте одновременное обращение к storage.
Логи, journald и ротация
Большой поток логов увеличивает запись на диск, количество системных вызовов и расходы на ротацию. Проверьте размер журнала и активные правила:
journalctl --disk-usage
journalctl --vacuum-size=2G
cat /etc/systemd/journald.conf
ls /etc/logrotate.d
Параметры journald задают в секции [Journal]:
[Journal]
SystemMaxUse=2G
RuntimeMaxUse=512M
RateLimitIntervalSec=30s
RateLimitBurst=1000
Ограничение размера защищает дисковое пространство, а rate limiting снижает шквал повторяющихся сообщений. Слишком жесткие значения усложнят расследование инцидента и могут скрыть важную ошибку. Сохраняйте критичные события в отдельном хранилище и согласуйте retention с требованиями эксплуатации.
Какие настройки обычно почти не помогают
Почему универсальные sysctl-рецепты дают непредсказуемый результат
Готовая конфигурация зависит от версии ядра, объема RAM, типа накопителя, сетевой карты, workload и приложения. Значение, полезное для сервера с NVMe и большим числом коротких HTTP-соединений, может ухудшить работу HDD-хранилища или базы данных с синхронной записью.
- Массовое увеличение сетевых буферов. Оправдано при доказанном bandwidth-delay product и нехватке окна TCP. Нужны данные по RTT, throughput, retransmits и памяти.
- Отключение swap. Допустимо для узкой системы с заранее рассчитанным запасом RAM и внешним контролем memory pressure. Нужны тесты OOM-сценария.
- Регулярный drop_caches. Подходит для диагностического сравнения холодного и прогретого кэша. Для постоянной работы он увеличивает чтение с диска.
- Безусловная смена I/O scheduler. Имеет смысл после сравнения на конкретном устройстве. Контролируйте await, p99 и пропускную способность.
- Жесткое значение vm.swappiness. Выбирается по активности swap, PSI memory, latency и объему RAM, а не по шаблону.
- Отключение защитных механизмов ядра. Не используйте такой прием ради непроверенного прироста. Сначала измерьте стоимость защиты и оцените риск.
- Настройка без нагрузки. Параметр может выглядеть полезным в idle, но ухудшать поведение при заполнении очередей и росте конкуренции.
Проверяйте три вещи: параметр существует в текущей системе, значение фактически применилось, а целевая метрика изменилась в нужную сторону. Результат фиксируйте вместе с версией ядра, железом и сценарием нагрузки.
Когда проблема не в Linux
Остановите тюнинг ОС, если симптомы указывают на приложение, базу данных, storage или архитектуру:
- один SQL-запрос занимает большую часть времени;
- растет lock wait или очередь connection pool;
- число workers не соответствует CPU и модели обработки запросов;
- виртуальная машина получает высокий steal;
- контейнер упирается в CPU или memory limit;
- storage не дает нужные IOPS или throughput;
- сеть ограничена провайдером, NIC или виртуальным свитчем.
После обновления отдельно сравните версию ядра, sysctl, конфигурацию Nginx, параметры Docker и драйверы. Для такого сценария полезен алгоритм восстановления производительности после обновлений. Возврат к старым значениям имеет смысл только после проверки совместимости и подтверждения, что именно они изменили поведение.
Итоговый чек-лист настройки производительности Linux-сервера
Минимальный набор команд для проверки
| Задача | Команды | На какой вопрос отвечают |
|---|---|---|
| CPU и очередь задач | uptime, top, vmstat 1 | Есть ли нехватка CPU, высокий system, iowait, steal или run queue |
| Память и swap | free -h, vmstat 1, swapon --show | Сколько доступно RAM и идет ли обмен со swap |
| Процессы | pidstat -dur 1, ps -eo pid,ni,stat,cmd | Кто потребляет CPU, I/O и какой nice применен |
| Диск | iostat -xz 1, fio | Каковы await, queue depth, util и реальная скорость |
| Сеть | ss -s, ss -lnt, ip -s link | Есть ли backlog, drops, errors и retransmits |
| NIC и qdisc | ethtool -S eth0, tc -s qdisc show dev eth0 | Есть ли ошибки интерфейса и переполнение очереди |
| sysctl | sysctl -n PARAMETER, sysctl --system | Каково фактическое значение и применился ли файл |
| systemd | systemctl show app.service | Какие лимиты, веса и квоты получил сервис |
| Лимиты процесса | cat /proc/1234/limits | Какие ограничения видит работающий процесс |
Как автоматизировать проверенные настройки через Ansible
Храните sysctl, systemd drop-ins, limits и параметры контейнеров в системе контроля версий. Для каждой настройки фиксируйте назначение, поддерживаемые версии, исходную метрику, ожидаемый эффект и процедуру rollback.
Пример идемпотентного применения sysctl:
- name: Set swappiness
ansible.posix.sysctl:
name: vm.swappiness
value: '10'
state: present
reload: true
- name: Set application open files limit
ansible.builtin.copy:
dest: /etc/systemd/system/app.service.d/limits.conf
mode: '0644'
content: |
[Service]
LimitNOFILE=65536
notify: Restart application
В role добавьте проверку версии ОС и ядра, наличие параметра, сбор метрик до и после, проверку состояния сервиса и аварийный откат. Не автоматизируйте значение, эффект которого не подтвержден нагрузочным тестом.
Перед изменениями определите SLA и целевую метрику. Снимите baseline. Найдите bottleneck. Выберите одну группу параметров. Измените ее временно. Проверьте систему и сервис под нагрузкой. Сравните p95, p99, throughput и error rate. Закрепите результат в конфигурации. Добавьте мониторинг. Перезагрузите тестовый узел и сверяйте значения после старта.
Для группы серверов проверьте расхождения конфигураций и версий. Один и тот же Ansible-рецепт должен учитывать тип диска, объем RAM, роль узла и ограничения контейнерного runtime. Такой порядок снижает риск получить одинаковую настройку на системах с разными узкими местами.