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

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

Keepalive по умолчанию: 2 часа TCP keepalive defaults

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

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

Если другая сторона пропадает без сигнала о закрытии, TCP замечает это очень нескоро. Keepalive (механизм TCP, который проверяет, живо ли неактивное соединение) по умолчанию выключен, а если его включить, проверка начинается только после 2 часов простоя.

Почему Клиент пропадает без сигнала о закрытии: выключилось питание или оборвалась связь → Следствие Сервер считает соединение живым (keepalive по умолчанию 7 200 с, а если оставались неотправленные данные, до отказа от повторных передач около 15 минут) → На экране В мире остаётся персонаж-фантом, а при перезаходе ошибка «Аккаунт уже в игре»

Симптомы
Ошибка входа / бесконечная загрузка, Невидимки / фантомы
Факторы
Потери
У кого
Только у меня
Когда
После бездействия, Сразу после входа или техработ
Ответственные
Основной ответственный Команда разработки · Разработка сервера · Совместно Команда разработки · Разработка клиента, Команда инфраструктуры · Серверная инфраструктура
Команда разработки: задачи
Сервер: отвечать на хартбиты, а если их долго нет, первым закрывать соединение (настроить TCP_KEEPIDLE и TCP_USER_TIMEOUT). При переподключении заменять старую сессию по токену сессии и продолжать игру. Клиент: отправлять хартбиты на уровне игры с интервалом от нескольких до десятков секунд (не больше половины самого короткого таймаута простоя), при обрыве автоматически переподключаться.
Команда инфраструктуры: задачи
Для сокетов, которым код не задаёт свои значения, снизить значения ядра по умолчанию (tcp_keepalive_time и др.; они действуют только на сокеты с включённым SO_KEEPALIVE).
Цифры для ориентира
По умолчанию Linux начинает проверку после 7 200 с простоя, отправляет 9 проб с интервалом 75 с и, если ответа так и нет, разрывает соединение. Всего выходит около 2 ч 11 мин. Windows по умолчанию тоже начинает проверку только после 2 часов простоя.
На графике
Высоко только у некоторых · время с последнего приёма по соединениям
Где смотреть
Посмотреть через ss -tnoi lastrcv (сколько ms прошло с последнего приёма) и таймер keepalive (timer:(keepalive,…)) по соединениям и сопоставить с записями игрового сервера об отказах «Аккаунт уже в игре»
Подтверждает
Остаются соединения ESTABLISHED с lastrcv от нескольких минут до нескольких часов, а перезаход с этого аккаунта отклоняется с ошибкой «Аккаунт уже в игре»
Опровергает
Если давно молчащих соединений нет, а «Аккаунт уже в игре» всё равно появляется, дело в коде очистки сессий на игровом сервере
Чем проверить
Инструменты инфраструктуры (игровой код не нужен)

Источники

  1. tcp(7) — Linux manual page Linux man-pages
    После 7 200 с простоя 9 проб с интервалом 75 с (ещё около 11 минут). Действует только на сокеты с включённым SO_KEEPALIVE. Опции TCP_KEEPIDLE и TCP_USER_TIMEOUT
  2. RFC 9293: Transmission Control Protocol (TCP) IETF
    Keepalive по умолчанию должен быть выключен, а интервал простоя по умолчанию не меньше 2 часов
  3. SO_KEEPALIVE socket option Microsoft
    Таймаут TCP keepalive в Windows по умолчанию 2 часа
  4. ss(8) — Linux manual page iproute2
    lastrcv в выводе -i (сколько ms прошло с последнего приёма), timer:(keepalive,…) в выводе -o

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

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

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

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