한국어English日本語简体中文繁體中文DeutschไทยTiếng ViệtРусскийPortuguês (Brasil)EspañolBahasa Indonesia

Анатомия игровых лагов › L7 ОС сервера (ядро)

Переполнение очереди подключений (backlog) Listen backlog / SYN queue overflow

ID причины so-backlog · Основной ответственный Команда разработки · Разработка сервера · Совместно Команда инфраструктуры · Серверная инфраструктура, Команда разработки · Разработка клиента

Открыть карточку в основной версии с иллюстрациями и экспериментами →

Когда сразу после техработ одновременно подключаются десятки тысяч игроков, очередь подключений ядра (backlog) переполняется и попытки подключения отбрасываются.

Почему С окончанием техработ подключения приходят быстрее, чем игровой сервер успевает принимать их через accept → Следствие Очередь подключений ядра (backlog: меньшее из значения, которое код сервера передал в listen, и предела ядра) заполнена → На экране Попытки подключения отбрасываются, повторы идут один за другим: ошибка входа / бесконечная загрузка

Симптомы
Ошибка входа / бесконечная загрузка
Факторы
Потери
У кого
Весь сервер
Когда
Сразу после входа или техработ
Ответственные
Основной ответственный Команда разработки · Разработка сервера · Совместно Команда инфраструктуры · Серверная инфраструктура, Команда разработки · Разработка клиента
Команда разработки: задачи
Сервер: увеличить значение, которое код передаёт в listen, не давать потоку, принимающему подключения, останавливаться на другой работе, сделать очередь на вход. Клиент: увеличивать интервал между повторами (со случайным разбросом).
Команда инфраструктуры: задачи
Увеличить somaxconn в ядре (эффект будет, только если поднять и его, и значение listen в коде сервера), держать SYN cookies включёнными, следить за числом переполнений (TcpExtListenOverflows в nstat).
Цифры для ориентира
Предел ядра Linux (somaxconn) начиная с версии 5.4 по умолчанию равен 4 096 (до этого 128), но если код сервера передаёт в listen меньшее значение, лимитом становится оно. Когда очередь заполнена, Linux молча, без ошибки, отбрасывает запросы на подключение. ОС клиента повторяет запрос несколько раз, начиная через 1 секунду, поэтому для игрока это выглядит как долгая загрузка без сообщения «Ошибка подключения». Сервер на Windows возвращает отказ, и клиент сразу видит «Ошибка подключения».
На графике
Всплеск сразу после входа или техработ · число переполнений очереди подключений (ListenOverflows), число попыток подключения
Где смотреть
Посмотреть прирост TcpExtListenOverflows и TcpExtListenDrops в nstat -az и сравнить через ss -ltn у слушающего сокета Recv-Q (число подключений, ждущих accept) и Send-Q (лимит backlog)
Подтверждает
В момент наплыва подключений растёт ListenOverflows, а Recv-Q слушающего сокета держится на уровне Send-Q
Опровергает
Если ListenOverflows не меняется, причина в другом. Если соединение установлено, а загрузка не заканчивается, это «Наплыв входов и запросы N+1». Если вход упирается ровно в определённое число игроков, это «Лимит файловых дескрипторов»
Чем проверить
Инструменты инфраструктуры (игровой код не нужен)

Источники

  1. listen(2) — Linux manual page Linux man-pages
    Backlog в listen, превышающий somaxconn, молча урезается. somaxconn по умолчанию 4 096 (с версии 5.4, раньше 128). При заполненной очереди запрос можно проигнорировать и положиться на повтор со стороны клиента
  2. IP Sysctl Linux kernel
    tcp_syn_retries: запрос на подключение (SYN) отправляется повторно несколько раз, первое ожидание перед повтором 1 секунда. tcp_abort_on_overflow по умолчанию выключен (при переполнении отказ не отправляется), tcp_syncookies по умолчанию включён
  3. listen function (winsock2.h) Microsoft
    В Windows при заполненной очереди клиент получает ошибку WSAECONNREFUSED
  4. SNMP counter Linux kernel
    TcpExtListenOverflows: сколько раз запрос на подключение (SYN) был отброшен из-за заполненной очереди accept. Вместе с ним растёт и TcpExtListenDrops
  5. net/ipv4/tcp_diag.c (Linux v6.12) Linux kernel
    Значения Recv-Q и Send-Q в ss: у слушающего сокета это число подключений, ждущих accept, и лимит backlog, у подключённого сокета это байты, ещё не прочитанные приложением, и отправленные байты без ACK

Смотрите также

Тот же слой: L7 ОС сервера (ядро)

Причины с тем же симптомом (Ошибка входа / бесконечная загрузка) на других слоях

Карточка в основной версии с иллюстрациями и экспериментами