У вас 64 ядра и 256 ГБ памяти, но Nginx при копеечном RPS внезапно начинает сыпать 502 Bad Gateway. Метрики CPU спят, диск не нагружен, а в логах upstream error: Connection refused или Cannot assign requested address. Вы думаете на утечку памяти в бэкенде, но корень зла - исчерпание пула ephemeral портов из-за механизма TIME_WAIT.
Каждое входящее TCP-соединение от клиента на Nginx и каждый исходящий прокси-запрос на бэкенд занимают локальный порт. По умолчанию диапазон ephemeral портов в Linux (ip_local_port_range) составляет около 28 тысяч портов (например, с 32768 по 60999). После закрытия соединения сокет падает в состояние TIME_WAIT и держится там фиксированные 60 секунд (модуль TCP_TIMEWAIT_LEN).
Считаем математику. При RPS всего в 500 запросов на бэкенд за минуту улетает 30 тысяч соединений. Пул пуст. Новые соединения просто некуда мапить. Nginx не может открыть сокет для апстрима и возвращает клиенту 502.
Проблема усугубляется на многоядерных серверах. Без SO_REUSEPORT все воркеры Nginx бьются за один и тот же listen-сокет, создавая lock contention на уровне ядра. Когда вы включаете SO_REUSEPORT, каждый воркер получает свой сокет, распределяя входящий трафик по ядрам через хеш-функцию ядра (включая порты источника и назначения). Это убивает блокировки, но на 64 ядрах пул портов улетает в космос еще быстрее из-за локальных очередей ядер.
Как это лечить на живом железе? Забываем про стандартные дефолты и правим sysctl.conf:
1. Снижаем таймаут TIME_WAIT, включая быстрый переиспользований сокетов для исходящих соединений:
`net.ipv4.tcp_tw_reuse = 1`
2. Расширяем диапазон локальных портов до максимума:
`net.ipv4.ip_local_port_range = 1024 65535`
3. Увеличиваем размер очереди входящих соединений (somaxconn), чтобы бэклог не сбрасывал пакеты при пиках:
`net.core.somaxconn = 65535`
4. Управляем размером таблицы TIME_WAIT в ядре (tcp_max_tw_buckets), чтобы защититься от SYN-флуда и нехватки памяти под дескрипторы:
`net.ipv4.tcp_max_tw_buckets = 2000000`
Аудит инфраструктуры - это не гадание по логам, а понимание сетевого стека на уровне struct sock в ядре Linux. Контролируйте свои эфемерные порты до того, как они уронели продакшн.
- Инфраструктурный аудит и калькулятор TCO кластера: @Personnel_run_bot (/tma)
- База знаний и разборы: ftops.space
- ftops.space | Run-As-Daemon Infrastructure
| # | Наименование новости | Тональность | Информативность | Дата публикации |
|---|---|---|---|---|
| 1 | Каждые 5 минут транзакции в PostgreSQL замирают на 3-7 секунд. ... | 0 | 8.8 | 29-09-2026 |
| 2 | Каждые пять минут нагруженный PostgreSQL кластер словно падает в обморок ... | 0 | 7.98 | 28-09-2026 |
| 3 | Каждые пять минут нагруженный PostgreSQL кластер словно падает в обморок ... | 0 | 8.03 | 27-09-2026 |
| 4 | Каждые 5 минут транзакции в PostgreSQL замирают на 3 - ... | -1 | 11.86 | 28-09-2026 |
| 5 | Каждые 5 минут транзакции в PostgreSQL замирают на 3-7 секунд. ... | 0 | 11.43 | 28-09-2026 |
| 6 | Сколько на самом деле стоит путь пакета через ядро Linux, ... | 0 | 7.07 | 28-09-2026 |
| 7 | Каждые пять минут высоконагруженная база данных в PostgreSQL словно проваливается ... | 1 | 8.42 | 29-09-2026 |
| 8 | База данных захлебывается в дисковом I/O wait, хотя на сервере ... | 0 | 8.6 | 26-09-2026 |
| 9 | База данных захлебывается в дисковом I/O wait, хотя на сервере ... | 0 | 8.41 | 26-09-2026 |
| 10 | Облачные провайдеры берут плату не за железо, а за лень ... | 0 | 9.49 | 29-09-2026 |