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

Анатомия игровых лагов › L8 Сокеты и протоколы

Перекос распределения в SO_REUSEPORT SO_REUSEPORT imbalance, stuck worker

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

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

Когда несколько процессов принимают трафик на одном порту, ядро закрепляет каждое подключение за процессом по хешу адреса и больше его не меняет. Если один процесс зависает, ждут только игроки, закреплённые за ним.

Почему Шлюз или сервер авторизации запускает несколько процессов с SO_REUSEPORT → Следствие Если один процесс останавливается из-за GC или перегрузки, закреплённые за ним новые подключения и UDP-пакеты к другим процессам не переходят → На экране Только у части игроков ошибка входа или фриз. При перезапуске со сменой числа процессов часть UDP-сессий обрывается

Симптомы
Ошибка входа / бесконечная загрузка, Фриз, Дисконнект
Факторы
Остановка, Потери
У кого
Только у меня, Весь сервер
Когда
Сразу после входа или техработ, Изредка, случайно
Ответственные
Основной ответственный Команда разработки · Разработка сервера · Совместно Команда инфраструктуры · Серверная инфраструктура
Команда разработки: задачи
Не допускать остановок принимающего потока, реализовать передачу сессий при перезапуске.
Команда инфраструктуры: задачи
Следить за очередью подключений каждого процесса (Recv-Q в ss), а если при деплое меняется число процессов, следовать процедуре передачи сессий.
На графике
Высоко только у некоторых · очередь подключений (Recv-Q) по слушающим сокетам
Где смотреть
Посмотреть через ss -ltnp для каждого слушающего сокета на этом порту Recv-Q (число подключений, ждущих accept) и процесс-владелец, сравнить пропускную способность процессов
Подтверждает
Из нескольких сокетов на одном порту Recv-Q постоянно растёт только у одного, а процесс этого сокета стоит или его пропускная способность близка к 0
Опровергает
Если Recv-Q растёт равномерно у всех сокетов, это общая перегрузка («Переполнение очереди подключений (backlog)»)
Чем проверить
Инструменты инфраструктуры (игровой код не нужен)

Источники

  1. socket(7) — Linux manual page Linux man-pages
    С SO_REUSEPORT несколько сокетов делают bind на один адрес и делят между собой TCP-подключения и UDP-пакеты
  2. net/core/sock_reuseport.c (Linux v6.12) Linux kernel
    Без BPF-программы сокет выбирается по хешу пакета, отображённому на число сокетов в группе
  3. Why does one NGINX worker take all the load? Cloudflare
    SO_REUSEPORT делит подключения по очередям воркеров простым хешем, поэтому если один воркер застрял, встают все подключения в его очереди
  4. net/ipv4/tcp_diag.c (Linux v6.12) Linux kernel
    Значения Recv-Q и Send-Q в ss: у слушающего сокета это число подключений, ждущих accept, и лимит backlog, у подключённого сокета это байты, ещё не прочитанные приложением, и отправленные байты без ACK

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

Тот же слой: L8 Сокеты и протоколы

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

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