Тюнинг Nginx под 50 тысяч соединений: разбор инцидента
50 тысяч TCP-соединений не означают, что Nginx нужно просто накормить большим worker_connections. Разбираем, где упирается конфигурация, почему растут 502 и как проверить лимиты файловых дескрипторов до следующего пика.
При 50 тысячах одновременных соединений Nginx чаще ломается не из-за одного «неправильного» параметра, а из-за цепочки лимитов: файловых дескрипторов, очереди accept, соединений с upstream и CPU на TLS. Разберём типичный инцидент для Nginx 1.26.x на Linux: как отличить нехватку ресурсов от проблем приложения, какие настройки менять и что измерять после каждого изменения.
Что на самом деле означает 50 тысяч соединений
Метрика connections показывает TCP-соединения, а не запросы в секунду. Пятьдесят тысяч клиентов могут почти ничего не делать, если держат keep-alive, или создавать постоянную нагрузку, если отправляют запросы и получают ответы.
Для reverse proxy есть ещё одна важная деталь: одно клиентское соединение не всегда равно одному файловому дескриптору. Пока запрос обслуживает upstream, Nginx обычно держит дескриптор клиента и отдельный дескриптор соединения с backend. Поэтому 50 тысяч клиентов могут потребовать близкое к 100 тысячам дескрипторов, а ещё нужны дескрипторы для логов, TLS, файлов статики и служебных операций.
Главная ошибка инцидента — считать worker_connections глобальным лимитом сервера. Это лимит на один worker, причём в него входят и клиентские, и upstream-соединения.
Сноска. Файловый дескриптор — числовой идентификатор открытого файла, сокета или другого ресурса процесса. Для Nginx сетевое соединение тоже занимает файловый дескриптор.
Где ломается конфигурация
worker_connections не спасает от лимита open files
Если в конфигурации указано worker_connections 65536, это ещё не означает, что worker сможет открыть 65 536 сокетов. Процесс ограничен значением RLIMIT_NOFILE, которое задаётся операционной системой или менеджером сервиса. При меньшем лимите в error log появляются ошибки вроде too many open files, а новые соединения начинают отбрасываться.
Проверяйте лимит именно у запущенного процесса, а не только значение в shell перед стартом Nginx. В systemd настройки интерактивной оболочки могут не иметь никакого отношения к сервису.
Очередь accept ограничена не только Nginx
Параметр backlog в директиве listen задаёт размер очереди ожидающих подключений, но итоговое значение также зависит от лимитов Linux, включая net.core.somaxconn. Если очередь переполняется во время всплеска, клиенты получают таймауты или ошибки соединения ещё до обработки HTTP-запроса.
Большой backlog не ускоряет обработку. Он лишь даёт системе больше места, чтобы пережить короткий пик, пока workers принимают новые подключения.
Прокси удваивает цену соединения
В схеме Nginx → приложение число дескрипторов и соединений с upstream может стать главным ограничением. Увеличивать worker_connections без проверки пула backend опасно: Nginx примет больше клиентов, но очередь к приложению вырастет, а пользователи увидят 502, 504 и увеличившееся время ответа.
Базовая конфигурация для проверки гипотезы
Ниже — не универсальный продакшен-файл, а безопасная отправная точка для Linux и Nginx 1.26.x. Значения нужно сверить с числом workers, типом трафика, лимитами systemd и возможностями backend.
worker_processes auto;
worker_rlimit_nofile 200000;
error_log /var/log/nginx/error.log warn;
pid /run/nginx.pid;
events {
worker_connections 16384;
use epoll;
multi_accept off;
}
http {
access_log /var/log/nginx/access.log;
upstream app_backend {
server 127.0.0.1:8080;
keepalive 128;
}
server {
listen 443 ssl backlog=65535 reuseport;
server_name example.com;
location / {
proxy_http_version 1.1;
proxy_set_header Connection "";
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_pass http://app_backend;
}
}
}
worker_processes auto подбирает число workers по доступным CPU. use epoll предназначен для Linux; на другой операционной системе этот параметр не следует копировать без проверки документации. reuseport распределяет новые соединения между listening-сокетами workers, но может изменить баланс и поведение при неравномерном трафике.
multi_accept off — консервативный выбор для начала расследования. При включении один worker пытается принять сразу все доступные соединения. Во время всплеска это может отнять время у уже обслуживаемых запросов, поэтому параметр проверяют нагрузочным тестом, а не включают автоматически.
План расследования инцидента
- Зафиксируйте масштаб. Снимите число активных соединений, requests per second, p95 или p99 задержки, долю 4xx и 5xx, загрузку CPU, память и сетевой трафик. Отдельно разделите keep-alive, активные запросы и соединения к upstream. Проверка результата: у вас есть временная шкала, по которой видно, что выросло первым.
- Проверьте конфигурацию и фактическое число workers. Выполните
nginx -t, затем посмотрите итоговую конфигурацию черезnginx -T. Проверка результата: Nginx принимает конфигурацию, а число workers и параметры listen совпадают с тем, что вы собирались изменить. - Сверьте лимиты дескрипторов. Проверьте лимит сервиса systemd и файл
/proc/<PID>/limitsу master или worker-процесса. Проверка результата: soft limit не ниже расчётного числа клиентских, upstream- и служебных дескрипторов. - Проверьте ошибки ядра и Nginx. Ищите
too many open files,worker_connections are not enough, таймауты подключения к upstream и сообщения о переполнении очередей. Проверка результата: после изменения лимита конкретная ошибка перестала расти, а не просто сместилась в 502. - Меняйте один класс параметров за раз. Сначала лимиты файлов, затем приём соединений, затем upstream и keep-alive. Проверка результата: после каждого изменения сохраняется сравнимый интервал нагрузки и есть метрики до и после.
nginx -t
nginx -T
ss -s
cat /proc/$(cat /run/nginx.pid)/limits
tail -n 100 /var/log/nginx/error.log
Какие настройки сравнивать
| Подход | Что меняется | Плюс | Цена и риск |
|---|---|---|---|
| Увеличить worker_connections | Лимит соединений на worker | Больше запас по открытым сокетам | Нужны соответствующие open files и память |
| Добавить workers | Число процессов Nginx | Лучшее использование нескольких CPU | Больше служебных расходов, не лечит медленный backend |
| Включить reuseport | Распределение входящих соединений | Меньше конкуренции за listening-сокет на Linux | Возможен неравномерный баланс и сложнее диагностика |
| Увеличить backlog | Очередь новых подключений | Переживает короткий всплеск | Не повышает пропускную способность приложения |
| Сократить keep-alive | Время жизни простаивающего соединения | Освобождает дескрипторы | Больше TCP- и TLS-handshake, выше нагрузка на CPU |
На практике первым кандидатом обычно становится не максимальное значение каждого параметра, а согласованный бюджет. Для 8 workers и worker_connections 16384 теоретический предел составляет 131 072 слота, но это не обещание обслужить столько клиентов: каждый worker имеет собственный лимит, а проксирование расходует дополнительные дескрипторы.
Граничные случаи и место, где тюнинг ломается
50 тысяч idle-соединений
Если соединения в основном простаивают, ограничителем будут память, лимиты дескрипторов и стоимость TLS, а не CPU обработки запросов. Слишком длинный keepalive_timeout удерживает ресурсы ради клиента, который может сделать следующий запрос через несколько минут. Слишком короткий таймаут заставляет клиентов чаще устанавливать новые TCP- и TLS-сессии.
50 тысяч активных запросов
Здесь Nginx может оставаться здоровым, пока приложение отвечает быстро. Если backend блокирует worker-пулы, использует медленные запросы к базе или исчерпывает собственный connection pool, увеличение Nginx только делает очередь длиннее. Следите за временем ответа upstream и количеством активных запросов на приложение, а не только за CPU Nginx.
TLS и HTTP/2
HTTP/2 способен передавать много запросов через одно TCP-соединение, поэтому число соединений и requests per second расходятся ещё сильнее. TLS увеличивает цену новых подключений. В таком сценарии полезнее измерять handshake rate, загрузку CPU и долю повторно используемых сессий, чем бездумно поднимать backlog.
Где подход не сработает
Настройки workers не исправят исчерпанный пул соединений базы данных, утечку памяти в приложении, неправильный лимит контейнера или сетевую проблему балансировщика. Если контейнер получил меньший ulimit, чем хост, правка nginx.conf не изменит реальный предел.
Что проверить после изменения
Сначала прогоните нагрузку, которая разделяет idle и active connections. Зафиксируйте число виртуальных клиентов, длительность теста, долю keep-alive, размер ответа, TLS и число backend-инстансов. Без этих условий сравнение «до и после» не доказывает, что тюнинг помог.
Минимальный набор наблюдения: количество соединений, accept rate, active requests, p95 и p99 latency, 502/504, ошибки open files, CPU каждого worker, RSS-память и время ответа upstream. Если после роста worker_connections исчезли ошибки лимита, но p99 и 504 увеличились, проблему перенесли на следующий слой.
Что делать дальше
Сохраните рабочую конфигурацию в системе контроля версий и оформите для неё расчёт: сколько workers запущено, сколько дескрипторов нужно на клиента и upstream, какой лимит выставлен в systemd и какой backlog разрешает ядро. Затем проведите отдельный тест для 50 тысяч idle-соединений и отдельный тест для активного трафика.
После этого настройте алерты на ошибки too many open files, рост 502/504, заполнение connection pool приложения и расхождение между числом клиентских и upstream-соединений. Инвалидация кеша и настройка буферов Nginx требуют отдельного разбора: в этом материале важны только лимиты соединений и путь к диагностике.
Аналитик звонков: Разбор записи звонка по этапам сделки: где сорвалось, что упущено, три исправляемые рекомендации с цитатами.
Спросить за 90 ₽Источники: Nginx documentation: Core functionality, Nginx documentation: Events module
Частые вопросы
Достаточно ли поставить worker_connections 50000?
Сколько workers нужно для 50 тысяч соединений?
Что делать, если после тюнинга появились 502 и 504?
Нужно ли включать reuseport и multi_accept одновременно?
Что будет, если я не успею увеличить лимит файловых дескрипторов?
Почему Nginx показывает мало CPU, но пользователи получают таймауты?
Материал носит информационный характер и подготовлен редакцией «Агентуры». Он не является офертой, рекламой или индивидуальной консультацией. Упомянутые продукты, компании и торговые знаки принадлежат их правообладателям. Перед принятием решений, влекущих юридические или финансовые последствия, обратитесь к профильному специалисту.