Чёрная дыра MTU (большие пакеты теряются раз за разом) PMTU black hole
ID причины rt-mtu · Основной ответственный Команда инфраструктуры · Сетевая инфраструктура · Совместно Команда инфраструктуры · Серверная инфраструктура, Команда разработки · Разработка сервера
Если на промежуточном участке допустимый размер пакета уменьшился, а уведомление «слишком большой» (ICMP) блокируется, большие пакеты пропадают, сколько бы раз их ни отправляли повторно.
Почему На участке VPN или туннеля максимальный размер меньше, а уведомления о превышении размера блокируются файрволом → Следствие Отправитель, не зная причины, раз за разом повторно передаёт тот же большой пакет, RTO каждый раз удваивается → На экране Обычно всё нормально, но в моменты передачи больших данных (инвентарь, места скопления игроков, загрузка при входе) встают и все следующие мелкие пакеты: фриз, в итоге дисконнект или бесконечная загрузка
При определённом действии, Сразу после входа или техработ
Ответственные
Основной ответственный Команда инфраструктуры · Сетевая инфраструктура · Совместно Команда инфраструктуры · Серверная инфраструктура, Команда разработки · Разработка сервера
Команда разработки: задачи
Чтобы снизить размер на стороне сервера, задать в сокете максимальный размер сегмента (TCP_MAXSEG). Одного дробления сообщений в игровом коде недостаточно (TCP заново собирает отправляемые данные в куски размером MSS).
Команда инфраструктуры: задачи
Сеть: ограничить MSS на пограничном оборудовании (MSS clamping), разрешить ICMP о превышении размера (тип 3, код 4, fragmentation needed) на файрволах и в сетевых ACL облака. Серверы и ОС: настроить MTU пути, проверить, что ICMP о превышении размера не блокируется ни в файрволе сервера, ни в облачной группе безопасности, как последнюю страховку включить в Linux tcp_mtu_probing=1.
Цифры для ориентира
Обычно 1 500 байт, после туннеля около 1 400. Если один и тот же пакет повторно передаётся 5–6 раз, фриз длится больше 10 с.
На графике
Высоко только у некоторых · RTO и backoff по соединениям, число обрывов по регионам и провайдерам
Где смотреть
Посмотреть повторные передачи проблемного соединения в захвате пакетов на стороне сервера или через bcc tcpretrans -s (показывает номера последовательности), а через ss -ti посмотреть mss, pmtu и backoff этого соединения. С сервера отправить на адрес игрока маленький ping и ping на 1 500 байт с включённым DF (ping -M do -s 1472) и сравнить
Подтверждает
Пакеты, заполненные до MSS, с одним и тем же номером последовательности повторно передаются снова и снова с удваивающимся интервалом, а пакеты поменьше проходят. ICMP о превышении размера (фильтр Wireshark icmp.type == 3 and icmp.code == 4) не приходят, на маленький ping ответ есть, а большой ping с DF пропадает без ответа
Опровергает
Если вместе с большими пропадают и мелкие пакеты, это потери, не зависящие от размера («Переполнение очереди в узком месте (потери от перегрузки)», «Смена маршрута и неисправный путь ECMP»). Если ICMP о превышении размера приходят и pmtu в ss -ti уменьшается, поиск MTU пути работает правильно
Чем проверить
Инструменты инфраструктуры (игровой код не нужен)
Подробнее
С tcp_mtu_probing=1 чёрная дыра распознаётся только после нескольких секунд таймаутов повторной передачи (соответствует tcp_retries1=3), и лишь тогда MSS снижается до 1 024 байт. Всё это время фриз, поэтому tcp_mtu_probing оставляют последней страховкой. В первую очередь нужно ограничение MSS, которое предотвращает проблему заранее.
Источники
RFC 1191: Path MTU discoveryIETF Поиск MTU пути: о слишком большом пакете сообщает ICMP «fragmentation needed and DF set» (тип 3, код 4)
IP SysctlLinux kernel tcp_mtu_probing: 0 выключено, 1 только при обнаружении чёрной дыры, 2 всегда (начальный MSS tcp_base_mss). tcp_retries1 по умолчанию 3
net/ipv4/tcp_timer.cLinux kernel Если повторные передачи по RTO идут tcp_retries1 раз подряд, это считается обнаружением чёрной дыры: включается поиск MTU и MSS снижается
iptables-extensions(8) — Linux manual pagenetfilter TCPMSS --clamp-mss-to-pmtu: обход проблемы, когда большие пакеты застревают на участке, блокирующем ICMP, через ограничение MSS в SYN
tcp(7) — Linux manual pageLinux man-pages TCP_MAXSEG: максимальный размер сегмента исходящих пакетов. Если задать его до подключения, меняется и MSS, который сообщается другой стороне
ping(8) — Linux manual pageiputils -M do включает DF и не отправляет пакеты больше известного ядру MTU пути, -s задаёт размер данных (8 байт заголовка ICMP сверх него)