Траблшутинг утечек сокетов TIME_WAIT: sysctl тюнинг и Nginx upstream keepalive
- Ошибка в логах Nginx:
110: Cannot assign requested addressпри попытке подключения к бэкенду. - Утилита
ss -sилиnetstatфиксирует более 30 000–60 000 TCP-сокетов в состоянииTIME-WAIT. - Веб-сервер перестает принимать новые входящие соединения при высоких значениях RPS.
1. Диагностика состояния сокетов в системе
# Сводка по сокетам
ss -s
# Подсчет TIME_WAIT соединений
ss -tan state time-wait | wc -l2. Тюнинг стека TCP в ядре Linux (/etc/sysctl.d/99-tcp-tuning.conf)
# Разрешить повторное использование сокетов TIME_WAIT для исходящих подключений
net.ipv4.tcp_tw_reuse = 1
# Расширение диапазона локальных эфемерных портов
net.ipv4.ip_local_port_range = 10240 65535
# Увеличение максимального размера таблицы TCP TIME_WAIT
net.ipv4.tcp_max_tw_buckets = 262144
# Увеличение размера очереди SYN-пакетов и backlog
net.core.somaxconn = 65535
net.ipv4.tcp_max_syn_backlog = 65535
# Уменьшение таймаута TCP FIN
net.ipv4.tcp_fin_timeout = 15Примените параметры:
sysctl --system3. Включение Keepalive соединений между Nginx и апстримом
По умолчанию Nginx закрывает соединение к бэкенду после каждого запроса, порождая тысячи сокетов TIME_WAIT. Включите постоянный пул:
upstream backend_cluster {
server 10.0.1.10:8080;
server 10.0.1.11:8080;
# Сохранять до 64 неактивных соединений в пуле для каждого воркера
keepalive 64;
}
server {
location / {
proxy_pass http://backend_cluster;
proxy_http_version 1.1;
proxy_set_header Connection ""; # Очистка заголовка Close
}
}4. Валидация и перезагрузка
nginx -t && systemctl reload nginx Частые вопросы (FAQ)
Почему tcp_tw_recycle удален из современных ядер Linux?
Параметр tcp_tw_recycle нарушал работу соединений через NAT (за одним публичным IP находились разные клиенты со своими таймстемпами TCP), что приводило к массовому сбросу пакетов. Вместо него используется безопасный tcp_tw_reuse.
Зачем указывать proxy_set_header Connection '' при настройке upstream keepalive?
По умолчанию Nginx отправляет заголовок 'Connection: close' на вышестоящий бэкенд. Очистка заголовка сообщает бэкенду о необходимости поддерживать TCP-соединение открытым.