Если игровой сервер часто открывает и закрывает короткие соединения с БД или другими серверами, закрытые соединения ещё какое-то время занимают порты, и новые соединения открыть не удаётся.
Почему На каждый запрос открывается и закрывается новое соединение → Следствие Сторона, закрывшая соединение первой, держит порт около 60 секунд (в Linux) в состоянии TIME_WAIT, и свободные порты заканчиваются → На экране Внутренние запросы не проходят: сбои сохранения и ошибки функций
Основной ответственный Команда разработки · Разработка сервера · Совместно Команда инфраструктуры · Серверная инфраструктура
Команда разработки: задачи
Переиспользовать соединения (пул соединений), не открывать и не закрывать соединение на каждый запрос.
Команда инфраструктуры: задачи
Расширить диапазон портов (ip_local_port_range), рассмотреть повторное использование TIME_WAIT для исходящих соединений (tcp_tw_reuse в Linux), следить за числом TIME_WAIT.
Цифры для ориентира
Диапазон портов в Linux по умолчанию (32768–60999) даёт около 28 000 портов. Если открывать к одному и тому же адресу больше 470 новых соединений в секунду, порты заканчиваются. В Windows портов по умолчанию около 16 000 (49152–65535), а TIME_WAIT длиннее, поэтому порты заканчиваются ещё быстрее.
На графике
Упор в лимит (плато) · число сокетов в TIME_WAIT, число неудачных внутренних соединений
Где смотреть
Подсчитать сокеты в TIME_WAIT по адресам назначения через ss -tan state time-wait и найти в логах игрового сервера ошибки connect (EADDRNOTAVAIL)
Подтверждает
Число TIME_WAIT к одному адресату (БД и т. п.) выходит на плато около размера диапазона эфемерных портов (по умолчанию около 28 000), а connect завершается с EADDRNOTAVAIL
Опровергает
Если TIME_WAIT мало, но сбоят только исходящие соединения во внешнюю сеть, это «Лимиты соединений и портов облачного NAT-шлюза»
Чем проверить
Инструменты инфраструктуры (игровой код не нужен)
Подробнее
60 секунд TIME_WAIT в Linux зашиты в ядро. Если уменьшить похожий по названию tcp_fin_timeout, TIME_WAIT короче не станет.
Источники
IP SysctlLinux kernel ip_local_port_range по умолчанию 32768–60999, параметр tcp_tw_reuse, tcp_fin_timeout: время пребывания в состоянии FIN_WAIT_2
TCP/IP port exhaustion troubleshootingMicrosoft Динамические порты Windows по умолчанию 49152–65535, закрытое соединение по умолчанию держит порт в TIME_WAIT 4 минуты
ss(8) — Linux manual pageiproute2 Фильтр состояния state time-wait отбирает только сокеты в TIME_WAIT
connect(2) — Linux manual pageLinux man-pages EADDRNOTAVAIL: соединение не открыть, потому что заняты все порты из диапазона эфемерных портов