Анатомия игровых лагов
Русский

Анатомия
игровых лагов

Справочник объясняет, откуда берутся микрофризы, телепортация персонажей и дисконнекты. Причины разделены на 13 слоёв, от экрана игрока до базы данных на сервере. Для каждой причины указаны способ проверки и ответственная команда, а в экспериментах можно менять условия и смотреть, что получится. Примеры взяты в основном из MMO, но большая часть относится к онлайн-играм любого жанра.

00С чего начать

Четыре фактора, которые вызывают лаги

Причин больше сотни, но факторов, из которых складываются лаги, по сути четыре. Пакеты приходят поздно, приходят неравномерно, не приходят совсем, или кто-то перестаёт считать. Игры прячут эти факторы разными приёмами, а то, что проступает, когда спрятать не удалось, и есть «форма» лага, которую мы видим.

В MMO мир на экране игрока перерисовывается по пакетам, которые присылает сервер. Частота зависит от игры, но обычно сервер рассчитывает состояние игры 10–30 раз в секунду (один такой расчёт называют тиком), выбирает из результата только изменения вокруг каждого игрока и отправляет их пакетами. ПК игрока читает пришедшие пакеты и рисует картинку. Поэтому лаги чаще всего сводятся к тому, как игра показывает «пакеты, которые не пришли вовремя».

Бывают случаи и за пределами этих четырёх факторов. Если сервер и ПК игрока считают одно и то же по-разному (разные правила перемещения, баг), то даже при исправной линии связи персонажа откидывает назад или появляются невидимки. Признак такого лага: он повторяется в одном и том же месте или при одном и том же действии, независимо от пинга.

От фактора к симптому

Аналогия

Представьте доставку посылок. Если доставка всегда занимает 3 дня, это задержка. Если одна посылка идёт день, а другая пять, это джиттер. Посылка пропала: это потери. Сортировочный центр закрылся: это остановка. Игры выкручиваются приёмами вроде «если посылка опоздала или не пришла, угадать её содержимое по соседним (интерполяция, экстраполяция)» и «если не пришла, попросить отправить ещё раз (повторная передача)».

Для начала о масштабах времени

Почти всё, что говорят о лагах, измеряется в миллисекундах (ms, 1/1000 секунды). Достаточно запомнить несколько чисел из таблицы ниже, и речь команды разработки и команды инфраструктуры станет намного понятнее.

ОриентирВремяЧто это значит

Свойства очередей, общие для всех слоёв

CPU, диск, база данных, роутер, линия провайдера. Слои разные, а устройство у них одно. Есть воркеры, которые обрабатывают запросы (ядра CPU, потоки, соединения с БД и т. п.), и перед ними выстраивается очередь. Пока воркеры свободны, очередь пуста, но когда загрузка (утилизация) переваливает за 80–90%, очередь резко растёт. Если запросы приходят к одному воркеру в случайные моменты, среднее ожидание при утилизации 50% равно времени обработки, при 80% оно больше в 4 раза, при 90% в 9 раз. Вот и ответ на вопрос «У CPU ещё 10% запаса, почему же лагает?». К тому же цифра CPU на экране мониторинга обычно усреднена по нескольким ядрам и за 1–5 минут, поэтому скрывает и одно ядро, загруженное на 100%, и нагрузку, которая навалилась всего на несколько секунд.

Что разбирает этот справочник и чего в нём нет

Справочник разбирает причины лагов во время игры в онлайн-играх: от ПК или телефона, который рисует картинку, через домашнюю сеть, провайдера и ЦОД до серверов и баз данных. Облачный гейминг, где картинка игры приходит видеопотоком, голосовой чат, работающий отдельным сервисом, и скорость патчей и загрузок устроены иначе, поэтому здесь не рассматриваются. Впрочем, сетевые причины внутри них (Wi-Fi, bufferbloat, перегрузка линий связи и т. п.) те же, что описаны здесь.

01Общая карта

Путь пакета: от ввода до БД на сервере

Когда игрок нажимает кнопку умения, сигнал проходит через его ПК, домашнюю сеть, провайдера и ЦОД и попадает на сервер. Результат, обработанный несколькими слоями внутри сервера, проходит те же слои в обратном порядке и отрисовывается на экране. Всего слоёв 13, и затор в любом из них оборачивается лагом. Нажмите на слой на карте ниже, чтобы перейти к его главе.

02Попробуйте сами

Лаборатория лагов

Небольшая симуляция: один сервер, одна линия связи, один ПК. Ломайте условия по одному и смотрите, как возникают микрофризы, телепортация, откидывание назад, перемотка, слоумо, задержка ввода, фриз и дисконнект. Таймлайн пакетов показывает линией, когда пакет отправлен и когда он пришёл. Чем сильнее наклон линии, тем дольше шёл пакет, а × отмечает потерянный пакет.

03Поиск по тому, что видно

Каталог симптомов

Игроки жалуются коротко: «лагает». Но по форме лага о причине можно понять довольно многое. Маленькая картинка у каждого симптома показывает путь персонажа на экране. Точки наложились друг на друга: персонаж стоял. Точки разошлись: он ускорился или перескочил вперёд.

Микрофризы

Движение теряет плавность: короткие остановки чередуются с рывками. Если пинг в норме, скорее всего, проблема в кадрах на ПК игрока (клиент или ОС). Если пинг скачет, вероятнее джиттер в Wi-Fi или на линии связи. Учтите, что внутриигровой пинг обычно измеряется в игровом цикле, который выполняется раз в кадр, поэтому при скачках кадров может скакать и значение пинга.

Телепортация

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

Откидывание назад

Персонаж бежит вперёд, и его утягивает обратно на только что пройденное место. Картинка на экране игрока (предсказание) разошлась с решением сервера. Ввод не дошёл до сервера (потери), серверная проверка перемещения его отклонила, или клиент и сервер по-разному считают движение.

Перемотка

Замерший экран снова оживает, и накопившиеся движения, удары и урон проносятся разом на большой скорости. Где-то по пути пакеты копились, а потом разом освободились. Типичные случаи: TCP ждёт повторной передачи, сервер нагоняет отставание, клиент не успевает обрабатывать пакеты.

Слоумо

Всё движется медленно. Применение умений и перемещение монстров выглядят растянутыми. В зависимости от устройства сервера скорость может остаться прежней, и тогда проблема проявляется как микрофризы и телепортация. Сервер не успевает вовремя завершать тики. Линия связи в порядке, поэтому пинг, измеренный вне игры, не меняется. Внутриигровой пинг может немного вырасти, если в него входит ожидание обработки на сервере. Проверьте резкий рост онлайна, расчёт зоны видимости, рассылку, нехватку памяти.

Задержка ввода

Между нажатием и результатом проходит заметное время. При этом картинка может оставаться плавной. Пинг (время пути туда и обратно) слишком велик, или где-то растёт очередь. Проверьте расстояние, очередь роутера, Nagle (функция TCP, которая копит мелкие пакеты и отправляет их вместе), серверные очереди. Если пинг низкий, а управление всё равно ватное, проверьте ПК игрока (V-Sync, низкий FPS) или архитектуру, где каждое действие ждёт подтверждения сервера (глава о моделях синхронизации).

Фриз

Всё на экране ненадолго (от 0,5 с до нескольких секунд) замирает, а потом снова движется. Целиком встал сервер (GC, дедлок, синхронный вызов), ненадолго оборвалась связь или остановился ПК игрока.

Съеденные действия / роллбэк

Действие, которое точно было сделано, как будто не происходило, или его результат отменяется намного позже. Запрос потерялся (потери, переполнение очереди), сервер решил иначе, чем показал экран игрока (разный момент проверки, отказ после опережающего фидбека), или сбой случился во время сохранения (блокировки или отказ БД, падение сервера).

Дисконнект

Посреди игры соединение рвётся, и игрока возвращает на экран входа или в окно переподключения. За время таймаута не пришло ни одного пакета. Проверьте долгие обрывы связи, таймаут простоя, падение или перезапуск сервера, сервер или ПК игрока, который стоял дольше таймаута (долгая загрузка). Если игра просто закрылась без сообщения, сначала проверьте аварийное завершение клиента (краш, нехватка памяти), а соединение потом.

Ошибка входа / бесконечная загрузка

В игру не пускает, или всё застревает на экране загрузки или входа. Переполнено звено, которое принимает новые подключения (очередь подключений сервера, файрвол, сервер авторизации, БД). Особенно часто сразу после техработ.

Невидимки / фантомы

NPC, монстра или игрока, которые должны быть рядом, нет только на вашем экране, или уже исчезнувший объект остался только у вас. Со скоростью это обычно не связано: выпал один пакет или не удалась отрисовка. Проверьте разницу каналов или фаз, потерянные уведомления о появлении и исчезновении объектов, пакеты, отброшенные во время загрузки, ошибки загрузки ассетов. Решающая подсказка: появляется ли объект, если уйти из зоны видимости и вернуться.

04Архитектура синхронизации

Модели синхронизации и ощущения

Одна игра нормально играется и при пинге 150 ms, а другая кажется неповоротливой даже при 60 ms. И это бывает не только в экшен-играх. Если подключение одно и то же, разница обычно возникает из-за того, как клиент и сервер распределили, «что решается, когда и кем», то есть из-за архитектуры синхронизации. Часть таких решений принята намеренно, а часть действительно сделана плохо.

Все сетевые игры решают одну и ту же задачу. Между сервером и ПК игрока всегда есть разница во времени, и кто-то из двоих должен решить, что делать с тем, что «ещё не подтверждено». Вариантов, по сути, четыре.

  • Ждать: ничего не показывать, пока сервер не подтвердит. Это точно, но пинг напрямую становится временем отклика.
  • Показать сразу, исправить потом: действие игрока проигрывается мгновенно, а если у сервера другой результат, его поправляют. Быстро, но иногда видны откидывание назад и отмена действий.
  • Запланировать заранее: сообщать о событии вместе с моментом в будущем, например «удар по земле через 1,5 с». Если анимация подготовки длится дольше пинга, пинг вообще не заметен.
  • Все считают одно и то же: обмениваться только вводом, а считать у всех одинаково (lockstep, роллбэк). Данных передаётся мало, но задержка одного игрока расходится на всех.

Поэтому чувствительность к пингу сильнее жанра определяют два вопроса: сколько раз одно ключевое действие ждёт ответа сервера и хватает ли с запасом времени, которое дают правила игры, на «пинг + время реакции человека».

Распространённые модели синхронизации

МодельКак работаетГде встречаетсяКак выглядит при пинге 150 msСлабые места
Запрос-ответ
Показ после подтверждения сервера
По нажатию клиент спрашивает сервер и проигрывает действие, только когда придёт ответ.Пошаговые, карточные и idle-игры; интерфейсы магазина, обмена и крафта; применение умений и предметов в старых MMOЛюбое действие начинается примерно на 0,2 с позже. В пошаговых играх почти незаметноСерии действий; интерфейсы, где на одном экране несколько запросов к серверу
Синхронизация состояния + интерполяция
Авторитетный сервер
Сервер каждый тик присылает состояние игры, а клиент дорисовывает движение между двумя состояниями.Отображение других игроков и монстров в большинстве MMOДругих игроков видно такими, какими они были примерно 0,2 с назад. Обычно почти незаметноДжиттер (неравномерность интервалов между пакетами) и потери → телепортация; низкий тикрейт
Клиентское предсказание + серверная коррекцияВвод игрока применяется сразу, а когда приходит результат сервера, клиент сравнивает и поправляет.Шутеры (FPS), экшен-MMO, перемещение в большинстве MMOУправление мгновенное. Изредка короткое откидывание назадЧастые коррекции, если клиент и сервер считают по-разному
Компенсация задержки
Проверка попадания с отмоткой на сервере
Сервер отматывает время назад к моменту, который видел атакующий, и там проверяет попадание.Шутеры (FPS), нон-таргет экшеныСтрелявшему всё кажется честным, а тот, в кого попали, говорит: «Я же спрятался, а в меня всё равно попали»Обида у того, в кого попали. Чем выше пинг атакующего, тем дальше отмотка и тем хуже
Синхронизация команд и точек назначенияОтправляется только намерение вроде «иди сюда» или «атакуй эту цель», а дальше обе стороны считают сами.MMO с перемещением по клику, бой с таб-таргетом, некоторые MOBAТолько старт чуть запаздывает, перемещение и атаки плавныеЕсли маршруты или результаты разошлись, нужна коррекция
Планирование событий
По времени сервера
О событии сообщают вместе с моментом в будущем («начать во время сервера T»), и каждый клиент проигрывает его в этот момент.Паттерны рейдовых боссов, кат-сцены, события в точно назначенное времяЕсли предупреждение длиннее пинга, влияния практически нетЕсли сообщение пришло позже запланированного момента, начало пропускается
Детерминированный lockstepВвод всех игроков собирается, и один и тот же ход у всех считается одинаково. Задаётся фиксированная задержка применения ввода (input delay).RTS (наподобие StarCraft), некоторые кооперативные игры и головоломкиЛюбой ввод запаздывает на одну и ту же величину (это маскируют звуком и индикацией сразу по нажатию). При большом джиттере фриз у всехДжиттер, потери, самый медленный игрок
Роллбэк
Предсказание, затем отмотка
Игра предсказывает ввод соперника и идёт дальше, а при ошибке отматывает время назад и пересчитывает.Файтинги (в духе GGPO), некоторые экшен- и спортивные игрыУправление почти мгновенное (задержка применения ввода обычно 1–3 кадра). Анимация соперника иногда перескакивает на несколько кадровПри большом пинге отмотка становится длиннее и выглядит как телепортация
Клиентский авторитетКаждый клиент сам определяет свои результаты, а сервер только пересылает и записывает их.Некоторые мобильные и казуальные игры, схемы P2P и с ретранслятором (relay)На своём экране всё гладко. Результаты расходятся с тем, что видят другиеЧиты; «я же попал, но не засчитало»

Реальные игры смешивают эти модели. Обычно модель выбирают под каждое действие: для перемещения предсказание, для умений опережающий фидбек с последующим подтверждением, для паттернов боссов планирование событий, для обмена запрос-ответ.

Что общего у игр, в которые комфортно играть даже при пинге 150 ms

1. Ни одно действие не ждёт ответа от сервера. По нажатию кнопки анимация, звук и эффекты стартуют сразу (опережающий фидбек), а результат сервера используется только там, где задержка не бросается в глаза, например в цифрах урона.

2. Время, которое дают правила игры, заметно больше пинга. Если босс предупреждает об атаке за 1–2 с, увернуться легко, даже когда пакет приходит примерно на 0,2 с позже, а на реакцию человека уходит 0,25 с. Если у умения игрока есть время каста, подтверждение сервера успевает прийти, пока заполняется полоса каста, и ожидание прячется внутри каста. Это главная причина, по которой MMO с таб-таргетом малочувствительны к пингу. И наоборот, короткое предупреждение около 0,5 с уже при пинге 150 ms трудно заметить и успеть увернуться (см. эксперимент с окнами реакции ниже).

3. Серии действий принимаются заранее. Если есть буферизация ввода (очередь умений), которая принимает следующее умение, даже нажатое до конца кулдауна, между звеньями комбо не вклинивается путь туда и обратно.

4. Джиттер поглощается. Буфер интерполяции и проигрывание по времени сервера превращают пакеты, которые идут «обычно 150 ms, иногда 250 ms», в ровный поток, который всегда отстаёт примерно на 250 ms. Картинка показывает чуть более далёкое прошлое, зато движение плавное. К постоянной задержке человек быстро привыкает, а к неравномерной привыкнуть трудно. Хорошо сделанные игры сами увеличивают и уменьшают буфер вслед за ростом и падением джиттера.

5. Решение сервера совпадает с тем, что видел игрок. Уклонения и попадания проверяются на тот момент, который видел игрок (компенсация задержки), или правила изначально не зависят от позиции (бой с выбором цели).

6. Задержка одного игрока не заставляет ждать остальных. При авторитетном сервере у остальных всё в порядке, даже если у одного игрока плохой пинг. В lockstep или в схеме с хостом ощущения всех определяет самый медленный игрок.

Как отличить намеренную архитектуру от ошибочной

Иногда чувствительность к пингу заложена в архитектуру намеренно, а иногда это следствие ошибки.

Может быть намеренным выбором
  • Короткие окна реакции: игры, где интерес как раз в коротком окне, например парирование с окном 0,2 с или идеальное уклонение. Время на реакцию неизбежно сокращается на величину пинга, а джиттер сбивает тайминг, поэтому это смягчают компенсацией задержки или региональными серверами.
  • Подтверждение сервером против читов: результаты, которые ни в коем случае нельзя подделать (валюта, предметы, рейтинги), правильно применять только после подтверждения сервера.
  • Lockstep: самая практичная схема, чтобы синхронизировать сотни юнитов одним только вводом. Взамен задержку применения ввода (input delay) подстраивают под пинг.
  • Честность: иногда компенсацию задержки намеренно ослабляют, чтобы тот, в кого попадают, не страдал из-за чужого высокого пинга.
Признаки того, что, скорее всего, сделано неправильно
  • Управление прямое, с клавиатуры или геймпада, но даже перемещение и обычная атака ждут подтверждения сервера. Без предсказания пинг напрямую определяет отзывчивость управления. При управлении командами, как в перемещении по клику, ожидание ответа сервера гораздо менее заметно, поэтому в MOBA и других жанрах такую схему иногда выбирают намеренно.
  • Несколько запросов к серверу на одно действие в интерфейсе: если «открыть окно → получить список → подтвердить → купить» выполняются отдельными запросами, при пинге 150 ms всё вместе займёт 0,7–0,8 с. Их можно объединить в один.
  • Пинг линии низкий, но управление стабильно «ватное»: стоит проверить алгоритм Нейгла (стандартное поведение TCP, когда мелкие пакеты копятся и отправляются вместе; отключается через TCP_NODELAY), двойное ожидание, когда запросы копятся до следующего тика и результат тоже уходит только на следующем тике, и схему, где ответ на каждое действие приходит только после сохранения в БД. Такое же ощущение дают V-Sync и низкий FPS на ПК игрока.
  • «Подтверждение, потом следующий ввод» без очереди умений: между всеми звеньями комбо вклинивается путь туда и обратно, и DPS падает тем сильнее, чем выше пинг.
  • Проигрывание сразу по приходу: если проигрывать всё в порядке получения, без буфера интерполяции и без времени сервера, джиттер напрямую превращается в микрофризы анимации.

Причины лагов в архитектуре синхронизации

Отклик только после ответа сервера (модель запрос-ответ) Request-response (no client-side feedback)

После нажатия кнопки нет ни анимации, ни звука, пока не придёт ответ сервера. Скорость отклика становится равна пингу.

Почему: Умения, перемещение и подбор предметов проигрываются только после подтверждения сервера → Следствие: С момента нажатия никакой реакции в течение пути туда и обратно плюс ожидания тика → На экране: При пинге 150 ms каждое действие запаздывает примерно на 0,2 с

Симптомы: Задержка ввода · Основной ответственный Команда разработки · Разработка клиента · Совместно Команда разработки · Разработка сервера

Протокол с множеством последовательных обменов (chatty) Chatty protocol / sequential round trips

Если для одного действия нужно несколько обменов с сервером по очереди, пинг умножается на их число.

Почему: Открытие магазина → запрос списка → проверка цены → покупка → обновление инвентаря, каждое отдельным запросом → Следствие: Следующий запрос уходит только после ответа на предыдущий → На экране: При пинге 150 ms одна покупка занимает почти 1 с. Загрузки подозрительно долгие

Симптомы: Задержка ввода, Ошибка входа / бесконечная загрузка · Основной ответственный Команда разработки · Разработка сервера · Совместно Команда разработки · Разработка клиента

Нет буферизации ввода умений No input/spell queue

Если следующее умение можно нажать только после подтверждения сервера, что предыдущее закончилось, в каждую связку вклинивается путь туда и обратно.

Почему: Ввод следующего умения принимается только «после подтверждения предыдущего» → Следствие: Между умениями появляется пустой промежуток длиной в пинг → На экране: Между приёмами связки появляются паузы, и чем выше пинг, тем ниже DPS

Симптомы: Задержка ввода, Съеденные действия / роллбэк · Основной ответственный Команда разработки · Разработка клиента · Совместно Команда разработки · Разработка сервера

Короткое окно реакции, которое съедает пинг Timing window too short for latency + reaction

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

Почему: Короткие окна реакции, например предупреждение об атаке босса за 0,5 с или окно парирования 0,2 с → Следствие: Предупреждение игрок видит поздно (задержка на пути к нему + интерполяция), и его ввод тоже приходит поздно (задержка на пути к серверу + ожидание тика) → На экране: Точно увернулся, а удар прошёл, парирование «съело»

Симптомы: Съеденные действия / роллбэк, Задержка ввода · Основной ответственный Команда разработки · Разработка сервера · Совместно Команда разработки · Разработка клиента, Команда инфраструктуры · Серверная инфраструктура

Проверка попадания без компенсации задержки Server-now hit validation

Если сервер проверяет попадание только по «текущей позиции на сервере», результат расходится с тем, что игрок видел на своём экране.

Почему: Противник на экране игрока стоит там, где был примерно 0,2 с назад (при пинге 150 ms и интерполяции 100 ms) → Следствие: Сервер проверяет по текущей позиции, и там, куда целился игрок, цели уже нет → На экране: Точно попал, а промах. По движущейся цели приходится стрелять с упреждением

Симптомы: Съеденные действия / роллбэк · Основной ответственный Команда разработки · Разработка сервера · Совместно Команда разработки · Разработка клиента

Чрезмерная компенсация задержки Excessive lag compensation

Если отматывать время слишком далеко в пользу атакующего, в того, кто уже спрятался, всё равно попадают.

Почему: Ради атакующего с высоким пингом сервер проверяет попадание с большой отмоткой назад → Следствие: На экране того, в кого попали, он уже был в укрытии → На экране: «В меня попали, когда я уже был за стеной», преимущество у игроков с высоким пингом

Симптомы: Съеденные действия / роллбэк · Основной ответственный Команда разработки · Разработка сервера

Клиентский авторитет Client-authoritative results

Если каждый клиент сам определяет свои результаты, на экране игрока всё плавно, но результаты расходятся с экранами других, и игра уязвима для читов.

Почему: Позицию и попадания определяет клиент, а сервер только пересылает → Следствие: Два игрока утверждают, что каждый попал первым, а сервер не может это проверить → На экране: Противник телепортируется или проходит сквозь стены, «я попал, а урона нет»

Симптомы: Телепортация, Съеденные действия / роллбэк · Основной ответственный Команда разработки · Разработка сервера · Совместно Команда разработки · Разработка клиента

Ожидание самого медленного игрока в lockstep Lockstep waits for the slowest peer

В схеме, где все вместе рассчитывают один и тот же ход, при опоздании ввода одного игрока ждут все.

Почему: Каждый ход можно рассчитать, только собрав ввод всех игроков → Следствие: Ввод одного игрока приходит поздно из-за джиттера или потерь → На экране: У всех одновременно замирание, в тяжёлых случаях окно «Ожидание игрока»

Симптомы: Фриз, Микрофризы, Задержка ввода · Основной ответственный Команда разработки · Разработка сервера · Совместно Команда разработки · Разработка клиента

Ошибки предсказания в роллбэк-неткоде Rollback misprediction

Игра предсказывает ввод соперника и показывает результат заранее, а при ошибке отматывает назад и пересчитывает. Чем больше пинг, тем глубже отмотка.

Почему: Соперник сменил ввод (не так, как предсказано) → Следствие: Реальный ввод приходит с опозданием на половину пинга, и на столько же приходится отматывать назад и пересчитывать → На экране: Движение соперника проскакивает несколько кадров или внезапно меняется

Симптомы: Телепортация · Основной ответственный Команда разработки · Разработка клиента

Воспроизведение сразу по приходу без меток времени Events played on arrival (no timestamps)

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

Почему: События «начало атаки», «запуск эффекта» выполняются сразу по приходу → Следствие: У каждого пакета своё время доставки, и интервалы скачут → На экране: Серия атак то ускоряется, то замедляется, тайминг паттернов босса каждый раз разный

Симптомы: Микрофризы, Перемотка · Основной ответственный Команда разработки · Разработка клиента · Совместно Команда разработки · Разработка сервера

Двойное ожидание тика Double tick quantization

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

Почему: Полученный запрос обрабатывается в следующем тике → Следствие: Результат тоже копится и уходит в следующем тике отправки → На экране: Сетевой пинг низкий, а отклик стабильно запаздывает примерно на 1,5 интервала тика. На 10-тиковом сервере в среднем 0,15 с, в худшем случае 0,2 с

Симптомы: Задержка ввода · Основной ответственный Команда разработки · Разработка сервера

Слишком строгая серверная проверка Over-strict server validation

Если сервер слишком строго проверяет скорость перемещения, кулдауны и дальность, он отклоняет даже нормальный ввод, пришедший пачкой из-за джиттера.

Почему: Жёсткие критерии вроде «расстояние, доступное за один тик» или «допуск по кулдауну 0 ms» → Следствие: Если из-за джиттера две команды приходят в одном тике, это засчитывается как нарушение правил → На экране: Откидывание назад, умение отклоняется, хотя кулдаун прошёл

Симптомы: Откидывание назад, Съеденные действия / роллбэк · Основной ответственный Команда разработки · Разработка сервера

Архитектура с хостом-игроком Listen server / host advantage

Если сервером служит ПК одного из игроков, его подключение и производительность ПК определяют ощущения всех.

Почему: Сервером служит ПК хоста (P2P, listen-сервер) → Следствие: Медленное подключение или ПК хоста сказывается на всех, а у самого хоста пинг 0 → На экране: Преимущество только у хоста, когда хост выходит, у всех фриз или дисконнект

Симптомы: Микрофризы, Фриз, Дисконнект · Основной ответственный Команда разработки · Разработка сервера · Совместно Команда разработки · Разработка клиента, Команда инфраструктуры · Серверная инфраструктура

Отказ сервера после опережающего фидбека Client-side feedback rejected by server

Если сервер потом не засчитывает удар или умение, которые экран игрока уже показал, результат, который игрок точно видел, отменяется.

Почему: Эффект удара и анимация умения проигрываются до подтверждения сервера (опережающий фидбек) → Следствие: Сервер заново проверяет дальность, позицию цели, кулдаун и ресурсы и отклоняет действие → На экране: Кровь брызнула, а урона нет; анимация умения проиграна, а эффекта нет; запустился только кулдаун

Симптомы: Съеденные действия / роллбэк, Откидывание назад · Основной ответственный Команда разработки · Разработка клиента · Совместно Команда разработки · Разработка сервера

Расхождение расчёта пути при синхронизации команд Command sync with divergent pathing

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

Почему: При перемещении кликом и преследовании монстром отправляется только точка назначения, а путь клиент рассчитывает сам → Следствие: Из-за различий в данных ландшафта, столкновений с другими персонажами или порядка расчёта объект идёт не тем путём, что на сервере → На экране: Монстр проходит сквозь стену и вдруг перескакивает на другое место, персонаж после клика как бы скользит и меняет направление

Симптомы: Телепортация, Откидывание назад · Основной ответственный Команда разработки · Разработка сервера · Совместно Команда разработки · Разработка клиента

Низкая частота отправки снапшотов Low snapshot / update rate

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

Почему: Ради экономии трафика обновления позиций отправляются всего 5–10 раз в секунду → Следствие: Для плавной картинки буфер нужен в 2 раза длиннее интервала между пакетами (200–400 ms), а если сделать его коротким, потеря одного пакета уже даёт фриз → На экране: Смена направления у противника видна поздно и расходится с проверкой попадания. При коротком буфере микрофризы, при потерях телепортация

Симптомы: Микрофризы, Телепортация, Съеденные действия / роллбэк · Основной ответственный Команда разработки · Разработка сервера · Совместно Команда разработки · Разработка клиента

05Охват проблемы

Когда тормозит один игрок или сбоит одна сторона

Больше всего путаницы в жалобах на лаги, когда страдают лишь несколько человек или только одна сторона. Как один игрок с плохой связью выглядит для остальных и тормозят ли из-за него другие, полностью зависит от того, как сервер обрабатывает ввод, и от модели синхронизации. В этой главе разобран и случай, когда из двух клиентов, запущенных на одном ПК, NPC не видно только в одном.

Если тормозят только отдельные игроки или подключения

Большинство современных MMO построены на авторитетном сервере. Все результаты определяет сервер, а клиент рисует то, что получил. В такой схеме лаги чаще всего видны только у того, у кого плохая связь.

  • Сам игрок с плохой связью получает задержку ввода: действия, которым нужно подтверждение сервера, например умения или подбор предметов, запаздывают на величину пинга. Перемещение благодаря предсказанию видно сразу, но при большом джиттере (неравномерность интервалов между пакетами) его ещё и откидывает назад, а другие игроки у него телепортируются.
  • Остальные видят лишь, как персонаж этого игрока замирает, а потом проматывает несколько шагов разом (перемотка) или телепортируется. Собственное управление и движение монстров у них в порядке. Если у игрока только высокий пинг, без джиттера и потерь, его персонаж просто плавно движется чуть позади реальной позиции. Лагающим в чужих глазах игрока делают прежде всего джиттер и потери, пинг влияет меньше.
  • Если плохая связь только у определённого провайдера или региона, симптомы выше разом появляются у всех этих игроков. Сервер видит, что неравномерно приходит только их ввод, поэтому и ложные срабатывания проверки перемещения или античита концентрируются на них.
  • Если тормозит только на определённом персонаже, в первую очередь подозревают данные этого персонажа, а уже потом линию связи. Персонаж, у которого скопились тысячи предметов или писем, при каждом входе и сохранении читает и записывает в несколько раз больше данных, чем остальные. Различить просто: зайдите тем же персонажем с другого ПК или подключения и посмотрите, тормозит ли так же.

Но бывают и схемы, где один медленный игрок тормозит всех. Их объединяет одно: «кто-то ждёт этого игрока».

  • Все ждут одного и того же хода: lockstep (RTS), кооперативный контент с пошаговой синхронизацией. Если ввод одного игрока опоздал, встают все. Даже без джиттера, при одной лишь большой задержке, ввод всех применяется с опозданием, равным пингу самого медленного игрока.
  • Сервер ждёт, пока отправит данные медленному игроку: блокирующая отправка (вызов отправки, который останавливается и ждёт, пока в буфере отправки появится место), синхронная обработка. Тормозят все, кого обслуживает этот серверный поток. Обычно для каждого игрока заводят отдельную очередь отправки и не ждут. Тогда лаги видны только у медленного игрока, а если его очередь слишком разрастается, дисконнект случается только у него.
  • Медленный игрок играет центральную роль: P2P (игроки соединяются напрямую, без сервера) или listen-сервер (ПК игрока одновременно служит сервером), где хостом выступает ПК этого игрока, а также события, которые продвигаются только с правами лидера группы. Если игра для снижения нагрузки на сервер поручает расчёт перемещения монстров клиенту ближайшего игрока, монстры, которых обсчитывает этот игрок, у всех на экране двигаются с микрофризами.
  • Проверка попадания отматывается к картинке медленного игрока: компенсация задержки. Медленный игрок попадает честно, а тот, в кого попадают, обижается: «Я уже спрятался, а в меня попали». Поэтому глубину отмотки ограничивают. Предел у каждой игры свой, примерно от 0,2 до 1 с (в движке Source по умолчанию 1 с).

Как всё выглядит при разных способах обработки ввода на сервере

Как сервер обрабатывает вводЧто видит сам медленный игрокКак медленный игрок выглядит для другихСобственная игра остальных
Обработка раз в тик
Фиксированный тик, весь полученный ввод разом
Результат умения запаздывает на пинг плюс ожидание тика (задержка ввода). При строгой проверке перемещения откидывание назадЗамирает, потом сразу несколько шагов (перемотка, телепортация). Если пинг высокий, но джиттера нет, движение плавноеНе влияет
Обработка сразу по приходу
Событийная модель, применение и рассылка сразу по получении
Задержка ввода на величину пинга. Быстрее лишь на время ожидания тикаДвижение то ускоряется, то замедляется (слабая перемотка). Несколько умений, пришедших пачкой, срабатывают в один моментНе влияет
Буфер ввода на игрока
Ввод копится у каждого игрока, по одному за тик
Подтверждение запаздывает на длину буфераОтносительно плавно. Когда буфер пустеет, ненадолго стоит на местеНе влияет
Проверка попадания с компенсацией задержки
Отмотка к тому, что видел атакующий
Попадает туда, куда целился (в пределах лимита отмотки)Его атаки попадают даже после того, как цель спряталасьОбидные попадания (распространяется)
Lockstep, ожидание ходаЗадержка ввода. Если ввод опоздал, фризФриз у всехФриз. Даже при простом опоздании задержка ввода (распространяется на всех)
Блокирующая отправка, синхронная обработка
Сервер ждёт этого игрока
Фриз, затем перемоткаТормозят все, кого обслуживает этот серверный потокСлоумо, фриз (распространяется на игроков этого потока)
Хост у медленного игрока
P2P, listen-сервер
У самого пинг 0Микрофризы на экранах у всехЛаги у всех
Монстрами управляет медленный игрок
Перемещение монстров считает клиент
На своём экране монстры в порядкеЕго монстры замирают, потом телепортируютсяВсе, кто сражается с этими монстрами (распространяется)

Два клиента на одном ПК, и только в одном не видно NPC

Если один человек запустил на одном ПК два клиента и NPC не видно только в одном, линия связи почти наверняка ни при чём. Оба клиента работают через один роутер и одно подключение. Разница возникает в одном из трёх мест.

  1. Сервер не отправил данные этому клиенту: другой канал, инстанс или фаза квеста (фазирование: механика, которая показывает разных NPC в зависимости от прогресса), сбой порядка регистрации в зоне видимости, лимит отправки на соединение, баг сессий, из-за которого один ПК или один IP считается одним игроком, ограничение на мультиклиент.
  2. Сервер отправил, но клиент выбросил: уведомление о появлении пришло во время загрузки и отброшено; пачка данных о появлении сразу после входа потерялась из-за переполнения буфера приёма или ненадёжного канала доставки (unreliable: потерянное не отправляется повторно); потерян опорный снапшот (полное состояние, от которого отсчитываются изменения, когда передаются только они); новый NPC с переиспользованным ID принят за старого; пакеты перехватил другой клиент из-за конфликта фиксированного UDP-порта; фоновое окно отстаёт в обработке, и переполняется буфер приёма; оценка времени сервера сбилась, и показ откладывается.
  3. Клиент получил, но не смог отрисовать: два клиента одновременно пишут в один файл кэша, и модель не загружается; не хватает видеопамяти (VRAM); различаются настройки, например лимит отображаемых персонажей; не совпадают версии или данные.

Три самые надёжные подсказки: видна ли табличка с именем, хотя модели персонажа нет (сервер отправил, не удалась отрисовка), появляется ли NPC, если уйти из зоны видимости и вернуться (пропущено одно уведомление о появлении) и становится ли лучше, если вывести окно проблемного клиента на передний план (ограничение обработки в фоновом окне). И наоборот, «фантом», например уже убитый монстр, который стоит только на экране игрока, означает пропущенное уведомление об исчезновении.

Проблемы только у части игроков

Игрок с плохой связью движется на чужих экранах рывками Laggy player seen by others (bursty inputs)

Ввод игрока с плохим подключением приходит на сервер неравномерно, пачками. Если сервер в каждом тике применяет всё, что успело прийти, другие видят, как этот персонаж замирает, а потом делает сразу несколько шагов.

Почему: Команды перемещения тормозящего игрока приходят неравномерно: в одном тике 0, в другом по 2–3 → Следствие: Сервер применяет их разом в тике получения, и позиция персонажа меняется ступеньками → На экране: На экранах других игроков только этот персонаж замирает, а потом разом проскакивает вперёд. Остальное в порядке

Симптомы: Перемотка, Телепортация · Основной ответственный Команда разработки · Разработка сервера · Совместно Внешние стороны · Внешние стороны

Перемотка на сервере, который обрабатывает ввод сразу по приходу Event-driven processing of bursty inputs

На сервере, который обрабатывает и рассылает пакеты сразу по приходу, действия тормозящего игрока, пришедшие пачкой, выполняются подряд и немедленно.

Почему: Запросы умений и перемещения от тормозящего игрока приходят пачкой → Следствие: Сервер выполняет их по порядку сразу при получении и тут же рассылает всем → На экране: Другие видят, как этот игрок применяет несколько умений в одно мгновение или движется как в ускоренной перемотке

Симптомы: Перемотка · Основной ответственный Команда разработки · Разработка сервера · Совместно Команда разработки · Разработка клиента

Размер буфера ввода на игрока Per-player server input buffer (jitter buffer)

Если сервер немного накапливает ввод каждого игрока и берёт по одной команде за тик, на чужих экранах движение плавное, но момент, когда действие самого игрока подтверждается сервером, сдвигается на столько же.

Почему: Сервер накапливает ввод тормозящего игрока в буфере и применяет по одной команде за тик → Следствие: Маленький буфер часто пустеет, и персонаж встаёт на месте или сервер двигает его, угадывая по последнему вводу, а большой буфер задерживает подтверждение ввода самого игрока → На экране: С маленьким буфером другие видят замирания, с большим результат умений самого игрока появляется поздно (задержка ввода)

Симптомы: Микрофризы, Задержка ввода · Основной ответственный Команда разработки · Разработка сервера · Совместно Команда разработки · Разработка клиента

Ложные срабатывания проверок у абонентов одного провайдера Anti-cheat / movement validation false positives on bad ISPs

У игроков на подключениях с большим джиттером ввод приходит пачками и часто попадает под серверную проверку скорости и кулдаунов.

Почему: Вечером растёт джиттер на подключениях определённого провайдера или региона → Следствие: Нормальный ввод, пришедший пачкой, сервер считает превышением скорости или нарушением кулдауна → На экране: Только у абонентов этого провайдера откидывание назад и отказы умений, в тяжёлых случаях сервер кикает игрока (дисконнект)

Симптомы: Откидывание назад, Съеденные действия / роллбэк, Дисконнект · Основной ответственный Команда разработки · Разработка сервера · Совместно Команда инфраструктуры · Сетевая инфраструктура

Один тормозящий участник группы и механики босса One laggy member in a synchronized mechanic

В рейдовых механиках, где все должны отреагировать в один и тот же момент, запоздалая реакция одного тормозящего игрока проваливает всю группу.

Почему: Общие механики вроде «всем разом разбежаться» или «одному нажать кнопку» → Следствие: Тормозящий игрок поздно видит предупреждение, и его ввод тоже приходит поздно → На экране: Вайп из-за одного игрока, остальные участники чувствуют, что «виноват тот, у кого лаги»

Симптомы: Съеденные действия / роллбэк, Задержка ввода · Основной ответственный Команда разработки · Разработка сервера · Совместно Команда разработки · Разработка клиента

Управление монстром у тормозящего клиента Monster movement delegated to a player client

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

Почему: Сервер поручает расчёт перемещения монстра клиенту ближайшего (или пришедшего первым) игрока → Следствие: Отчёты этого игрока о результатах приходят на сервер с опозданием или пачками → На экране: Только этот монстр на экранах всех вокруг замирает и телепортируется. У самого игрока, которому поручен монстр, всё нормально

Симптомы: Телепортация, Микрофризы, Перемотка · Основной ответственный Команда разработки · Разработка сервера

Раздутые данные отдельного персонажа One character with oversized data (inventory, mail, buffs)

У персонажа, у которого накопились тысячи предметов и писем или необычно много друзей, записей в чёрном списке и баффов, данных для загрузки при входе, сохранения и рассылки окружающим в разы больше, чем у других. Тормозит только этот персонаж, независимо от подключения.

Почему: У давно прокачиваемого персонажа в инвентаре и почте скопились тысячи предметов или наград за события → Следствие: При каждом входе, переходе между локациями и сохранении приходится читать и писать в БД соответствующий объём, и данные о снаряжении и баффах для рассылки окружающим тоже большие → На экране: Только у этого персонажа долгая загрузка при входе и замирания при открытии инвентаря или почты. Если сервер ждёт сохранения в игровом потоке, на мгновение замирают и окружающие

Симптомы: Ошибка входа / бесконечная загрузка, Задержка ввода, Фриз · Основной ответственный Команда разработки · Разработка сервера · Совместно Команда инфраструктуры · Инфраструктура БД

Разные каналы, инстансы и фазы Different channel / instance / phase

Если два персонажа находятся в разных каналах или инстансах или в разных «фазах», где набор видимых NPC зависит от прогресса квеста, они видят разные миры.

Почему: Второй персонаж попал в другой канал или находится на другом этапе квеста → Следствие: Этому персонажу сервер этот NPC не отправляет (это нормально) → На экране: NPC нет только у одного из них. Похоже на баг, но так задумано

Симптомы: Невидимки / фантомы · Основной ответственный Команда разработки · Разработка сервера · Совместно Команда разработки · Разработка клиента

Отбрасывание уведомлений о появлении во время загрузки Spawn messages dropped before the client is ready

Сразу после входа в зону сервер отправляет уведомления о появлении NPC вокруг, а клиент ещё загружает карту и отбрасывает эти уведомления.

Почему: Сразу после обработки входа сервер рассылает уведомления о появлении окружающих объектов → Следствие: Клиент ещё загружается, обработчика сообщений пока нет, и уведомления отбрасываются → На экране: Сервер считает их отправленными и повторно не шлёт. Пока игрок не выйдет из зоны видимости и не вернётся, NPC не видно

Симптомы: Невидимки / фантомы · Основной ответственный Команда разработки · Разработка клиента · Совместно Команда разработки · Разработка сервера

Сбой порядка регистрации в зоне видимости Interest-management race on enter/leave

Если момент регистрации персонажа в сетке видимости совпадает с моментом, когда NPC переходит в другую ячейку, уведомление о появлении этого NPC может потеряться.

Почему: Обработка входа, смены канала или телепорта совпадает по времени с перемещением NPC → Следствие: Этот NPC выпадает из расчёта «объектов, которые стали видны» → На экране: Не видно только нескольких определённых NPC, или остаётся NPC, который уже ушёл

Симптомы: Невидимки / фантомы · Основной ответственный Команда разработки · Разработка сервера

Потеря опорного снапшота Lost baseline for delta compression

Если сервер отправляет «только то, что изменилось с прошлого раза», то при потере первой полной посылки (опорного снапшота) последующие изменения применить невозможно.

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

Симптомы: Невидимки / фантомы, Телепортация · Основной ответственный Команда разработки · Разработка сервера · Совместно Команда разработки · Разработка клиента

Потеря уведомления об исчезновении (фантомные объекты) Missed despawn (ghost entity)

И наоборот, если пропущено уведомление «исчез», уже убитые или ушедшие NPC и игроки остаются только на экране этого игрока.

Почему: Уведомления о смерти, уходе или выходе из зоны видимости теряются или приходят не по порядку → Следствие: Клиент считает, что объект всё ещё на месте → На экране: Монстр не реагирует на удары, на месте стоит игрок, который уже вышел из игры

Симптомы: Невидимки / фантомы · Основной ответственный Команда разработки · Разработка сервера · Совместно Команда разработки · Разработка клиента

Потеря данных о появлении из-за наплыва сразу после входа Initial spawn burst lost (unreliable channel, receive buffer, fragmentation)

В момент входа в зону сервер разом отправляет данные о появлении десятков и сотен окружающих объектов. Если отправлять их по ненадёжному каналу доставки (unreliable) или если буфер приёма переполнится, пока клиент занят загрузкой и не читает сокет, часть данных пропадает и повторно не приходит.

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

Симптомы: Невидимки / фантомы · Основной ответственный Команда разработки · Разработка сервера · Совместно Команда разработки · Разработка клиента

Путаница из-за повторного использования ID объектов Entity ID reused without a generation counter

Если при возрождении убитого NPC сервер снова использует тот же ID объекта, клиент, пропустивший за это время уведомление об исчезновении, принимает новый NPC за старый.

Почему: NPC умирает и появляется снова с тем же ID объекта → Следствие: Клиент, пропустивший уведомление об исчезновении, считает объект «уже известным» и игнорирует уведомление о появлении или оставляет объект мёртвым → На экране: NPC нет только на одном экране или он лежит убитым, иногда выглядит как другой NPC

Симптомы: Невидимки / фантомы · Основной ответственный Команда разработки · Разработка сервера · Совместно Команда разработки · Разработка клиента

Конфликт фиксированного UDP-порта Two clients bound to the same local UDP port

Если клиент рассчитан на конкретный локальный порт, второй клиент на том же ПК не может занять порт или делит пакеты с первым.

Почему: Два клиента пытаются открыть один и тот же локальный UDP-порт (принудительно делят его через опцию повторного использования) → Следствие: ОС передаёт входящие пакеты только одному из сокетов или не гарантирует, какой из них получит пакет. Роутер и сервер тоже видят оба клиента под одним адресом → На экране: Один клиент не получает пакеты мира: не видно NPC и других игроков, или случается дисконнект

Симптомы: Невидимки / фантомы, Дисконнект, Ошибка входа / бесконечная загрузка · Основной ответственный Команда разработки · Разработка клиента · Совместно Команда разработки · Разработка сервера

Ошибка разделения сессий по IP или устройству Session keyed by IP or machine ID

Если сервер или промежуточный сервер различает соединения по IP или ID устройства, два клиента на одном ПК (с одним публичным IP) считаются одним игроком.

Почему: Таблица сессий строится по IP или по IP + ID устройства → Следствие: Данные второго клиента перезаписывают первую сессию или смешиваются с ней → На экране: В одном клиенте не видно NPC, а в другом случается дисконнект или приходят чужие данные

Симптомы: Невидимки / фантомы, Дисконнект · Основной ответственный Команда разработки · Разработка сервера · Совместно Команда разработки · Разработка клиента

Ограничение на несколько клиентов Multi-client restriction policy

Если модуль защиты или политика сервера ограничивает число клиентов на одном ПК, второй клиент не запускается или не подключается, либо у первого случается дисконнект. Некоторые игры блокируют только функции дополнительного клиента.

Почему: Модуль защиты обнаруживает повторный запуск, или сервер ограничивает дополнительные подключения с одного устройства → Следствие: Второй запуск или подключение отклоняется, либо один из клиентов отключается. Изредка блокируется только часть функций дополнительного клиента → На экране: Ошибка входа или дисконнект у одного клиента. В играх, которые блокируют только функции, у одного клиента не видно NPC или магазина

Симптомы: Ошибка входа / бесконечная загрузка, Невидимки / фантомы, Дисконнект · Основной ответственный Команда разработки · Разработка клиента · Совместно Команда разработки · Разработка сервера

Ограничение обработки в фоновом окне Background window throttling

Для клиента в фоновом окне игра, движок и ОС снижают частоту кадров и объём обработки. Полученные пакеты не успевают обрабатываться, копятся и переполняют буфер.

Почему: Ограничение кадров в фоне в настройках игры или графического драйвера (например, в драйвере NVIDIA задаётся от 20 до 200 в секунду), энергосбережение, настройка движка останавливаться в фоне. ОС тоже отдаёт приоритет по CPU и GPU окну на переднем плане → Следствие: За кадр обрабатывается меньше пакетов, очередь растёт, а при переполнении буфера приёма пакеты отбрасываются → На экране: Когда окно выводят на передний план, всё появляется разом, или некоторые NPC так и не появляются

Симптомы: Невидимки / фантомы, Перемотка, Дисконнект · Основной ответственный Команда разработки · Разработка клиента · Совместно Внешние стороны · Внешние стороны

Конфликт одновременного доступа к файлам кэша и ассетов Shared cache / asset file lock conflicts

Если два клиента одновременно пишут в одну папку кэша или блокируют файлы, один из них не может загрузить модели и текстуры NPC.

Почему: Два клиента одновременно пишут файлы кэша и патчей в одной папке установки → Следствие: Не удаётся заблокировать файл или читается наполовину записанный файл, и загрузка срывается → На экране: Табличка с именем видна, а модели персонажа нет, или NPC прозрачный

Симптомы: Невидимки / фантомы · Основной ответственный Команда разработки · Разработка клиента

Сбой стриминга из-за нехватки памяти или VRAM Memory / VRAM exhaustion

Когда два клиента делят видеопамять, для новых моделей и текстур не остаётся места, и часть объектов не рисуется.

Почему: Два клиента делят VRAM и RAM. Кроме того, ОС может в первую очередь урезать квоту видеопамяти фонового окна → Следствие: Движок не может загрузить новые модели и текстуры или постоянно выгружает и загружает их снова → На экране: NPC появляются с опозданием, размыты или не видны, микрофризы

Симптомы: Невидимки / фантомы, Микрофризы · Основной ответственный Команда разработки · Разработка клиента · Совместно Внешние стороны · Внешние стороны

Разные настройки отображения Different display settings

Если у двух клиентов различаются настройки вроде лимита отображаемых персонажей, скрытия табличек с именами и моделей NPC или режима для слабых ПК, они показывают разное.

Почему: Только в одном клиенте включён «лимит числа отображаемых персонажей» или режим для слабых ПК → Следствие: Дальние или низкоприоритетные NPC не рисуются (это нормально) → На экране: NPC нет только в одном клиенте

Симптомы: Невидимки / фантомы · Основной ответственный Команда разработки · Разработка клиента

Несовпадение версии клиента или данных Client version / data table mismatch

Если второй клиент установлен отдельно или не до конца пропатчен, он не знает новых ID NPC от сервера и молча их игнорирует.

Почему: Установка в другой папке или клиент, запущенный во время патча → Следствие: Получив неизвестный ID NPC или модели, клиент пропускает его → На экране: В одном клиенте не видно только недавно добавленных NPC

Симптомы: Невидимки / фантомы · Основной ответственный Команда разработки · Разработка клиента · Совместно Команда разработки · Разработка сервера

Бюджет отправки и приоритеты для каждого соединения Per-connection bandwidth budget and priority

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

Почему: В людных местах сервер отправляет данные в порядке важности в пределах лимита отправки для каждого соединения → Следствие: Для соединения с заниженной оценкой пропускной способности (например, у фонового окна, которое поздно подтверждает приём) объекты из конца очереди постоянно откладываются → На экране: Дальние NPC появляются поздно или не появляются только в одном клиенте

Симптомы: Невидимки / фантомы, Задержка ввода · Основной ответственный Команда разработки · Разработка сервера · Совместно Команда разработки · Разработка клиента

Отложенный показ объектов из-за ошибки оценки серверного времени Clock estimate error holds or discards entities

Если клиент неверно оценивает серверное время, только что пришедшие данные объекта он откладывает как «ещё из будущего» или отбрасывает как «слишком старые».

Почему: Оценка серверного времени у одного клиента сильно сбита (измерение во время загрузки, выход из режима сна) → Следствие: Время, на которое ведётся интерполяция, не совпадает со временем в данных объекта → На экране: Объект появляется с опозданием или стоит неподвижно

Симптомы: Невидимки / фантомы, Микрофризы · Основной ответственный Команда разработки · Разработка клиента

06Частая причина

Повторная передача TCP: почему она возникает и почему растёт задержка

Когда в серверных метриках растёт число повторных передач TCP (retransmission), часто растёт и число жалоб на лаги. Повторная передача означает, что «пакет пропал» или что отправитель «ошибочно решил, что он пропал». Причина может быть в любом месте маршрута, от Wi-Fi до сетевой карты сервера, а в соединении, которое, как игра, отправляет мелкие пакеты с большими промежутками, потеря одного пакета оборачивается остановкой на сотни ms. В этой главе собраны первопричины повторных передач, способы найти причину и пути решения.

Сервер отправляетИгра получает123×Пропал456124563Ожидание повторной отправки (зависит от способа восстановления)3В игру ничего не приходит: фриз3, 4, 5, 6 разом: перемотка
Соединение отправляет пакет каждые 50 ms, и пропадает один пакет 3. TCP передаёт данные только по порядку, поэтому, даже когда пришли 4, 5 и 6, игре они не отдаются, пока пакет 3 не будет получен повторно. Так одна потеря превращается в фриз и следующую за ним перемотку. Момент повторной отправки зависит от способа восстановления: примерно от одного RTT до «RTT + минимум 200 ms» по таймеру повторной передачи (см. ниже «Виды повторной передачи»).

Четыре причины, по которым повторная передача замедляет игру

  1. Ожидание порядка (HOL-блокировка): пока потерянный пакет не получен повторно, TCP не отдаёт игре пакеты, пришедшие после него. Потерялся один, и всё, что за ним, встаёт, а потом высвобождается разом (фриз, затем перемотка).
  2. Ожидание повторной отправки: отправитель повторяет пакет, только когда истечёт таймер повторной передачи (RTO). В Linux это «RTT + минимум 200 ms». Если потеряется и повторный пакет, ожидание каждый раз удваивается (0,3 с → 0,6 с → 1,2 с …).
  3. Thin stream (соединение, которое редко отправляет мелкие пакеты): быстрая повторная передача срабатывает по сигналу получателя «пришли 3 следующих пакета» (3 дублирующих ACK; ACK означает подтверждение «получил»). Игровые пакеты идут по одному раз в 50–200 ms, поэтому RTO часто наступает раньше, чем наберётся такой сигнал. Вот почему большие загрузки держатся нормально, а встаёт именно игра. RACK в современных Linux принимает решение уже по одному пришедшему следующему пакету и сильно сокращает этот разрыв, но если пакеты идут с интервалом около 200 ms, RACK тоже не быстрее RTO.
  4. Снижение объёма отправки: TCP считает потерю сигналом перегрузки и уменьшает объём, который можно отправить за раз (окно перегрузки). Если дошло до RTO, отправку приходится снова разгонять с одного пакета за раз. Тем временем новые пакеты копятся на сервере, и крупные обновления в людных местах задерживаются одно за другим.

Виды повторной передачи

ВидКогда происходитВремя до восстановленияКак выглядит в игре
Быстрая повторная передача
Fast retransmit
Следующие пакеты пришли раньше, и получатель сообщает о «пропуске в середине» (дублирующие ACK, SACK)RTT + время, за которое придут 3 следующих пакетаКороткая заминка. Чем плотнее идут пакеты, тем быстрее
RACK/TLP
Потери по времени, повтор последнего пакета
Позже отправленный пакет пришёл, а предыдущего всё нет в течение заданного времени; или ACK долго нет, и последний пакет отправляется ещё разВскоре после подтверждения следующего пакета (RACK; ждёт ещё около 1/4 RTT, потому что пакеты могли просто поменяться местами). Если следующих пакетов нет, около 2×RTT (TLP), а если неподтверждённый пакет всего один, ещё 200 ms с учётом отложенного ACKОтносительно короткая заминка даже в thin stream. По умолчанию в современных Linux
Повторная передача по RTO
Retransmission timeout
Ожидание истекло без каких-либо сигналовRTT + минимум 200 ms, удваивается при каждой неудачеФриз от сотен ms до нескольких секунд, затем перемотка; если затянется, дисконнект
Повторная передача SYNПропал сам запрос на подключение: переполнение очереди подключений (backlog), блокировка файрволом1 с, 2 с, 4 с, 8 с … (Linux 6.5 и новее до пяти раз повторяет с интервалом 1 с, затем удваивает; старые Windows начинают с 3 с)После нажатия кнопки подключения задержка ровно в целые секунды, например 1 или 3 с; если неудачи продолжаются, ошибка входа / бесконечная загрузка
Ложная повторная передача
Spurious retransmission
Пакет не терялся, но пришёл поздно или не по порядку, и отправитель, решив, что он потерян, отправил его сноваВосстанавливать нечего, но объём отправки всё равно снижается (Linux может отменить снижение, если распознает ситуацию по DSACK, сообщению получателя «уже получено», или по временным меткам)Лишняя нагрузка на линию, медленнее большие передачи. В метриках высокая только доля повторных передач
Проба нулевого окна (zero window probe)
Путают с повторной передачей
Пакет, который отправитель шлёт для проверки, пока буфер получателя заполнен и тот просит «пока не присылай»Пока получатель не начнёт читатьФриз. Линия в порядке, просто программа-получатель не успела прочитать данные вовремя

Как найти, где теряются пакеты

Доля повторных передач показывает, «какую часть отправленных пакетов пришлось отправить снова». Значение, накопленное с загрузки системы, скрывает текущие изменения, поэтому долю считают по приросту за фиксированный интервал, например за 1 минуту. Официального порога нет, но для среднего по всему серверу примерные ориентиры такие: ниже 0,1%: норма, 0,1–1%: у части игроков изредка заминки, выше 1%: заметно многим игрокам, выше 3%: серьёзно. В играх, где много мобильных или зарубежных игроков, обычный уровень выше. Поэтому вместе с самим числом смотрят, во сколько раз оно выросло относительно обычного. Среднее тянут за собой немногие плохие подключения, поэтому кратчайший путь к причине: разбивка по регионам, провайдерам, серверам и времени суток. Если на пути стоит устройство, которое принимает соединение и открывает новое к серверу (прокси, некоторые балансировщики нагрузки и шлюзы), метрики игрового сервера видят только участок между этим устройством и сервером. Повторные передачи на стороне игроков смотрят на этом устройстве.

Где смотретьЧто смотретьЧто это даёт
Весь сервер (Linux)Прирост между двумя запусками nstat с интервалом 1 минута: TcpRetransSegs ÷ TcpOutSegs, а также счётчики группы TcpExt: TCPTimeouts, TCPLossProbes и TCPLossProbeRecovery, TCPLostRetransmit, TCPSpuriousRTOs, TCPDSACKRecv, TCPSynRetransДоля повторных передач, сколько раз дошло до RTO, сколько отправлено TLP и сколько из них действительно закрыли потерю, сколько раз терялся даже повторно отправленный пакет, повторные передачи запросов на подключение. Много DSACK и Spurious означает «отправлено снова, хотя не терялось». В Linux OutSegs не включает повторные передачи, поэтому строгая доля равна RetransSegs ÷ (OutSegs + RetransSegs), но в районе 1% разница невелика
По соединениям (Linux)retrans (сейчас в восстановлении/всего), rto, backoff, rtt, cwnd, lost, reordering, bytes_retrans из ss -tiМного ли повторных передач только у определённых игроков или регионов, насколько вырос RTO (backoff показывает, сколько раз подряд RTO удваивался). bytes_retrans ÷ bytes_sent даёт долю повторных передач этого соединения
Каждая повторная передача (Linux)eBPF-утилита tcpretrans (bcc). -c считает по соединениям, -l включает TLPПри каждой повторной передаче выводит строку с IP и портом второй стороны и состоянием соединения. Лёгкий способ без захвата пакетов узнать, на каких диапазонах адресов игроков или на каких серверах они скапливаются
Сетевая карта сервераdropped, missed, crc из ip -s -s link; rx_missed_errors, rx_no_buffer_count, rx_crc_errors и т. п. из ethtool -S (названия зависят от драйвера, у mlx5 это rx_out_of_buffer и rx_discards_phy); 2-й столбец (dropped) и 3-й столбец (time_squeeze) в /proc/net/softnet_statОтбросила ли сетевая карта сервера пакеты сразу при приёме (кольцевой буфер, CPU) или неисправен кабель либо оптический модуль (CRC). В softnet_stat одна строка на каждый CPU, значения шестнадцатеричные. Если time_squeeze постоянно растёт, ядро CPU, которое обрабатывает приём, не успевает сделать работу вовремя
Облачная сетьУ AWS ENA: bw_in_allowance_exceeded, bw_out_allowance_exceeded, pps_allowance_exceeded, conntrack_allowance_exceeded, linklocal_allowance_exceeded из ethtool -S. В стандартном представлении CloudWatch их нет, поэтому их собирают отдельно агентом CloudWatchНе отбросились ли пакеты молча на лимите инстанса. Если значения растут, лимит превышен. У других облаков тоже есть лимиты пропускной способности и числа соединений в зависимости от размера VM
Коммутаторы, маршрутизаторы, файрволыCRC и входные ошибки на портах, выходные отбрасывания, превышения полисера, заполнение таблицы сессий, логи отбрасыванийОтброшены ли пакеты на участке оборудования ЦОД. Если средняя утилизация за 5 минут низкая, а выходные отбрасывания растут, это микробёрсты (очень короткие всплески трафика)
МаршрутПотери, которые тянутся до последнего узла в mtr или pathping. Чтобы увидеть потери около 1%, нужны сотни отправок и больше, а при отправке на тот же TCP-порт, что у игры (mtr -T -P PORT), результат точнееС какого узла начинаются потери. Если потери видны только на одном промежуточном узле, а дальше всё чисто, это устройство просто ограничивает ответы на измерения (ICMP). Маршруты туда и обратно могут различаться, поэтому измеряют и со стороны сервера в сторону игрока
Захват пакетов (на обоих концах)Фильтр Wireshark tcp.analysis.retransmission и фильтры того же семейства tcp.analysis.: fast_retransmission, spurious_retransmission, duplicate_ack, lost_segment, zero_windowЕсли исходный пакет есть в захвате отправителя, но нет у получателя, он потерялся между ними. Если он есть и у получателя, это ложная повторная передача или ACK задержался либо пропал на обратном пути. Пакеты, отброшенные в кольцевом буфере принимающего сервера, в захвате тоже выглядят как «потерянные между», поэтому их смотрят вместе со счётчиками сетевой карты
Windows ServerTCPv4\Segments Retransmitted/sec ÷ Segments Sent/sec в Системном мониторе, Network Interface\Packets Received Discarded, netsh int tcp show global, pktmon (встроен в Windows 10 1809 и Windows Server 2019 и новее)Динамика доли повторных передач, отбросила ли сетевая карта пакеты сразу при приёме, настройки TCP, в каком месте внутри Windows отброшены пакеты

Порядок проверки: при совместном разборе с командой инфраструктуры быстрее всего идти так.

  1. Когда и у кого: с какого момента выросла доля повторных передач и не концентрируется ли она на определённом регионе, провайдере, сервере или времени суток.
  2. Настоящие ли это потери: если вместе растут TCPSpuriousRTOs и DSACK, сначала подозревают ложные повторные передачи, когда опоздавший пакет приняли за потерянный.
  3. Приём на сервере: если в тот же момент выросли счётчики сетевой карты, softnet или лимитов облака, пакеты отброшены на стороне сервера.
  4. Оборудование ЦОД: смотрят счётчики отбрасываний и CRC, а также таблицы сессий на коммутаторах и файрволах.
  5. Внешний маршрут: запускают mtr в обе стороны, со стороны проблемного игрока и со стороны сервера, и ищут участок, где начинаются потери.
  6. Если всё ещё непонятно: одновременно снимают захват пакетов на обоих концах и сравнивают.

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

Как исправить

1. Не терять пакеты (устранение первопричины)

  • Кабель вместо Wi-Fi, 5 GHz или 6 GHz, SQM и ECN на роутере, чтобы реже переполнялись очереди
  • Распределять отправку обновлений внутри тика, чтобы сервер не выстреливал их все разом. Пачки от одного соединения сглаживать пейсингом (fq, BBR, ограничение скорости отправки)
  • Увеличить кольцевые буферы, распределить прерывания по нескольким ядрам, проверить лимиты облака
  • Заменить кабели и оптические модули с ошибками CRC, согласовать настройки дуплекса
  • Шейпер (ставит излишек в очередь и выпускает постепенно) вместо полисера (сразу отбрасывает излишек), увеличить допустимый burst
  • Оставить запас в таблицах файрвола и отслеживания соединений (conntrack), а также по числу пакетов в секунду на промежуточном оборудовании; пустить трафик в обе стороны через один и тот же файрвол
  • Не допускать чёрных дыр MTU: настроить MSS (максимальный объём данных в одном пакете) и разрешить ICMP-сообщения о превышении размера (поиск MTU оставить последней страховкой); поддерживать записи NAT и LB хартбитами от клиента

2. Восстанавливаться быстрее

  • Проверить, что SACK и временные метки не отключены в настройках сервера и не вырезаются промежуточным оборудованием (без SACK не работает и RACK-TLP)
  • Использовать RACK-TLP (по умолчанию в современных Linux и Android). То, что отправляет клиент, например ввод игрока, восстанавливает ОС клиента, и серверные настройки на это не влияют (в Windows TLP и RACK включены по умолчанию начиная с Windows 10 (1607) и Windows Server 2016, а новый RACK, который восстанавливает и потерянные повторные передачи, начиная с Windows Server 2022)
  • Для thin stream включить tcp_thin_linear_timeouts, в Linux 6.15 и новее снизить потолок RTO через TCP_RTO_MAX_MS
  • Держать TCP_NODELAY включённым для игровых соединений (если Nagle придерживает новые пакеты, у RACK пропадают следующие пакеты, по которым он судит о потере)
  • Для соединений между серверами во внутренней сети снизить минимальный RTO для маршрута (ip route … rto_min)
  • TCP_USER_TIMEOUT и игровые хартбиты, чтобы быстро разрывать мёртвые соединения и переподключаться

3. Снизить чувствительность к повторным передачам (архитектура)

  • Позиции и бой в реальном времени передавать по UDP и повторять только нужное (старую позицию повторять бессмысленно). Если в каждом пакете дублировать несколько последних вводов, потерю одного закроет следующий пакет
  • Разделить на разные потоки то, что требует порядка (чат, обмен), и пакеты реального времени (стримы QUIC, отдельные TCP-соединения и т. п.). Потери в одном потоке не блокируют другой
  • Если остаётесь на TCP, перезаписывать в буфере отправки старые позиции актуальным состоянием, чтобы они там не копились (TCP_NOTSENT_LOWAT и т. п.). Перемотка после долгого фриза становится короче
  • Прятать короткие заминки на экране буфером интерполяции и предсказанием. Остановку по RTO на сотни ms так спрятать трудно

Названия настроек: что включать и что легко перепутать

Восстановлением после потерь в основном управляют настройки операционной системы (ядра), и лишь несколько из них можно включить отдельно для игровых соединений как опции сокета. TCP_NODELAY, который часто путают с ними из-за названия, восстановление не ускоряет. Однако если его не включить (Nagle работает), новые пакеты во время восстановления задерживаются ещё сильнее. Ниже приведены настройки для Linux; в Windows названия и набор поддерживаемых настроек отличаются.

НастройкаГдеЧто меняетВнимание
TCP_NODELAYОпция сокетаОтключает Nagle. Мелкие сообщения уходят сразу, без накопленияУбирает ожидание 40–200 ms, которое бывает и без потерь. Сам таймер повторной передачи (RTO) не меняется. Но если Nagle включён, то, пока ждут восстановления, новые пакеты тоже придерживаются и после восстановления ждут ещё один RTT, а следующие пакеты, на которые опираются быстрая повторная передача и RACK, не уходят, и дело легко доходит до RTO. В играх его обычно включают
net.ipv4.tcp_recovery (RACK)Настройка ядраОбнаружение потерь по времени. Устойчиво к нарушению порядка и быстро восстанавливает даже thin streamПо умолчанию 1 (включено). Механизм появился в Linux 4.4, нынешний вид принял примерно к 4.18. С 6.17 RACK остался единственным способом обнаружения потерь, и значение 0 ничего не меняет. Не работает в соединениях без SACK
net.ipv4.tcp_early_retrans (TLP)Настройка ядраЕсли ACK долго нет (около 2×RTT), ещё раз отправляет последний пакет, чтобы быстро обнаружить потерю последних пакетов (tail loss)По умолчанию 3 (включено), 0 выключает. Работает только с SACK. Если неподтверждённый пакет (in-flight) всего один, ждёт ещё 200 ms и становится почти таким же медленным, как RTO
net.ipv4.tcp_sack, tcp_dsack, tcp_timestampsНастройка ядраВыборочное подтверждение (SACK, сообщает о пропусках в середине), уведомление о повторном получении (DSACK), измерение RTT (временные метки)По умолчанию всё включено. На некоторых серверах их выключили во время проблемы безопасности SACK в 2019 году и так и оставили. Без SACK не работают и RACK, и TLP
net.ipv4.tcp_thin_linear_timeouts / TCP_THIN_LINEAR_TIMEOUTSНастройка ядра / опция сокетаДля соединений, где неподтверждённых пакетов (in-flight) меньше 4, RTO не удваивается первые 6 разПо умолчанию выключено. Опцией сокета можно включить только для игровых соединений. Первый RTO не сокращает
TCP_RTO_MAX_MS / net.ipv4.tcp_rto_max_msОпция сокета / настройка ядра (Linux 6.15 и новее)Снижает потолок удваивающегося RTO (по умолчанию 120 с). Минимум 1 сНе даёт RTO вырасти до десятков секунд после серии потерь. Мёртвые соединения тоже обнаруживаются быстрее
net.ipv4.tcp_mtu_probingНастройка ядраЕсли крупные пакеты продолжают пропадать, уменьшает размер, чтобы пройти через чёрную дыру MTUПо умолчанию 0 (выключено). 1 = уменьшает размер, только когда повторные передачи идут около 3 с и есть подозрение на чёрную дыру (до этого соединение стоит). 2 = с самого начала стартует с 1 024 байт и понемногу пробует размер больше
ip route … rto_minНастройка маршрутаСнижает минимальный RTO для этого маршрута (по умолчанию 200 ms)Только для внутренней сети между серверами. Если снизить на интернет-участке, растут ложные повторные передачи. net.ipv4.tcp_rto_min_us в Linux 6.11 и новее задаётся на весь сервер и меняет заодно интернет-соединения. С 6.15 опцией сокета TCP_RTO_MIN_US можно снизить только для внутренних соединений
TCP_USER_TIMEOUTОпция сокетаСколько продолжать повторные передачи, прежде чем отказаться от соединенияВосстановление не ускоряет. Позволяет быстро разорвать мёртвое соединение и переподключиться. Если не задать, Linux разрывает соединение только после примерно 15 повторных передач, это около 15 минут (tcp_retries2)
SO_KEEPALIVE + TCP_KEEPIDLE и т. п.Опция сокетаПроверяет, живо ли неактивное соединениеС повторной передачей не связано. Нужно, чтобы не истекали записи NAT и LB и обнаруживались мёртвые соединения
Очередь fq + SO_MAX_PACING_RATE, BBRНастройка очереди / опция сокета / настройка ядраРавномерно распределяет отправку пакетов и снижает потери от всплесков трафика (burst: отправка большого объёма разом)Это «профилактика» потерь. Со скоростью восстановления не связано

Первопричины повторных передач TCP

Потери на беспроводном участке Wi-Fi / cellular link loss

Wi-Fi и мобильная сеть несколько раз повторяют передачу на беспроводном участке, а если и это не помогает, выбрасывают пакет. Выброшенный пакет TCP отправит повторно только спустя заметное время.

Почему: Слабый сигнал или сильные помехи, передача на беспроводном участке срывается раз за разом → Следствие: Если превышен лимит повторов беспроводного оборудования (обычно от нескольких до десяти с лишним раз), пакет выбрасывается → На экране: Фриз на всё время ожидания повторной передачи TCP, следующие пакеты ждут в буфере приёма, затем перемотка

Симптомы: Фриз, Перемотка, Телепортация · Основной ответственный Внешние стороны · Внешние стороны · Совместно Команда инфраструктуры · Серверная инфраструктура, Команда разработки · Разработка сервера, Команда разработки · Разработка клиента

Переполнение очереди в узком месте (потери от перегрузки) Tail drop at a congested bottleneck

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

Почему: Видео, загрузки и трафик других пользователей забивают узкое место → Следствие: Пока очередь заполнена, новые пакеты выбрасываются подряд (tail drop). Даже не выброшенные пакеты ждут в конце забитой очереди → На экране: Разом пропадает несколько пакетов: долгий фриз, потом перемотка, чаще по вечерам

Симптомы: Фриз, Перемотка, Откидывание назад · Основной ответственный Команда инфраструктуры · Сетевая инфраструктура · Совместно Внешние стороны · Внешние стороны, Команда разработки · Разработка клиента

Переполнение неглубоких буферов всплесками отправки Sender bursts overflow shallow buffers

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

Почему: В начале тика пакеты для всех игроков отправляются разом → Следствие: Мгновенно переполняется буфер порта коммутатора, где сходится трафик нескольких серверов (от сотен KB до нескольких MB на порт), или лимит облачного инстанса (средняя загрузка при этом низкая) → На экране: Телепортация и короткие фризы сразу у многих игроков, по средним метрикам причину не видно

Симптомы: Телепортация, Фриз, Перемотка · Основной ответственный Команда разработки · Разработка сервера · Совместно Команда инфраструктуры · Серверная инфраструктура, Команда инфраструктуры · Сетевая инфраструктура

Отбрасывание избытка полисером Traffic policing

Тарифы провайдеров, лимиты облачных инстансов и оборудование защиты от DDoS могут сразу отбрасывать пакеты сверх заданной скорости, не ставя их в очередь.

Почему: Мгновенный объём передачи превышает разрешённую скорость или разрешённый всплеск (burst) → Следствие: Пакеты сверх лимита отбрасываются сразу, без очереди (полисинг) → На экране: В моменты больших всплесков пропадает сразу несколько пакетов: фриз, потом перемотка. Средняя скорость при этом ниже лимита

Симптомы: Фриз, Перемотка, Телепортация · Основной ответственный Команда инфраструктуры · Сетевая инфраструктура · Совместно Команда инфраструктуры · Серверная инфраструктура, Команда разработки · Разработка сервера

Физические ошибки (неисправные кабели, оптические модули и разъёмы) Bit errors: bad cable, optics, dirty fiber

Повреждённый кабель, запылённый оптический разъём или выработавший ресурс оптический модуль дают битовые ошибки, и оборудование молча выбрасывает испорченные пакеты.

Почему: Из-за неисправного кабеля, оптического модуля или разъёма переворачиваются биты → Следствие: Оборудование отбрасывает пакеты с неверной контрольной суммой (CRC) → На экране: Только у тех, чей трафик идёт по этому пути, постоянно бывают короткие фризы с перемоткой, время суток не влияет

Симптомы: Фриз, Перемотка, Телепортация · Основной ответственный Команда инфраструктуры · Сетевая инфраструктура · Совместно Команда инфраструктуры · Серверная инфраструктура, Внешние стороны · Внешние стороны

Несовпадение дуплекса Duplex mismatch

Если на одной стороне включено автосогласование, а на другой скорость и дуплекс заданы жёстко, одна сторона работает в полудуплексе и под нагрузкой каждый раз теряет пакеты из-за коллизий.

Почему: Скорость и дуплекс жёстко заданы только на одной стороне → Следствие: Одна сторона работает в полном дуплексе, другая в полудуплексе, возникают коллизии и поздние коллизии → На экране: Обычно всё нормально, но при росте трафика у всех, чей трафик идёт через это устройство, фриз, потом перемотка

Симптомы: Фриз, Перемотка · Основной ответственный Команда инфраструктуры · Сетевая инфраструктура · Совместно Команда инфраструктуры · Серверная инфраструктура

Отбрасывание пакетов на принимающем сервере Receiver host drops (ring, softirq, CPU)

Пакеты дошли до сервера, но выбрасываются: переполнен кольцевой буфер NIC (буфер, где ненадолго лежат пришедшие пакеты) или загружено до предела процессорное ядро, на котором ОС обрабатывает приём.

Почему: Резкий наплыв игроков, все прерывания на одном ядре CPU, CPU steal на виртуальной машине, перегрузка виртуального коммутатора → Следствие: Отбрасывание в кольцевом буфере (rx_missed_errors и др., название зависит от драйвера) или в очереди приёма ядра (softnet dropped) → На экране: Когда игроков много, на всём сервере одновременно задержка ввода и короткие фризы

Симптомы: Задержка ввода, Фриз, Перемотка, Телепортация · Основной ответственный Команда инфраструктуры · Серверная инфраструктура

Отбрасывание пакетов файрволом или conntrack Stateful firewall / conntrack drops

Файрвол или conntrack в Linux (функция, которая записывает проходящие соединения в таблицу) выбрасывает пакеты, если таблица заполнена или состояние соединения кажется ему неверным.

Почему: Таблица отслеживания соединений заполнена (table full), или пакеты туда и обратно идут разными путями, и через файрвол проходит только одно направление (асимметричный маршрут) → Следствие: Файрвол считает, что пакет относится к «неизвестному соединению» или несёт «номер последовательности вне окна», и отбрасывает его → На экране: Когда таблица заполнена, новые подключения не проходят, а при расхождении маршрутов у игроков на этом маршруте после серии повторных передач дисконнект

Симптомы: Фриз, Дисконнект, Ошибка входа / бесконечная загрузка · Основной ответственный Команда инфраструктуры · Сетевая инфраструктура · Совместно Команда инфраструктуры · Серверная инфраструктура, Команда разработки · Разработка сервера, Команда разработки · Разработка клиента

Перегрузка промежуточного оборудования (файрвол, IPS, защита от DDoS) Inline appliance PPS / CPU overload

Файрволы, системы предотвращения вторжений (IPS) и оборудование защиты от DDoS проверяют каждый проходящий пакет. Как только поток превышает их возможности, необработанные пакеты выбрасываются.

Почему: В часы пик и на событиях идёт больше сотен тысяч мелких игровых пакетов в секунду, или правила проверки слишком тяжёлые → Следствие: Упор в лимит CPU или пакетов в секунду, оборудование отбрасывает пакеты. При ложном срабатывании блокируются и нормальные пакеты → На экране: Фризы и телепортация одновременно на всех серверах за этим оборудованием, хуже всего при наплыве игроков

Симптомы: Фриз, Перемотка, Телепортация, Дисконнект · Основной ответственный Команда инфраструктуры · Сетевая инфраструктура · Совместно Команда разработки · Разработка сервера

Чёрная дыра MTU (большие пакеты теряются раз за разом) PMTU black hole

Если на промежуточном участке допустимый размер пакета уменьшился, а уведомление «слишком большой» (ICMP) блокируется, большие пакеты пропадают, сколько бы раз их ни отправляли повторно.

Почему: На участке VPN или туннеля максимальный размер меньше, а уведомления о превышении размера блокируются файрволом → Следствие: Отправитель, не зная причины, раз за разом повторно передаёт тот же большой пакет, RTO каждый раз удваивается → На экране: Обычно всё нормально, но в моменты передачи больших данных (инвентарь, места скопления игроков, загрузка при входе) встают и все следующие мелкие пакеты: фриз, в итоге дисконнект или бесконечная загрузка

Симптомы: Фриз, Дисконнект, Ошибка входа / бесконечная загрузка · Основной ответственный Команда инфраструктуры · Сетевая инфраструктура · Совместно Команда инфраструктуры · Серверная инфраструктура, Команда разработки · Разработка сервера

Истечение записи NAT или балансировщика посреди соединения NAT / load balancer mapping expired mid-connection

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

Почему: Соединение, по которому какое-то время не ходят пакеты (игрок отошёл, сидит в лобби) → Следствие: NAT роутера, CGNAT провайдера, файрвол, балансировщик нагрузки или облачная группа безопасности удаляют неактивную запись → На экране: Как только игрок снова начинает двигаться, идут повторные передачи и затем дисконнект, или дисконнект сразу

Симптомы: Дисконнект, Фриз · Основной ответственный Команда разработки · Разработка клиента · Совместно Команда разработки · Разработка сервера, Команда инфраструктуры · Сетевая инфраструктура, Команда инфраструктуры · Серверная инфраструктура

Смена маршрута и неисправный путь ECMP Route change / bad ECMP member

Пакеты пропадают в течение нескольких секунд, пока меняется интернет-маршрут, или постоянно на соединениях, попавших на неисправный путь среди нескольких путей ECMP.

Почему: Пересчёт маршрутов BGP или неисправное оборудование либо линия связи на одном из нескольких путей (ECMP, LAG) → Следствие: Временные потери во время переключения маршрута или постоянные потери только у соединений на этом пути → На экране: Внезапный фриз на несколько секунд, потом перемотка, или «после перезахода лучше» (соединение попало на другой путь)

Симптомы: Фриз, Перемотка, Телепортация · Основной ответственный Команда инфраструктуры · Сетевая инфраструктура · Совместно Команда разработки · Разработка сервера, Внешние стороны · Внешние стороны

Ложные повторные передачи из-за скачков задержки Spurious RTO from delay spikes

Пакет цел и лишь ненадолго сильно задерживается. Если эта задержка дольше RTO, отправитель считает пакет потерянным и передаёт его повторно.

Почему: Bufferbloat, энергосбережение Wi-Fi, переключение состояний радиомодуля в мобильной сети или пауза виртуальной машины дают мгновенную задержку в сотни ms → Следствие: RTO истекает раньше, происходит повторная передача, вскоре приходит и оригинал (получатель получает дубликат) → На экране: Фриз и перемотку вызывает сам скачок задержки. Ложная повторная передача почти не удлиняет фриз, она только поднимает метрики повторных передач, и её принимают за потери

Симптомы: Фриз, Перемотка, Задержка ввода · Основной ответственный Внешние стороны · Внешние стороны · Совместно Команда инфраструктуры · Серверная инфраструктура, Команда разработки · Разработка клиента

Ложные быстрые повторные передачи из-за нарушения порядка Reordering triggers spurious fast retransmit

Если на нескольких путях или агрегированных линках порядок пакетов меняется, получатель дублирующими ACK сообщает «пакета не хватает», и отправитель повторно отправляет пакеты, которые не терялись.

Почему: Порядок перемешивают оборудование с балансировкой по отдельным пакетам, LAG (агрегирование линков) с распределением по пакетам и моменты смены маршрута → Следствие: Следующие пакеты приходят раньше, накапливаются 3 дублирующих ACK → быстрая повторная передача → На экране: На редкие игровые пакеты почти не влияет. Медленнее идут крупные обновления в местах скопления игроков и загрузка патчей, иногда микрофризы

Симптомы: Микрофризы, Задержка ввода · Основной ответственный Команда инфраструктуры · Сетевая инфраструктура · Совместно Команда инфраструктуры · Серверная инфраструктура

Задержка и потеря ACK (забитая отдача) ACK path congestion on asymmetric links

Данные дошли нормально, но если ACK «получено» задерживается или теряется в забитой очереди отдачи, отправитель считает данные потерянными и передаёт их повторно.

Почему: Дома отдачу забивает выгрузка видео или облачный бэкап → Следствие: ACK задерживаются в очереди роутера на сотни ms или выбрасываются при её переполнении → На экране: Игровые пакеты от сервера в основном приходят вовремя. Ввод игрока стоит в той же очереди отдачи и запаздывает: задержка ввода и откидывание назад, иногда ложные повторные передачи

Симптомы: Задержка ввода, Откидывание назад · Основной ответственный Внешние стороны · Внешние стороны · Совместно Команда разработки · Разработка клиента

Неподходящая настройка RTO RTO min too low or too high

Если слишком занизить минимальный RTO, от малейшей задержки возникают ложные повторные передачи, а значение по умолчанию (200 ms) для игры слишком велико, и каждая потеря даёт долгий фриз.

Почему: Минимальный RTO сильно занижен под ЦОД, или на интернет-участке оставлено значение по умолчанию → Следствие: Если мало, лавина повторных передач даже от мгновенной задержки, если много, долгое ожидание при каждой потере → На экране: При значении по умолчанию каждая потеря даёт фриз на сотни ms, потом перемотку. Если слишком занизить, фризы короче, но резко растут ложные повторные передачи и линия связи загружается зря

Симптомы: Фриз, Перемотка, Задержка ввода · Основной ответственный Команда инфраструктуры · Серверная инфраструктура · Совместно Команда разработки · Разработка сервера

Медленное восстановление потерь в thin stream Thin streams fall back to RTO

Когда мелкие пакеты отправляются редко, как в играх, RTO наступает раньше, чем соберутся «3 следующих пакета». От тех же потерь поток стоит намного дольше, чем при больших передачах.

Почему: Интервал между пакетами около 100 ms, поэтому неподтверждённых пакетов (in-flight) всего несколько → Следствие: Чтобы собрались 3 дублирующих ACK, нужно больше 300 ms, поэтому раньше срабатывает RTO (пинг + 200 ms), при серии потерь он удваивается → На экране: От одной потери фриз около 0,3 с, если потеряна и повторная передача, фриз почти на 1 с, потом перемотка

Симптомы: Фриз, Перемотка · Основной ответственный Команда разработки · Разработка сервера · Совместно Команда инфраструктуры · Серверная инфраструктура, Команда разработки · Разработка клиента

Удаление опций TCP промежуточным оборудованием Middlebox strips TCP options

Если некоторые файрволы или ускорители удаляют или меняют опции TCP, то при потере нескольких пакетов они восстанавливаются по одному за RTT или окно (сколько можно отправить за раз) становится маленьким, и передача замедляется.

Почему: «Нормализация TCP» на файрволе или старый ускоритель удаляют опции SACK, временных меток и масштабирования окна → Следствие: Если потеряно несколько пакетов, они восстанавливаются по одному за RTT, окно ограничено 64 KB → На экране: Каждая потеря даёт намного более долгий фриз (без SACK нельзя использовать и RACK-TLP), после которого перемотка. Большие передачи вроде патчей тоже идут медленно

Симптомы: Фриз, Перемотка · Основной ответственный Команда инфраструктуры · Сетевая инфраструктура · Совместно Команда инфраструктуры · Серверная инфраструктура

Нулевое окно (остановка, похожая на повторную передачу) Zero window, often mistaken for retransmission

Если программа-получатель не успевает вовремя читать сокет и буфер заполняется, отправитель останавливает передачу и шлёт только пробы нулевого окна. С линией связи это не связано.

Почему: Кадр на клиенте завис или поток сервера заблокирован, и сокет не читается → Следствие: Окно приёма становится 0, отправитель останавливает передачу и шлёт только пробы (интервал постепенно растёт) → На экране: Фриз, потом перемотка. В захвате пакетов видно «ZeroWindow», потерь нет

Симптомы: Фриз, Перемотка · Основной ответственный Команда разработки · Разработка клиента · Совместно Команда разработки · Разработка сервера, Команда инфраструктуры · Серверная инфраструктура

Повторная передача запроса на подключение (SYN) SYN retransmission on connect

Если запрос на подключение теряется из-за переполнения очереди подключений (backlog) или блокировки файрволом, ОС клиента отправляет его повторно через 1 с, а затем с растущими интервалами.

Почему: Сразу после техработ из-за наплыва подключений переполняется очередь подключений сервера, или файрвол либо защита от DDoS выбрасывают SYN → Следствие: ОС клиента повторно отправляет SYN через 1 с, затем через заданные интервалы (в старых Linux 1 с → 2 с → 4 с) → На экране: После нажатия кнопки входа задержка ровно в целые секунды (1 с, 3 с), при постоянных неудачах ошибка входа или бесконечная загрузка

Симптомы: Ошибка входа / бесконечная загрузка · Основной ответственный Команда разработки · Разработка сервера · Совместно Команда инфраструктуры · Серверная инфраструктура, Команда инфраструктуры · Сетевая инфраструктура, Команда разработки · Разработка клиента

07Распределение ответственности

Зоны ответственности команды разработки и команды инфраструктуры

Внешне лаги похожи, но исправляют их в разных местах. За код клиента и сервера и архитектуру синхронизации отвечает команда разработки, за линии связи, сетевое оборудование, серверы и серверы БД отвечает команда инфраструктуры. Проблемы на ПК и в домашней сети игрока, на участках провайдеров и у облачного провайдера ни одна из команд не может исправить напрямую, поэтому остаётся давать подсказки игрокам, отправлять запросы или искать обходные пути. На каждой карточке причины отмечены основной ответственный и кто участвует совместно, а если раскрыть на карточке блок «Цифры для ориентира · Способ проверки · Задачи по командам», видно, что делать каждой команде.

  1. Жалоба или алертСимптом, время с точностью до секунды, сервер и канал
  2. У когоОдин игрок или дом / определённый провайдер или регион / определённый сервер или канал / все
  3. Кого звать первымОсновной ответственный в карточках причин-кандидатов. «Куда смотреть сначала» в помощнике диагностики
  4. Что передатьIP и провайдер, причина дисконнекта, графики, последние изменения
  5. Совместная работаРазделить по задачам команд из карточки
Путь от поступившего тикета до задач, разбитых по командам. Сильнее всего ответственного определяет вопрос «у кого», а подробные критерии приведены в таблице ниже и в главе Диагностика по метрикам.
ОтветственныеЗона ответственностиТипичные способы исправления
Команда разработкиКлиентКод игрового клиента: кадры, GC, загрузка; интерполяция, экстраполяция, предсказание; сетевая часть клиента (включая отправку хартбитов и автоматическое переподключение)Правки кода, настройка буфера интерполяции и предсказания, изменение схемы загрузки, интервал хартбитов и логика переподключения, патчи клиента
Команда разработкиСерверКод игрового сервера: тики, потоки, блокировки; архитектура синхронизации; приём подключений (цикл accept, аргумент listen); ответы на хартбиты и очистка оборванных соединений; опции сокетов; проектирование запросов и транзакцийОптимизация логики, асинхронные вызовы, распределение нагрузки по тикам и локациям, очередь на вход, продолжение сессии по токену, опции сокетов (TCP_NODELAY и др.), проектирование запросов и индексов, патчи сервера
Команда инфраструктурыСетьЛинии связи и сетевое оборудование ЦОД (коммутаторы, маршрутизаторы, файрволы, балансировщики нагрузки, защита от DDoS), сетевые ACL, маршрутизация VPC и балансировщики нагрузки в облаке, провайдеры и пирингНастройка и замена оборудования, расширение линий и пиринга, смена маршрутов, эскалация провайдерам, настройка таймаутов простоя и лимитов сессий на балансировщиках нагрузки и файрволах
Команда инфраструктурыСерверы и ОССерверы и облачные инстансы (включая группы безопасности и отслеживание соединений), настройки ОС и ядра, NIC, среда деплоя и мониторингаРасширение мощностей и смена типа инстансов, настройки ядра (sysctl: somaxconn, conntrack и др.), группы безопасности и время отслеживания соединений, кольцевые буферы NIC и распределение прерываний, перенос cron и резервного копирования на другое время
Команда инфраструктурыСерверы БДСерверы и хранилища БД; настройки, репликация и резервное копирование БД; кэш-серверыРасширение БД, обеспечение IOPS хранилища, параметры БД и настройки репликации, настройка резервного копирования и контрольных точек
Внешние стороныИгрок, провайдер, облакоПК и домашняя сеть игрока, участки сети провайдеров (вне наших договоров), облачные провайдерыПодсказки игрокам (кабельное подключение и т. п.), запросы провайдерам и облачным провайдерам, обходные пути и смягчение на стороне игры

Ответственные по слоям и темам

Жирное число показывает, у скольких причин эта сторона основной ответственный, а +число показывает, в скольких она участвует совместно. Нажмите на ячейку, чтобы увидеть ниже эти причины и задачи команды.

Если граница неясна: основной ответственный там, где причина, остальные смягчают последствия и проверяют

Основной ответственный находится там, где первопричина, или там, где её можно устранить. Даже если причина в линии связи или оборудовании, команда разработки тем временем снижает последствия архитектурными решениями (буфер интерполяции, дублирование ввода, переподключение). А если причина в серверном коде, команда инфраструктуры, добавляя оборудование, лишь откладывает проблему. Границы, которые часто путают, определены так.

  • Дисконнект после бездействия: таймауты простоя на роутерах игроков и оборудовании провайдеров мы изменить не можем, а записи NAT в них надёжно обновляют только пакеты, уходящие изнутри. Поэтому клиент отправляет хартбиты и при разрыве автоматически переподключается, а сервер отвечает на хартбиты, при их отсутствии первым закрывает соединение и затем продолжает сессию по токену. Команда инфраструктуры сообщает значения таймаутов нашего оборудования и при необходимости увеличивает их.
  • Переполнение очереди подключений (backlog): реальный предел задают аргумент listen и цикл accept в серверном коде, поэтому основной ответственный здесь Разработка сервера, а «Серверы и ОС» отвечают за предел ядра (somaxconn) и SYN cookies.
  • Облако: группы безопасности и отслеживание соединений на инстансе относятся к зоне Серверы и ОС, сетевые ACL, маршрутизация VPC и облачные балансировщики нагрузки относятся к зоне Сеть.

«Сначала» в таблице показывает, кого звать первым; это определено подсчётом основных ответственных в карточках причин, подходящих под ситуацию. Если указаны двое, первый чаще всего бывает основным ответственным в этих карточках, а второго зовут сразу вместе с ним.

СитуацияЗадачи команды разработкиЗадачи команды инфраструктурыЧто смотреть сначала
Большие потери и джиттер у определённого провайдера или региона
СначалаКоманда инфраструктурыСеть
Адаптивный буфер интерполяции, дублирование ввода, устойчивая к потерям передача по UDP, выборка IP, порта и времени пострадавших из статистики потерь и повторных передач по соединениям, ослабление проверки перемещения с учётом состояния линииИзмерить маршрут в обе стороны тем же протоколом и портом, что у игры (mtr), исключить плохие маршруты, эскалировать провайдеру, добавить пиринг и линииРаспределение потерь и джиттера по провайдерам, доля повторных передач
Рост повторных передач TCP
СначалаКоманда инфраструктурыСетьКоманда разработкиСервер
TCP_NODELAY, распределение отправки тика внутри тика, своевременное чтение сокетов (против нулевого окна), поддержание записей NAT хартбитами, пакеты реального времени по UDP или через отдельное соединение, старые позиции не копятся в буфере отправки (TCP_NOTSENT_LOWAT)Устранить точки потерь (кабели, оптические модули, дуплекс, полисеры, отслеживание соединений на файрволе, MTU), настроить MSS, кольцевые буферы и распределение прерываний на серверах, настройки восстановления в ядре (RACK, tcp_mtu_probing)Прирост повторных передач (nstat), число нулевых окон, счётчики отбрасываний и CRC на NIC и портах коммутаторов
Тик не укладывается в бюджет из-за насыщения CPU сервера
СначалаКоманда разработкиСервер
Оптимизация расчёта зоны видимости и рассылки, разделение тика на несколько потоков, разделение переполненных локаций и каналов, число рабочих потоков по лимиту CPU, время тика в метрикахCPU и инстансы с высокой производительностью на ядро (частотой), алерты по загрузке каждого ядра, проверка CPU steal и троттлинга CPU контейнеров, разнесение ядер для прерываний и для потока тикаВремя тика, загрузка CPU по ядрам, steal, число эпизодов троттлинга (nr_throttled)
Медленные ответы БД
СначалаКоманда разработкиСерверКоманда инфраструктурыСерверы БД
Проектирование запросов, индексов и транзакций (короткие транзакции, единый порядок блокировок), асинхронные вызовы вне игрового потока, пакетные запросы и кэш, настройка размера пула соединений и таймаута ожиданияНаходить медленные запросы, планы выполнения и ожидания блокировок и передавать команде разработки; настройки контрольных точек, репликации и обновления статистики; IOPS хранилища; проверка, что число серверов × размер пула не превышает максимум соединений; расширение серверов БДЛог медленных запросов, ожидания блокировок, ожидание соединений, отставание репликации, IOPS
Ошибка входа сразу после техработ
СначалаКоманда разработкиСервер
Не давать потоку приёма подключений (цикл accept) застревать на другой работе, увеличить аргумент backlog в listen, система очереди на вход, объединение запросов при входе (убрать N+1), повторные попытки клиента с растущим и случайным интерваломsomaxconn и SYN cookies в ядре, лимиты сессий на файрволах и балансировщиках нагрузки, лимиты conntrack и файловых дескрипторов на серверах, прогрев кэша БД, заблаговременное масштабирование серверов перед событиямиListenOverflows, заполнение таблицы сессий и conntrack, число запросов при входе и ожидание соединений
Дисконнект после бездействия
СначалаКоманда разработкиКлиент
Клиент: отправлять хартбиты с интервалом не больше половины самого короткого таймаута простоя (чтобы, если один опоздает или потеряется, следующий успел до таймаута), при разрыве автоматически переподключаться. Сервер: отвечать на хартбиты, если их нет заданное время, первым закрывать соединение, продолжать сессию по токену.Собрать таймауты простоя балансировщиков нагрузки и файрволов на маршруте (Сеть) и время отслеживания соединений в облачных группах безопасности (Серверы и ОС), передать команде разработки, на своём оборудовании при необходимости увеличить. Таймауты роутеров игроков и CGNAT провайдеров изменить нельзяРаспределение времени простоя у оборванных соединений (если оно скапливается около одного значения, виновато устройство с таким таймаутом), тип сети (мобильная, проводная)
Сервер замирает в одно и то же время
СначалаКоманда разработкиСерверКоманда инфраструктурыСерверы и ОС
Случайно разносить по времени события «ровно в час», сохранения, таймеры и истечение кэша; дробить пакетные запросы на мелкие части; явно выбрать GC с короткими паузамиРазнести по времени cron, резервное копирование и сжатие логов и понизить их приоритет I/O; делать бэкап БД с реплики и равномерно распределять контрольные точки; проверить burst-кредиты диска; ограничить скорость передачи бэкаповВремя остановок в сравнении с расписанием задач (cron, бэкапы, пакетные задачи, контрольные точки), логи GC
DDoS и всплески трафика
СначалаКоманда инфраструктурыСеть
Передать команде инфраструктуры профиль игрового трафика (порты, размеры пакетов, пакеты в секунду), ограничить частоту запросов на аккаунт и персонажа, рано отсекать некорректные пакетыЗащита от DDoS (центр очистки трафика) с правилами под игровой трафик, сокрытие адресов серверов, лимиты пакетов в секунду на оборудовании; лимиты по IP с учётом общих IP провайдеров и компьютерных клубовПакеты в секунду, CPU и отбрасывания на оборудовании, доля неудачных подключений по регионам и провайдерам (проверка ложных срабатываний)
Проблемы с Wi-Fi или ПК игрока
СначалаВнешние стороныИгрок, провайдер, облакоКоманда разработкиКлиент
Индикатор состояния сети в игре (пинг, потери), автоматическая длина буфера интерполяции по джиттеру, тип сети и загрузка CPU ПК в логах, снятых в момент лагов, подсказки вроде «подключитесь кабелем»Исправить напрямую нельзя. Если жалобы скапливаются у одного провайдера или в одном регионе, переклассифицировать как проблему линии связиДанные о подключении и устройстве из жалоб, доля жалоб от одного провайдера или региона

Что приложить при передаче

Команда разработки → команда инфраструктуры

  • Точное время (с точностью до секунды, с часовым поясом) и длительность; продолжается ли сейчас
  • ID сервера и канала, охват (только у меня, определённый провайдер, весь сервер) и число затронутых игроков (относительно онлайна)
  • Название и форма симптома: для дисконнекта время простоя до разрыва, для фриза длительность и период повторения
  • IP, порт, провайдер и регион пострадавших (если плох один из нескольких маршрутов, без порта его не отличить), протокол игры (TCP, UDP) и порт сервера
  • Метрики игры: время тика, распределение пинга и потерь, число соединений с ростом повторных передач, причины дисконнектов (таймаут хартбита, сброс соединения (RST) и т. п.)
  • Текущий интервал хартбитов, таймаут неактивности на сервере, схема повторных попыток
  • Были ли недавно деплои или изменения настроек; какие причины уже проверены и исключены

Команда инфраструктуры → команда разработки

  • Метрики оборудования и линий за то же время (утилизация, счётчики отбрасываний и ошибок, число сессий) и метрики ОС сервера (ListenOverflows, заполнение conntrack, CPU steal)
  • Таймауты и лимиты устройств на маршруте: таймауты простоя балансировщиков нагрузки и файрволов, время отслеживания соединений в группах безопасности, лимиты числа сессий и пакетов в секунду
  • История изменений оборудования и линий и запланированные работы (замены, изменения настроек, бэкапы и cron, уведомления провайдеров о работах)
  • Номера обращений к провайдерам и облачным провайдерам и когда ждать ответа
  • Временные меры (обходные пути, ослабленные лимиты) и когда их планируют отменить
  • Где была причина, вывод и план предотвращения повторения
  • Что нужно сделать на стороне игры (интервал хартбитов, схема повторных попыток, ограничение числа соединений и т. п.)

Обеим командам: назначают одного ответственного за инцидент, ведут хронологию в одном общем чате и заранее сообщают время следующего обновления. Если основной ответственный переходит к другой команде, вместе с инцидентом передают и эту хронологию, чтобы не повторять те же проверки. По окончании по той же хронологии исправляют ответственных и задачи в карточке соответствующей причины.

Процесс игрового клиента

Сама игровая программа, которая работает на ПК или телефоне игрока. Даже при идеальной сети, если здесь запаздывают кадры, на экране появляются микрофризы. И от этого же слоя зависит, насколько хорошо игра маскирует плохую сеть.

Игра примерно 60 раз в секунду повторяет одно и то же: читает ввод, обрабатывает пришедшие пакеты, обновляет состояние игры на один шаг и рисует картинку. Один проход этого цикла называется кадром, и при 60 FPS на кадр отводится 16,7 ms (в мобильных играх на 30 FPS 33,3 ms). Если кадр запаздывает, картинка на это время замирает, а в следующем кадре разом сдвигается на всё накопившееся.

В сетевой части клиент занят тем, что «восполняет недостающую информацию». Позиции других игроков приходят с сервера с промежутками, поэтому движение между ними приходится дорисовывать (интерполяция); если пакеты перестали приходить, движение приходится угадывать (экстраполяция); а собственного персонажа игрока клиент двигает сразу, не дожидаясь подтверждения сервера (предсказание). Сбои этих приёмов игрок и видит как телепортацию, откидывание назад и микрофризы.

Аналогия

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

Причины лагов на этом слое

Всплески времени кадра Frame hitch

Расчёт одного кадра занимает в несколько раз больше времени, чем обычно, и картинка на миг замирает.

Почему: Наплыв эффектов умений, массовый спавн и полное обновление UI приходятся на один кадр → Следствие: Кадр не укладывается в 16,7 ms и занимает 50–300 ms → На экране: Картинка на миг замирает, а в следующем кадре все разом сдвигаются

Симптомы: Микрофризы, Фриз · Основной ответственный Команда разработки · Разработка клиента

Сборка мусора на клиенте Client GC (Unity C#, Unreal, Lua)

Пока освобождается использованная и уже ненужная память (мусор), вся игра стоит. Характерный признак: микрофризы через равные промежутки.

Почему: Каждый кадр создаются и выбрасываются временные строки, массивы и списки → Следствие: Когда мусора накапливается много, GC останавливает главный поток и освобождает память → На экране: Регулярные микрофризы раз в несколько секунд или десятков секунд

Симптомы: Микрофризы, Фриз · Основной ответственный Команда разработки · Разработка клиента

Синхронная загрузка и компиляция шейдеров в главном потоке Synchronous asset load, shader compile

Перед первой отрисовкой новой локации, монстра или эффекта игра останавливается, чтобы прочитать файлы и скомпилировать шейдеры.

Почему: Вход в новую локацию, первое появление незнакомого умения, снаряжения или монстра → Следствие: Главный поток ждёт чтения файлов и компиляции шейдеров → На экране: Фриз на 0,1–1 с только в первый раз, со второго раза всё нормально

Симптомы: Фриз, Микрофризы · Основной ответственный Команда разработки · Разработка клиента

Стриминг ассетов отстаёт из-за медленного накопителя Slow storage stalls asset streaming

На медленном накопителе вроде HDD текстуры и модели открытого мира читаются медленнее, чем перемещается игрок. Объекты появляются с опозданием, или игра дёргается, ожидая окончания чтения.

Почему: Быстрое перемещение на маунте или телепортом либо вход в людное место, где сразу нужно много новых текстур и моделей → Следствие: Медленный накопитель вроде HDD не успевает читать с нужной скоростью, запросы на чтение копятся, а завершения некоторых загрузок главный поток ждёт → На экране: Текстуры какое-то время размытые, здания и персонажи появляются с опозданием, а пока игра ждёт чтения, бывают микрофризы и фризы

Симптомы: Невидимки / фантомы, Микрофризы, Фриз · Основной ответственный Команда разработки · Разработка клиента · Совместно Внешние стороны · Внешние стороны

Нагрузка на рендеринг при большом скоплении игроков Render/animation cost of crowds

Когда в кадр попадают сотни игроков, как на осаде или у мирового босса, клиент не справляется уже с самой отрисовкой.

Почему: В одном кадре сотни персонажей и наложенные друг на друга эффекты → Следствие: Затраты на анимацию, тени, таблички с именами и эффекты растут пропорционально числу игроков → На экране: FPS падает с 60 до 15, микрофризы во всех движениях, ввод тоже запаздывает

Симптомы: Микрофризы, Задержка ввода · Основной ответственный Команда разработки · Разработка клиента

Узкое место: обработка пакетов в главном потоке Network processing on the main thread

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

Почему: В людном месте приходят тысячи обновлений в секунду → Следствие: Главный поток упирается в лимит обработки на кадр и не успевает всё прочитать → На экране: Движения других игроков отображаются всё позже и пачками

Симптомы: Перемотка, Задержка ввода · Основной ответственный Команда разработки · Разработка клиента · Совместно Команда разработки · Разработка сервера

Буфер интерполяции отсутствует или слишком короткий Missing/short interpolation buffer

Если отрисовывать пакеты сервера сразу после получения, джиттер (неравномерность интервалов между пакетами) целиком виден на экране.

Почему: Полученная позиция рисуется сразу, или буфер короче джиттера → Следствие: На опоздавших пакетах движение останавливается, на пришедших пачкой скачет вперёд → На экране: Другие персонажи двигаются рывками

Симптомы: Микрофризы · Основной ответственный Команда разработки · Разработка клиента · Совместно Команда разработки · Разработка сервера

Чрезмерная экстраполяция (dead reckoning) Over-extrapolation / dead reckoning

Пока пакеты не приходят, клиент продолжает двигать объект с последней известной скоростью, а обнаружив ошибку, возвращает его назад.

Почему: Пакеты перестали приходить, и объект продолжает двигаться с последним направлением и скоростью → Следствие: На самом деле противник остановился или сменил направление → На экране: Персонаж противника долго идёт в одну сторону, а потом резко переносится в настоящую позицию или проходит сквозь стену. Если пакеты приходят неравномерно, он то убегает вперёд, то его тянет обратно, и движение выглядит дрожащим

Симптомы: Телепортация, Микрофризы · Основной ответственный Команда разработки · Разработка клиента

Расхождение клиентского предсказания с сервером Prediction mismatch / reconciliation

Клиент заранее показал движение персонажа игрока, но сервер посчитал иначе, и персонажа утягивает на серверную позицию.

Почему: Клиент двигает персонажа до подтверждения сервера (предсказание) → Следствие: Сервер по-другому считает коллизии, скорость движения или баффы либо не получает команду → На экране: Когда приходит подтверждение, персонажа откидывает назад

Симптомы: Откидывание назад · Основной ответственный Команда разработки · Разработка клиента · Совместно Команда разработки · Разработка сервера

Лавина догоняющих шагов при фиксированном таймстепе Fixed-timestep catch-up / spiral of death

После одной остановки игра разом досчитывает накопившиеся шаги и из-за этого снова отстаёт.

Почему: Симуляция идёт с фиксированным шагом, и игра один раз останавливается → Следствие: Накопившиеся шаги считаются разом в одном кадре → На экране: Долгие кадры идут один за другим, и картинка скачет, или срабатывает лимит, и мир замедляется

Симптомы: Микрофризы, Перемотка, Слоумо · Основной ответственный Команда разработки · Разработка клиента

Ошибка синхронизации часов Clock sync error

Если клиент неверно оценивает серверное время, сбиваются момент интерполяции и проверка кулдаунов.

Почему: Время сервера синхронизируется один раз при входе и не корректируется, даже когда меняется пинг → Следствие: Момент интерполяции и время окончания кулдауна расходятся с сервером → На экране: Противник иногда дёргается, умение отклоняется, хотя кулдаун уже прошёл

Симптомы: Микрофризы, Съеденные действия / роллбэк · Основной ответственный Команда разработки · Разработка клиента

Потеря точности времени во float Float time precision loss on long sessions

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

Почему: Время с запуска игры накапливается во float или как есть передаётся в шейдеры → Следствие: Чем дольше работает клиент, тем больше наименьшая разница, которую может выразить float → На экране: Только в клиенте, проработавшем несколько дней, дрожат персонажи, анимации и эффекты с бегущей текстурой, а после перезапуска всё нормально

Симптомы: Микрофризы · Основной ответственный Команда разработки · Разработка клиента

V-Sync и очередь рендеринга V-Sync, render queue

Отрисованные GPU кадры по несколько штук ждут в очереди и выводятся в такт монитору, поэтому ввод доходит до экрана с опозданием.

Почему: Графический драйвер заранее держит в очереди 1–3 кадра → Следствие: Ввод доходит до экрана на столько же позже → На экране: Пинг низкий, а управление ватное и запаздывает

Симптомы: Задержка ввода, Микрофризы · Основной ответственный Команда разработки · Разработка клиента · Совместно Внешние стороны · Внешние стороны

Утечка памяти на клиенте Client memory leak

Чем дольше работает игра, тем больше памяти она занимает, всё сильнее тормозит и в итоге принудительно закрывается.

Почему: При переходах между локациями текстуры, UI и эффекты не освобождаются → Следствие: GC запускается чаще, памяти ОС не хватает, начинается своп → На экране: Через несколько часов игры микрофризы нарастают, потом игра принудительно закрывается (игроку это кажется дисконнектом)

Симптомы: Микрофризы, Дисконнект · Основной ответственный Команда разработки · Разработка клиента

Краш клиента Client crash

Игра закрывается из-за необработанной ошибки. Игроку это кажется дисконнектом, хотя сервер работает нормально.

Почему: Обращение по нулевой ссылке, нехватка памяти, ошибка графического драйвера → Следствие: Процесс игры принудительно завершается → На экране: Жалобы «вылетел из игры». У остальных в это же время всё в порядке

Симптомы: Дисконнект · Основной ответственный Команда разработки · Разработка клиента · Совместно Внешние стороны · Внешние стороны

Проверки модуля защиты игры (античита) Anti-cheat scan and heartbeat

Модуль защиты от взлома работает вместе с игрой и периодически выполняет проверки. Если проверка тяжёлая или хартбит (периодический сигнал «я жив») с сервером защиты запаздывает, появляются микрофризы или дисконнект.

Почему: Модуль защиты периодически проверяет память игры, запущенные программы и драйверы → Следствие: Во время проверки игровой поток стоит, или хартбит не уходит вовремя → На экране: Рывки через равные промежутки, в тяжёлых случаях дисконнект с сообщением об ошибке защиты

Симптомы: Микрофризы, Фриз, Дисконнект · Основной ответственный Команда разработки · Разработка клиента · Совместно Команда разработки · Разработка сервера

ОС и устройство клиента

Игра работает поверх Windows, Android или iOS и делит CPU, память и сеть с другими программами. Если операционная система поздно выделяет игре CPU, снижает частоту ради экономии батареи или приостанавливает фоновые приложения, возникают лаги.

Планировщик операционной системы (механизм, который решает, чья очередь занимать CPU) делит процессорное время между программами. Игра, антивирус, браузер и программы обновления ждут «своей очереди», и ОС по очереди выделяет им ядра на время от нескольких до десятков ms (квант времени). Игре на переднем плане ОС даёт чуть больший приоритет, но если задач больше, чем ядер, ждать приходится и игре, и это ожидание задерживает кадры.

Сеть тоже проходит через ОС. Пакеты, принятые сетевой картой или Wi-Fi-чипом, попадают в буфер приёма драйвера и ОС и ждут, пока игра их заберёт. Если игра занята и забирает их поздно, буфер переполняется, а если забирает разом, получается перемотка. На мобильных устройствах особенно важно, что ОС ради экономии батареи переводит радиомодуль в режим энергосбережения и то и дело приостанавливает само приложение.

Аналогия

ОС похожа на шеф-повара, который распределяет одну-единственную кухню между несколькими поварами. Даже если игра готовит срочное блюдо, ей придётся ждать, когда плиту займёт повар по имени «антивирусная проверка». А если на кухне становится слишком жарко (нагрев), шеф убавляет огонь.

Причины лагов на этом слое

Фоновые процессы занимают CPU Background CPU contention

Когда ядра заняты антивирусной проверкой, обновлением Windows, программой для стримов или видео в браузере, игровой поток не получает процессорного времени и ждёт.

Почему: Другие программы надолго занимают ядра CPU → Следствие: Игровой поток ждёт, пока планировщик выделит ему ядро → На экране: Кадры запаздывают, обработка полученных пакетов тоже

Симптомы: Микрофризы, Перемотка · Основной ответственный Внешние стороны · Внешние стороны · Совместно Команда разработки · Разработка клиента

Энергосбережение и тепловой троттлинг Power saving, thermal throttling

Из-за работы ноутбука от батареи, режима энергосбережения на телефоне или нагрева устройства падает скорость CPU и GPU. Характерный признак перегрева: сначала всё нормально, а тормоза начинаются заметно позже.

Почему: Устройство работает от батареи или в режиме энергосбережения либо нагрелось → Следствие: Частоты CPU и GPU снижаются на 30–50% в зависимости от устройства → На экране: В режиме энергосбережения сразу, а при перегреве спустя от нескольких минут до примерно 20 минут игры FPS падает и появляются микрофризы

Симптомы: Микрофризы, Задержка ввода · Основной ответственный Внешние стороны · Внешние стороны · Совместно Команда разработки · Разработка клиента

Разрешение таймера Timer resolution (Windows 15.6ms)

Стандартный таймер Windows работает с шагом 15,6 ms, поэтому «подождать всего 1 ms» на деле растягивается до следующего тика таймера, то есть до 15,6 ms.

Почему: Ограничение FPS и отправка пакетов сделаны через Sleep (короткое ожидание) → Следствие: ОС будит поток только с шагом 15,6 ms → На экране: Интервалы между кадрами и между отправками ввода неравномерные

Симптомы: Микрофризы · Основной ответственный Команда разработки · Разработка клиента

Сворачивание мобильного приложения в фон App suspended in background

Если ненадолго свернуть игру, чтобы посмотреть уведомление, через несколько секунд ОС приостанавливает приложение (suspend), а сервер тем временем отключает игрока.

Почему: Игру свернули, чтобы прочитать сообщение или ответить на звонок → Следствие: Движок останавливает игровой цикл, а вскоре ОС приостанавливает и само приложение, и его сетевую активность → На экране: По возвращении уже дисконнект и переподключение

Симптомы: Дисконнект · Основной ответственный Команда разработки · Разработка клиента · Совместно Команда разработки · Разработка сервера

Переключение Wi-Fi ↔ LTE/5G Network switch changes IP

Когда игрок выходит из дома, Wi-Fi пропадает и устройство переключается на LTE или 5G. IP-адрес меняется, и старое соединение перестаёт работать.

Почему: Сигнал Wi-Fi слабеет, и устройство переключается на мобильную сеть → Следствие: IP-адрес меняется, и через соединение, открытое со старого адреса, обмениваться данными больше нельзя → На экране: Короткий фриз, затем дисконнект или переподключение

Симптомы: Фриз, Дисконнект · Основной ответственный Команда разработки · Разработка сервера · Совместно Команда разработки · Разработка клиента, Команда инфраструктуры · Сетевая инфраструктура

Проверка пакетов защитным ПО Antivirus / firewall inspection

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

Почему: Защитная программа проверяет каждый входящий и исходящий пакет → Следствие: К каждому пакету добавляется задержка, а если проверка не успевает, пакеты отбрасываются → На экране: Пинг беспорядочно скачет, или подключение блокируется

Симптомы: Микрофризы, Ошибка входа / бесконечная загрузка · Основной ответственный Внешние стороны · Внешние стороны · Совместно Команда разработки · Разработка клиента

Переполнение буфера приёма Socket receive buffer overflow

Если игра занята и поздно забирает пакеты из сокета (интерфейса ОС для приёма и отправки данных по сети), буфер ОС переполняется.

Почему: Кадры запаздывают, и игра поздно читает сокет → Следствие: Буфер приёма ОС заполняется: UDP-пакеты отбрасываются, а TCP уменьшает окно приёма и заставляет отправителя остановиться → На экране: Телепортация (UDP) или перемотка (TCP)

Симптомы: Телепортация, Перемотка · Основной ответственный Команда разработки · Разработка клиента

Нехватка памяти и своп на клиенте Paging / swap on client

Если вместе с игрой открыты десятки вкладок браузера, ОС выгружает часть памяти игры на диск.

Почему: Оперативной памяти в целом не хватает → Следствие: ОС переносит на диск память игры, которая сейчас не используется → На экране: Когда игра снова обращается к этой памяти, фриз на десятки или сотни ms в зависимости от накопителя

Симптомы: Фриз, Микрофризы · Основной ответственный Внешние стороны · Внешние стороны · Совместно Команда разработки · Разработка клиента

Нехватка видеопамяти (VRAM) VRAM over-commit

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

Почему: Высокое качество текстур, множество разного снаряжения и эффектов в людном месте забивают память видеокарты → Следствие: ОС переносит неиспользуемые сейчас текстуры в оперативную память ПК, а когда они нужны, возвращает их по медленной шине PCIe → На экране: Рывки при каждом появлении новой сцены или нового персонажа, текстуры какое-то время размытые

Симптомы: Микрофризы, Фриз · Основной ответственный Команда разработки · Разработка клиента · Совместно Внешние стороны · Внешние стороны

Фоновое сканирование Wi-Fi Periodic Wi-Fi background scan

ОС периодически перебирает радиоканалы в поисках соседних сетей Wi-Fi, и на это время связь ненадолго прерывается.

Почему: ОС или драйвер через равные промежутки ищут окружающие сети Wi-Fi → Следствие: На время поиска приём и передача ненадолго останавливаются → На экране: Пинг скачет строго через равные промежутки (например, каждые 60 секунд)

Симптомы: Микрофризы, Телепортация · Основной ответственный Внешние стороны · Внешние стороны · Совместно Команда разработки · Разработка клиента

Энергосбережение NIC и проблемы драйверов NIC power saving, driver bugs

Если сетевая карта или модуль Wi-Fi уходят в энергосбережение между пакетами, на пробуждение нужно время.

Почему: Включено энергосбережение сетевого адаптера, или драйвер устарел → Следствие: Задержка выхода из энергосбережения (wake-up), иногда перезапуск устройства → На экране: Нерегулярные задержки, изредка фриз на несколько секунд

Симптомы: Микрофризы, Фриз · Основной ответственный Внешние стороны · Внешние стороны · Совместно Команда разработки · Разработка клиента

Другие приложения на устройстве забирают пропускную способность Other apps saturating the link

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

Почему: Другие приложения загружают или отдают данные на максимальной скорости → Следствие: Игровые пакеты копятся в очередях ПК и роутера → На экране: Пинг взлетает, задержка ввода, перемотка

Симптомы: Задержка ввода, Перемотка · Основной ответственный Внешние стороны · Внешние стороны · Совместно Команда разработки · Разработка клиента

Ограничение обработки в свёрнутом или неактивном окне Minimized / unfocused window throttling

Когда игрок переключается на другое окно или сворачивает игру, и сама игра, и Windows ради экономии энергии замедляют её работу. По возвращении накопившиеся пакеты приходят разом, или соединение уже оборвано.

Почему: Переключение на другое окно через Alt+Tab или сворачивание игры → Следствие: Пока игру не видно, она сильно снижает FPS или останавливается, а Windows тоже понижает приоритет невидимых программ → На экране: В момент возвращения перемотка, а если игра была свёрнута долго, дисконнект

Симптомы: Перемотка, Микрофризы, Дисконнект · Основной ответственный Команда разработки · Разработка клиента

Вмешательство оверлеев Overlays and screen hooks

Мессенджеры, лаунчеры, программы записи и счётчики FPS встраиваются в рендеринг игры (хукинг), чтобы рисовать свой UI поверх игровой картинки. Работы в каждом кадре становится больше, а иногда оверлей конфликтует с игрой, и она дёргается или принудительно закрывается.

Почему: Включены оверлеи мессенджера, игрового лаунчера, утилиты видеокарты или программы записи → Следствие: При каждом выводе кадра на экран оверлей вклинивается и дорисовывает свой UI → На экране: Кадры немного запаздывают, в момент всплывающего уведомления бывают рывки, графические ошибки или принудительное закрытие игры (игроку это кажется дисконнектом)

Симптомы: Микрофризы, Фриз, Дисконнект · Основной ответственный Внешние стороны · Внешние стороны · Совместно Команда разработки · Разработка клиента

Задержка дисплея, устройств ввода и генерации кадров Display, input device and frame generation latency

Если пинг в норме, а управление ватное, задержку между вводом и экраном может добавлять обработка изображения в телевизоре, беспроводной контроллер или генерация кадров.

Почему: Игровой режим телевизора выключен, используется Bluetooth- или другой беспроводной контроллер, или включена генерация кадров (DLSS Frame Generation, FSR Frame Generation) → Следствие: Телевизор выводит кадр позже из-за обработки изображения, беспроводной ввод опаздывает на период опроса и из-за помех, а генерация кадров ждёт следующий кадр, чтобы построить промежуточный → На экране: Пинг и FPS хорошие, но нажатие доходит до экрана с опозданием: задержка ввода

Симптомы: Задержка ввода · Основной ответственный Внешние стороны · Внешние стороны · Совместно Команда разработки · Разработка клиента

Домашняя сеть: Wi-Fi, роутер, мобильная сеть

Последние несколько метров, прежде чем пакет покинет дом. Расстояние маленькое, но немалая часть жалоб на лаги рождается именно здесь. Wi-Fi делит один радиоканал между многими устройствами, а роутер выпускает трафик всей семьи через одну общую очередь.

Wi-Fi делит один радиоканал (частотный диапазон) с роутерами соседей, а диапазон 2,4 GHz к тому же пересекается с Bluetooth и микроволновками. При столкновении передач устройство ненадолго ждёт и отправляет снова, и когда таких повторов накапливается много, пакеты приходят неравномерно. Средний пинг может выглядеть нормально, а в отдельные моменты скакать: типичная картина для Wi-Fi.

Роутер стоит на пути каждого домашнего устройства в интернет. Если отправлять больше, чем способна принять линия связи, внутри роутера или модема образуется очередь, и устройства без управления очередями (SQM) дают ей вырасти до сотен ms. Дорогой роутер ведёт себя так же, если эта функция выключена. Стоит младшему брату или сестре начать выгружать видео, и игровые пакеты ждут в самом конце этой очереди. Это явление называют bufferbloat (раздувание очередей в оборудовании).

Ещё роутер записывает каждое соединение «устройство внутри ↔ сервер снаружи» в таблицу NAT и удаляет запись, если какое-то время по соединению не идут пакеты. Это частая причина дисконнекта после бездействия. В мобильной сети к этому добавляются переключение между базовыми станциями, режим энергосбережения радиомодуля и слабый сигнал.

Аналогия

Роутер похож на единственный въезд в жилой комплекс. Если в очереди стоят грузовики с переездом (выгрузка видео), даже срочному мотокурьеру (игровой пакет) приходится ждать за ними. Умный роутер (SQM) открывает для курьеров отдельную полосу.

Причины лагов на этом слое

Помехи и слабый сигнал Wi-Fi Wi-Fi interference, weak signal

При слабом сигнале или помехах пакеты на беспроводном участке приходится отправлять повторно по нескольку раз, и они приходят неравномерно.

Почему: Стены, расстояние, микроволновка, Bluetooth и соседские роутеры ухудшают качество радиосигнала → Следствие: Передача на беспроводном участке не удаётся → несколько повторных передач → На экране: Пакеты приходят неравномерно (джиттер), персонажи двигаются рывками, а в тяжёлых случаях из-за потерь телепортируются

Симптомы: Микрофризы, Телепортация, Откидывание назад · Основной ответственный Внешние стороны · Внешние стороны · Совместно Команда разработки · Разработка клиента

Перегруженный радиоканал Wi-Fi Crowded Wi-Fi channel

Там, где рядом десятки роутеров (например, в многоквартирном доме), они делят один радиоканал, и каждому приходится ждать своей очереди на передачу.

Почему: Десятки роутеров работают на одном радиоканале 2,4 GHz → Следствие: Перед передачей нужно ждать, пока другие устройства закончат и радиоканал освободится → На экране: Вечером, когда люди возвращаются домой, растёт джиттер (неравномерность интервалов между пакетами), появляются микрофризы

Симптомы: Микрофризы, Задержка ввода · Основной ответственный Внешние стороны · Внешние стороны · Совместно Команда разработки · Разработка клиента

Bufferbloat (очередь в роутере) Bufferbloat

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

Почему: Подключение забито: домашние выгружают видео или делают облачный бэкап, игрок сам ведёт стрим, идёт большая загрузка → Следствие: Роутер или модем складывает лишние пакеты в длинную очередь → На экране: Игровые пакеты тоже ждут в конце очереди, и пинг взлетает до сотен ms

Симптомы: Задержка ввода, Перемотка, Телепортация · Основной ответственный Внешние стороны · Внешние стороны · Совместно Команда разработки · Разработка клиента

Истечение записи в таблице NAT NAT mapping timeout

Роутер удаляет из таблицы NAT неактивные соединения, по которым какое-то время не было пакетов. Это частая причина дисконнекта в тот момент, когда игрок после простоя снова начинает двигаться.

Почему: Роутер записывает соединение «домашнее устройство ↔ внешний сервер» в таблицу NAT (таблицу трансляции адресов) → Следствие: Если пакетов какое-то время нет, запись удаляется (для UDP обычно через 30–120 секунд) → На экране: Пакеты сервера больше не попадают в домашнюю сеть, дисконнект

Симптомы: Дисконнект · Основной ответственный Команда разработки · Разработка клиента · Совместно Команда разработки · Разработка сервера

Слабый или перегретый роутер Router CPU / session table exhaustion

Когда на дешёвый роутер приходятся десятки устройств и тысячи соединений, он сам перестаёт справляться.

Почему: Десятки устройств, P2P-программы и торренты открывают тысячи соединений → Следствие: CPU и таблица сессий роутера забиты → На экране: Задержки и потери при обработке пакетов, новые соединения не устанавливаются

Симптомы: Микрофризы, Ошибка входа / бесконечная загрузка, Дисконнект · Основной ответственный Внешние стороны · Внешние стороны

Хендовер между базовыми станциями (в движении) Cellular handover

В автобусе или метро связь прерывается на время смены базовой станции.

Почему: При перемещении меняется базовая станция, к которой подключён телефон → Следствие: Обычно перерыв длится десятки ms, но если из-за плохого сигнала переключение не удалось, связь может пропасть на время от сотен ms до нескольких секунд → На экране: Фриз, затем телепортация, а при долгом перерыве дисконнект

Симптомы: Фриз, Телепортация, Дисконнект · Основной ответственный Внешние стороны · Внешние стороны · Совместно Команда разработки · Разработка клиента, Команда разработки · Разработка сервера

Задержка перехода состояний RRC (энергосбережение радиомодуля) Radio state promotion (RRC)

Если связи какое-то время нет, телефон переводит радиосоединение в экономичное состояние, а при следующем пакете поднимает его снова, и пакет опаздывает.

Почему: После короткой паузы в обмене данными телефон переводит радиосоединение в режим энергосбережения → Следствие: Чтобы отправить следующий пакет, соединение нужно снова поднять → На экране: Заметно запаздывает только первое действие после простоя

Симптомы: Задержка ввода · Основной ответственный Команда разработки · Разработка клиента

Слабый сигнал мобильной сети и мёртвые зоны Weak cellular signal

В лифте, под землёй или в глубине здания растёт число повторных передач, падает скорость, и в итоге дело доходит до дисконнекта.

Почему: Игрок переходит туда, где сигнал слабый → Следствие: Больше повторных передач по радио, скорость падает, связь на мгновения пропадает → На экране: Из-за джиттера и потерь микрофризы и телепортация, в итоге дисконнект

Симптомы: Микрофризы, Телепортация, Дисконнект · Основной ответственный Внешние стороны · Внешние стороны · Совместно Команда разработки · Разработка клиента

Частые переключения 5G ↔ LTE (на границе покрытия 5G) 5G NSA / LTE switching

Внутри зданий со слабым сигналом 5G или на границе покрытия 5G телефон часто переключается между 5G и LTE, и при каждом переключении пинг скачет или связь ненадолго прерывается.

Почему: Игрок там, где сигнал 5G то есть, то нет (внутри здания, на границе покрытия 5G) → Следствие: Телефон постоянно переключается между 5G и LTE, и каждый раз возникает короткий перерыв → На экране: Даже на месте пинг беспорядочно скачет, иногда бывают фризы и телепортация

Симптомы: Микрофризы, Телепортация, Фриз · Основной ответственный Внешние стороны · Внешние стороны · Совместно Команда разработки · Разработка клиента

Ограничения публичного Wi-Fi и корпоративной сети Captive portal, restrictive network

Страница входа в Wi-Fi кафе или корпоративный файрвол блокируют подключение к игре.

Почему: Авторизация на странице входа ещё не пройдена, или файрвол блокирует игровые порты и UDP → Следствие: Попытки подключения блокируются полностью или проходят только частично → На экране: Ошибка входа, или авторизация проходит, но в игру не пускает

Симптомы: Ошибка входа / бесконечная загрузка · Основной ответственный Внешние стороны · Внешние стороны · Совместно Команда разработки · Разработка клиента, Команда разработки · Разработка сервера

Интернет-маршрут: сети провайдеров и дальние участки

Покинув дом, пакет проходит через сеть провайдера, стыки между провайдерами, а иногда и подводные кабели, и попадает в ЦОД, где стоит сервер. Задержка на этом участке в основном определяется расстоянием и выбором маршрута (маршрутизацией), и игровая компания часто не может исправить её напрямую.

Свет в оптоволокне проходит около 200 000 km в секунду. До сервера в 1 000 km путь туда и обратно занимает минимум 10 ms, и, пока сигнал идёт по оптоволокну, никакой апгрейд серверов или оборудования эту цифру не уменьшит. Реальные пакеты идут в обход, через точки, где соединяются провайдеры (пиринг), поэтому обычно путь занимает в 1,5–2 раза больше теоретического значения. На направлениях, где вдоль прямой почти нет крупных кабелей, например Корея–Европа, трафик идёт в обход через Юго-Восточную Азию и Суэц или через США, и путь занимает в 2,5–3 раза больше (около 230–270 ms туда и обратно).

Проблема в том, что этот маршрут меняется в зависимости от времени и обстоятельств. Примерно с 21:00 до 23:00 все смотрят видео, и стыки между провайдерами легко перегружаются. Когда меняется маршрутная информация (BGP), пакеты от нескольких секунд до нескольких десятков секунд (изредка несколько минут) не доходят до адресата, а при обрыве подводного кабеля трафик неделями идёт в обход по дальнему маршруту. Если лаги «только у абонентов определённого провайдера», «только по вечерам» или «только за рубежом», в первую очередь подозревают этот слой.

Аналогия

Сеть провайдеров похожа на сеть автомагистралей. Даже если дорога из Сеула в Пусан свободна, на расстояние всё равно уходит время; в час пик пункты оплаты (пиринговые стыки) стоят в пробках, а после аварии навигатор ведёт в дальний объезд.

Причины лагов на этом слое

Задержка распространения (физическое расстояние) Propagation delay

Даже свет в оптоволокне проходит всего около 200 000 km в секунду. Если сервер далеко, задержка будет большой, каким бы хорошим он ни был.

Почему: Сервер далеко (зарубежный сервер, другой континент) → Следствие: Время пути туда и обратно растёт с расстоянием (не меньше 10 ms на каждые 1 000 km) → На экране: Постоянная задержка ввода на каждое действие, невыгодное положение при проверке попаданий

Симптомы: Задержка ввода · Основной ответственный Команда инфраструктуры · Серверная инфраструктура · Совместно Команда инфраструктуры · Сетевая инфраструктура, Команда разработки · Разработка сервера

Спутниковый интернет (низкоорбитальный и геостационарный) Satellite internet (LEO, GEO)

В спутниковом интернете радиосигнал летит в космос и обратно. Через геостационарный спутник один только путь туда и обратно занимает больше 0,5 с. Низкоорбитальные спутники вроде Starlink обычно быстрые, но в моменты перераспределения маршрута задержка скачет, а связь может ненадолго прерываться.

Почему: Подключение дома, на судне или в самолёте через геостационарный или низкоорбитальный спутниковый интернет либо через бортовой Wi-Fi, работающий через спутник → Следствие: Геостационарная орбита находится на высоте около 36 000 km, поэтому сам путь сигнала длинный. На низкой орбите маршрут терминал–спутник–наземная станция часто перераспределяется, и в эти моменты ненадолго появляются задержка и потери → На экране: Через геостационарный спутник большая задержка ввода на любое действие, через низкоорбитальный обычно всё нормально, но через равные промежутки времени микрофризы и телепортация

Симптомы: Задержка ввода, Микрофризы, Телепортация · Основной ответственный Внешние стороны · Внешние стороны · Совместно Команда разработки · Разработка клиента, Команда разработки · Разработка сервера

Неоптимальная маршрутизация Suboptimal routing

Из-за договоров о соединении между провайдерами трафик даже до близкого сервера идёт в обход через далёкие точки.

Почему: Провайдер игрока и провайдер сервера не соединены напрямую → Следствие: Трафик идёт через другую страну или другой город, растут расстояние и число устройств на пути → На экране: Пинг заметно выше только у абонентов определённого провайдера

Симптомы: Задержка ввода · Основной ответственный Команда инфраструктуры · Сетевая инфраструктура · Совместно Внешние стороны · Внешние стороны

Перегрузка пиринга в часы пик Peak-hour congestion at peering

Примерно с 21:00 до 23:00 резко растёт видеотрафик, и стыки между провайдерами (пиринг) легко перегружаются.

Почему: По вечерам массово смотрят стримы и скачивают файлы → Следствие: На пиринговых стыках появляются очереди и потери → На экране: Только по вечерам у абонентов определённого провайдера микрофризы и телепортация

Симптомы: Микрофризы, Телепортация, Откидывание назад · Основной ответственный Команда инфраструктуры · Сетевая инфраструктура · Совместно Внешние стороны · Внешние стороны

Аварии на подводных кабелях и международных линиях Submarine cable fault

После обрыва подводного кабеля трафик несколько недель (иногда месяцев), пока идёт ремонт, ходит дальними обходными маршрутами, а оставшиеся линии перегружены.

Почему: Обрыв кабеля или отказ оборудования → Следствие: Трафик уходит на дальние обходные маршруты и оставшиеся линии → На экране: У зарубежных игроков резко растёт пинг и появляются потери, это длится от нескольких дней до нескольких недель

Симптомы: Задержка ввода, Телепортация · Основной ответственный Внешние стороны · Внешние стороны · Совместно Команда инфраструктуры · Сетевая инфраструктура

Смена маршрута BGP и сходимость Route change / BGP convergence

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

Почему: Меняется маршрутная информация на участке какого-то провайдера → Следствие: От нескольких секунд до нескольких десятков секунд пакеты пропадают или переходят на новый маршрут → На экране: Внезапный фриз на несколько секунд, после которого меняется пинг (например, 40 → 70 ms)

Симптомы: Фриз, Телепортация · Основной ответственный Команда инфраструктуры · Сетевая инфраструктура · Совместно Команда разработки · Разработка сервера, Внешние стороны · Внешние стороны

Неисправность одного из путей ECMP ECMP / link bundle member fault

Провайдеры и ЦОД держат несколько путей к одной цели и для каждого соединения выбирают один из них. Если неисправен только один путь, лаги постоянно бывают только у тех, кому достался этот путь.

Почему: На участке из нескольких объединённых линий одна линия или одно устройство неисправно или перегружено → Следствие: Путь выбирается по сочетанию адресов и портов (хешу), поэтому потери и задержка только у соединений, попавших на этот путь → На экране: В одном регионе и у одного провайдера телепортация постоянно бывает только у части игроков. После переподключения иногда всё проходит

Симптомы: Телепортация, Откидывание назад, Микрофризы · Основной ответственный Команда инфраструктуры · Сетевая инфраструктура · Совместно Команда разработки · Разработка сервера, Внешние стороны · Внешние стороны

Ограничение скорости и управление трафиком у провайдера Traffic shaping, data caps

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

Почему: После исчерпания пакета трафика по тарифу скорость ограничена, либо ограничен определённый трафик → Следствие: Пакеты ждут в очереди или отбрасываются → На экране: Лаги после определённого объёма трафика, особенно в мобильной сети

Симптомы: Задержка ввода, Телепортация · Основной ответственный Внешние стороны · Внешние стороны · Совместно Команда разработки · Разработка сервера, Команда инфраструктуры · Сетевая инфраструктура

Ограничение UDP и DPI на уровне страны или провайдера UDP blocking, throttling and inspection by networks

Некоторые сети блокируют отдельные UDP-адреса и порты или ограничивают скорость UDP, а оборудование инспекции пакетов (DPI) отсеивает протоколы, которые не может распознать. Игры, работающие по UDP, в таких сетях не подключаются или часто теряют соединение.

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

Симптомы: Ошибка входа / бесконечная загрузка, Дисконнект, Телепортация · Основной ответственный Внешние стороны · Внешние стороны · Совместно Команда разработки · Разработка клиента, Команда разработки · Разработка сервера, Команда инфраструктуры · Сетевая инфраструктура

Плохое качество линии связи Faulty last-mile line / modem

Плохой контакт в разъёмах, старый кабель или неисправный модем дают постоянные потери и периодические обрывы связи.

Почему: Повреждённый кабель, плохой контакт, неисправность модема или оптического терминала → Следствие: Пакеты отбрасываются из-за битовых ошибок, иногда связь пропадает на время от нескольких секунд до минуты, пока линия переподключается → На экране: Постоянные небольшие потери, иногда фриз на несколько секунд или дисконнект

Симптомы: Телепортация, Фриз, Дисконнект · Основной ответственный Внешние стороны · Внешние стороны

Сбои и задержки DNS DNS failure / slowness

DNS превращает имя сервера в адрес. Если DNS отвечает медленно или с ошибкой, клиент не может найти сервер авторизации и сервер патчей.

Почему: Сбой DNS провайдера или ошибка настройки → Следствие: Не находятся адреса сервера авторизации и сервера патчей → На экране: После нажатия кнопки входа долгое ожидание или ошибка входа. У тех, кто уже в игре, всё нормально

Симптомы: Ошибка входа / бесконечная загрузка · Основной ответственный Внешние стороны · Внешние стороны · Совместно Команда разработки · Разработка клиента

Перегрузка общих линий из-за DDoS DDoS saturating shared links

Массированная атака на игровую компанию или на другого клиента в той же сети забивает общие линии связи.

Почему: Появляется огромный объём атакующего трафика → Следствие: Задерживается и отбрасывается даже нормальный трафик на тех же линиях → На экране: У многих игроков одновременно телепортация, дисконнекты, ошибки входа

Симптомы: Телепортация, Дисконнект, Ошибка входа / бесконечная загрузка · Основной ответственный Команда инфраструктуры · Сетевая инфраструктура · Совместно Внешние стороны · Внешние стороны

Общий IP провайдера (CGNAT) Carrier-grade NAT

В мобильных сетях и у некоторых провайдеров один IP делят много абонентов, а записи NAT для неактивных соединений быстро удаляются.

Почему: Оборудование провайдера ведёт таблицу сессий для огромного числа абонентов → Следствие: Лимит таблицы сессий, короткий таймаут простоя → На экране: Дисконнект после бездействия, ложные срабатывания, при которых блокируются сразу все игроки с одним IP

Симптомы: Дисконнект, Ошибка входа / бесконечная загрузка · Основной ответственный Команда разработки · Разработка клиента · Совместно Команда разработки · Разработка сервера, Команда инфраструктуры · Сетевая инфраструктура

Трафик через VPN или игровой ускоритель VPN / game accelerator detour

С включённым VPN или игровым ускорителем пакеты идут через промежуточные серверы этого сервиса. Если такой сервер далеко или перегружен, соединение становится даже медленнее, чем без него.

Почему: VPN или ускоритель направляет все игровые пакеты через промежуточный сервер → Следствие: Добавляются расстояние до промежуточного сервера и его перегрузка, а из-за заголовков туннеля уменьшается MTU (максимальный размер пакета за одну передачу) → На экране: Рост пинга и потери, ошибка входа из-за блокировки вместе с другими пользователями того же промежуточного адреса

Симптомы: Задержка ввода, Телепортация, Ошибка входа / бесконечная загрузка · Основной ответственный Внешние стороны · Внешние стороны · Совместно Команда инфраструктуры · Сетевая инфраструктура, Команда разработки · Разработка сервера

Сетевое оборудование ЦОД

Прямо перед сервером пакет по очереди проходит маршрутизатор, оборудование защиты от DDoS, файрвол, балансировщик нагрузки и коммутатор. Обычно этот участок занимает меньше 1 ms, но если у одного устройства кончается ёмкость или оно отказывает, это одновременно задевает тысячи игроков всего сервера.

У каждого устройства своя роль. Маршрутизатор выбирает маршрут, оборудование защиты от DDoS отсеивает атакующий трафик, файрвол пропускает только разрешённые соединения и отслеживает каждое из них в таблице сессий. Балансировщик нагрузки распределяет входящие соединения по нескольким серверам, а коммутатор соединяет серверы между собой.

Общие слабые места этих устройств: размер таблиц и размер буферов. Когда таблица сессий файрвола заполнена, новые соединения не принимаются; балансировщик нагрузки удаляет неактивные соединения через заданное время; а маленький буфер коммутатора переполняется меньше чем за 1 ms, когда несколько серверов в один момент разом отправляют пакеты тысячам игроков (появление мирового босса). А пока отказавшее устройство переключается на резервное (failover), несколько секунд стоят все.

Аналогия

Вход в ЦОД похож на досмотр и выход на посадку в аэропорту. Пункт досмотра (файрвол) пропускает только тех, кто есть в списке, а когда строки в списке кончаются, больше никого не принимает. Сотрудник у выхода (балансировщик нагрузки) считает пассажира, который долго сидит тихо, «ушедшим» и вычёркивает его из списка.

Причины лагов на этом слое

Переполнение таблицы сессий файрвола Firewall session table exhaustion

Файрвол записывает каждое пропущенное соединение в таблицу сессий и отслеживает его. Когда таблица заполнена, новые соединения принять нельзя.

Почему: Из-за наплыва подключений или атаки число сессий достигает лимита → Следствие: Для нового соединения нет свободной записи, и оно отклоняется → На экране: У тех, кто пытается войти, ошибка входа или бесконечная загрузка, у части уже установленных соединений тоже дисконнект

Симптомы: Ошибка входа / бесконечная загрузка, Дисконнект · Основной ответственный Команда инфраструктуры · Сетевая инфраструктура · Совместно Команда разработки · Разработка сервера, Команда разработки · Разработка клиента

Задержка и ложные срабатывания защиты от DDoS DDoS scrubbing latency, false positives

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

Почему: После обнаружения атаки (или постоянно) входящий трафик идёт в обход через центр очистки → Следствие: Маршрут удлиняется, часть нормальных пакетов признаётся атакой → На экране: Пинг растёт у всех, ошибка входа только в отдельных регионах или у отдельных провайдеров

Симптомы: Задержка ввода, Ошибка входа / бесконечная загрузка, Телепортация · Основной ответственный Команда инфраструктуры · Сетевая инфраструктура · Совместно Команда разработки · Разработка сервера

Таймаут простоя балансировщика Load balancer idle timeout

Балансировщик нагрузки удаляет неактивное соединение через определённое время. Игра считает, что соединение живо, и в итоге получает дисконнект.

Почему: Игрок какое-то время не отправляет ни одного пакета (окно чата, отошёл от компьютера) → Следствие: Балансировщик удаляет неактивное соединение (типичные значения по умолчанию 60–350 с) → На экране: Дисконнект в момент, когда игрок снова начинает двигаться

Симптомы: Дисконнект · Основной ответственный Команда инфраструктуры · Сетевая инфраструктура · Совместно Команда разработки · Разработка клиента, Команда разработки · Разработка сервера

Истечение отслеживания соединений в облачной группе безопасности Cloud security group connection tracking timeout

Файрвол облачного сервера (группа безопасности) тоже отслеживает соединения, и запись о неактивном соединении истекает через заданное время. Поэтому даже на сервере, к которому подключаются напрямую без балансировщика, игрок после бездействия может получить дисконнект.

Почему: Группа безопасности настроена так, что отслеживает игровые соединения (разрешены только определённые адреса, ограничены исходящие правила, трафик идёт через NLB и т. п.) → Следствие: Запись о соединении, которое какое-то время неактивно, истекает, и последующие пакеты группа безопасности молча отбрасывает → На экране: После отлучки игрок двигается, но ответа нет, затем дисконнект. Серверная программа долго ничего не замечает

Симптомы: Дисконнект · Основной ответственный Команда инфраструктуры · Серверная инфраструктура · Совместно Команда разработки · Разработка клиента, Команда разработки · Разработка сервера

Лимиты соединений и портов облачного NAT-шлюза Cloud NAT gateway connection / port limits

Исходящие соединения серверов из частной подсети во внешний мир (авторизация на платформе, платежи, внешние API) проходят через NAT-шлюз, который подменяет адрес и порт. Если одновременных соединений к одной цели больше, чем позволяет лимит портов шлюза, новые соединения не устанавливаются.

Почему: Серверы открывают много коротких соединений к одному внешнему адресу, например к авторизации на платформе или платёжному сервису, или долго держат соединения открытыми → Следствие: NAT-шлюз не может выделить для этой цели ещё один исходный порт, и новое соединение не устанавливается → На экране: В самой игре всё нормально, но функции, которые обращаются наружу (вход, платежи, выдача наград), не работают или тормозят (ошибка входа / бесконечная загрузка, съеденные действия / роллбэк)

Симптомы: Ошибка входа / бесконечная загрузка, Съеденные действия / роллбэк · Основной ответственный Команда инфраструктуры · Сетевая инфраструктура · Совместно Команда разработки · Разработка сервера

Перекос балансировки и ошибки health check LB imbalance, bad health checks

Соединения скапливаются на одном сервере, или балансировщик продолжает отправлять игроков на уже упавший сервер.

Почему: Правило распределения не подходит, или health check (проверка работоспособности) не видит реального состояния → Следствие: Перегружен только один сервер, или подключения идут на упавший сервер → На экране: Только в части каналов или у части игроков слоумо, ошибка входа или бесконечная загрузка

Симптомы: Слоумо, Ошибка входа / бесконечная загрузка · Основной ответственный Команда инфраструктуры · Сетевая инфраструктура · Совместно Команда разработки · Разработка сервера

Микробёрсты на коммутаторе Switch microburst drops

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

Почему: Появление мирового босса, массовое умение или совпавшие во времени тики нескольких серверов, и всё отправляется разом → Следствие: Буфер (от сотен KB до нескольких MB на порт) там, где несколько портов сходятся в один или быстрый порт переходит в медленный, мгновенно заполняется → На экране: Часть пакетов отбрасывается, у многих игроков одновременно телепортация и съеденные умения

Симптомы: Телепортация, Съеденные действия / роллбэк · Основной ответственный Команда разработки · Разработка сервера · Совместно Команда инфраструктуры · Сетевая инфраструктура, Команда инфраструктуры · Серверная инфраструктура

Перегрузка линии связи ЦОД Uplink saturation

Если раздача патчей, отправка логов и бэкапы идут по той же линии, что и игра, линия забивается.

Почему: Крупные передачи данных занимают ту же линию → Следствие: Растут очередь на линии и потери → На экране: Рост пинга и телепортация на всём сервере

Симптомы: Задержка ввода, Телепортация · Основной ответственный Команда инфраструктуры · Сетевая инфраструктура · Совместно Команда инфраструктуры · Серверная инфраструктура

Переключение сетевого оборудования на резерв (failover) Network device failover

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

Почему: Из-за отказа или обслуживания трафик переключается на резервное устройство → Следствие: Переключение занимает несколько секунд, а если состояние сессий не синхронизировано, соединения сбрасываются → На экране: Одновременный фриз у всех игроков сервера, массовые дисконнекты

Симптомы: Фриз, Дисконнект · Основной ответственный Команда инфраструктуры · Сетевая инфраструктура · Совместно Команда разработки · Разработка сервера, Команда разработки · Разработка клиента

Неисправный кабель и ошибки порта Bad cable / optics (CRC errors)

Если оптический модуль или кабель неисправен, определённая доля пакетов на этом пути повреждается.

Почему: Битовые ошибки из-за неисправного оптического модуля или кабеля → Следствие: Повреждённые пакеты устройство молча отбрасывает → На экране: Только у части серверов и игроков на этом пути постоянные потери, телепортация и откидывание назад

Симптомы: Телепортация, Откидывание назад · Основной ответственный Команда инфраструктуры · Сетевая инфраструктура

Несовпадение MTU (пропадают только большие пакеты) MTU black hole

Если на промежуточном участке MTU (максимальный размер пакета за одну передачу) меньше, а уведомления о превышении размера блокируются, постоянно пропадают только большие пакеты.

Почему: На участке туннеля или VPN MTU уменьшается → Следствие: Уведомление о превышении размера (ICMP) блокирует файрвол, и отправитель о нём не знает → На экране: Фриз и затем дисконнект только при открытии больших экранов вроде инвентаря или списка персонажей

Симптомы: Фриз, Дисконнект, Ошибка входа / бесконечная загрузка · Основной ответственный Команда инфраструктуры · Сетевая инфраструктура · Совместно Команда инфраструктуры · Серверная инфраструктура, Команда разработки · Разработка сервера

Сетевая карта сервера (NIC)

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

NIC складывает пришедшие пакеты по очереди в кольцевой буфер (буфер приёма из фиксированного числа слотов, которые используются по кругу) и сообщает CPU: «пришёл пакет» (прерывание). CPU забирает пакеты из кольцевого буфера и передаёт ОС. Если пакеты приходят быстрее, чем CPU их забирает, слоты заканчиваются, и все следующие пакеты отбрасываются. Такой лаг трудно найти: тихо растут только числа в статистике сетевой карты (ethtool -S), а в логах игрового сервера никаких ошибок нет.

Современные NIC умеют держать несколько очередей приёма (кольцевых буферов) и распределять уведомления по нескольким ядрам CPU (RSS), но если это не настроено или трафик сваливается в одну очередь, на 100% загружается одно ядро, и оно становится узким местом. У облачного сервера перед NIC есть ещё отдельные лимиты пакетов в секунду, пропускной способности и числа соединений, и всё, что сверх них, отбрасывается, не доходя до сервера. В обычных метриках вроде CPU или кольцевого буфера это не видно; в AWS следы остаются только в статистике драйвера ENA (pps_allowance_exceeded и др. в ethtool -S).

Аналогия

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

Причины лагов на этом слое

Все прерывания NIC на одном ядре Single-queue NIC / no RSS

Если NIC отправляет прерывания о приходе пакетов только на одно ядро CPU, это ядро становится узким местом.

Почему: Одна очередь приёма, или выключен RSS, который распределяет пакеты по нескольким ядрам → Следствие: Одно ядро загружено на 100% и не успевает забирать пакеты → На экране: При наплыве игроков потери и задержка на всём сервере (телепортация, задержка ввода)

Симптомы: Телепортация, Откидывание назад, Задержка ввода · Основной ответственный Команда инфраструктуры · Серверная инфраструктура

Слишком маленький кольцевой буфер RX ring buffer overflow

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

Почему: Кольцевой буфер оставлен маленьким, со значением по умолчанию (256–2 048 слотов в зависимости от драйвера) → Следствие: Во время всплеска трафика буфер переполняется раньше, чем CPU успевает забрать пакеты → На экране: Потери только в моменты всплесков (телепортация, съеденные умения). В логах игрового сервера следов нет

Симптомы: Телепортация, Съеденные действия / роллбэк · Основной ответственный Команда инфраструктуры · Серверная инфраструктура

Избыточное объединение прерываний Interrupt coalescing

Если ради разгрузки CPU NIC копит пакеты и сообщает о них разом, пакеты задерживаются на время накопления.

Почему: NIC копит пакеты определённое время или до определённого числа и только потом сообщает о них → Следствие: Пока идёт накопление, пакеты ждут → На экране: Небольшой рост задержки. Обычно он мал, но при чрезмерных настройках доходит до миллисекунд

Симптомы: Задержка ввода · Основной ответственный Команда инфраструктуры · Серверная инфраструктура

Превышен лимит PPS в облаке Cloud PPS / bandwidth allowance

У каждого типа облачного сервера есть лимиты пакетов в секунду и пропускной способности, и всё сверх лимита молча отбрасывается.

Почему: Онлайн растёт, и число пакетов в секунду превышает лимит инстанса → Следствие: Облачная сеть отбрасывает превышение → На экране: Потери непонятного происхождения, телепортация, съеденные умения. При этом у CPU сервера есть запас

Симптомы: Телепортация, Съеденные действия / роллбэк · Основной ответственный Команда инфраструктуры · Серверная инфраструктура · Совместно Команда разработки · Разработка сервера, Внешние стороны · Внешние стороны

Исчерпание пропускной способности NIC NIC bandwidth saturation

Если карта на 1 Gbps или 10 Gbps загружена до предела, очередь отправки растёт, и в итоге пакеты отбрасываются.

Почему: Из-за роста рассылки объём отправки доходит до предела карты → Следствие: Очередь отправки растёт, а при переполнении пакеты отбрасываются → На экране: Задержка и потери на всём сервере (задержка ввода, телепортация)

Симптомы: Задержка ввода, Телепортация · Основной ответственный Команда разработки · Разработка сервера · Совместно Команда инфраструктуры · Серверная инфраструктура

Накладные расходы виртуализации и шумные соседи Noisy neighbors in virtualization

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

Почему: Другие виртуальные машины на том же физическом сервере потребляют много ресурсов → Следствие: Обработка пакетов на нашей виртуальной машине нерегулярно запаздывает → На экране: Без явной причины время от времени появляется джиттер (неравномерность интервалов между пакетами) и микрофризы

Симптомы: Микрофризы · Основной ответственный Команда инфраструктуры · Серверная инфраструктура · Совместно Внешние стороны · Внешние стороны

Обслуживание облачного хоста и живая миграция Cloud host maintenance / live migration

Во время обслуживания физического сервера (хоста) облачный провайдер переносит виртуальную машину на другой хост (живая миграция) или ненадолго её приостанавливает. На это время замирает весь сервер, а если пауза долгая, соединения рвутся.

Почему: Из-за обслуживания хоста или прогноза отказа провайдер переносит виртуальную машину на другой хост или ненадолго приостанавливает её → Следствие: Во время переноса CPU, память и сеть работают медленнее, а в конце виртуальная машина ненадолго полностью останавливается (в зависимости от провайдера и способа от меньше 1 с до примерно 30 с) → На экране: Фриз у всех на сервере одновременно, затем перемотка и телепортация, а если остановка дольше таймаута, массовые дисконнекты

Симптомы: Фриз, Перемотка, Телепортация, Дисконнект · Основной ответственный Команда инфраструктуры · Серверная инфраструктура · Совместно Команда разработки · Разработка сервера, Внешние стороны · Внешние стороны

Проблемы драйвера и прошивки NIC NIC hang / reset

Из-за ошибки драйвера или сбоя какой-то функции карта зависает и перезапускается, и на это время весь приём и отправка прекращаются.

Почему: Ошибка драйвера, сбой функций offload → Следствие: NIC зависает и перезапускается (несколько секунд) → На экране: У всех на этом сервере одновременно фриз, затем телепортация или дисконнект

Симптомы: Фриз, Дисконнект · Основной ответственный Команда инфраструктуры · Серверная инфраструктура

Ожидание объединения пакетов в GRO/LRO GRO/LRO batching

GRO и LRO объединяют несколько пакетов в один, чтобы снизить нагрузку на CPU. При некоторых настройках маленький игровой пакет ненадолго ждёт следующий, чтобы объединиться с ним.

Почему: NIC или ядро ОС объединяет пришедшие пакеты и обрабатывает их вместе → Следствие: Если включено аппаратное объединение (LRO) или задано время ожидания объединения, пакет ненадолго ждёт следующий → На экране: Небольшой рост задержки (обычно не больше нескольких десятков µs)

Симптомы: Задержка ввода · Основной ответственный Команда инфраструктуры · Серверная инфраструктура

ОС сервера (ядро)

Ядро Linux или Windows на сервере принимает соединения, управляет буферами сокетов и распределяет CPU и память для игрового сервера. Большинство значений по умолчанию консервативны и рассчитаны на самые разные задачи, поэтому игровому серверу, к которому десятки тысяч игроков подключены подолгу, они часто не подходят как есть.

Когда приходит новое подключение, ядро кладёт запрос в очередь подключений (backlog), а игровой сервер забирает запросы по одному. Когда очередь заполнена, Linux молча отбрасывает новые запросы, а Windows возвращает отказ. В Linux каждому соединению нужен файловый дескриптор (fd), то есть номер, который присваивается открытому файлу или соединению, и у числа fd на один процесс тоже есть предел. Когда сразу после техработ десятки тысяч игроков одновременно жмут кнопку входа, первыми заканчиваются очередь подключений и fd.

Кроме того, при нехватке памяти ядро, если включена подкачка, выгружает часть памяти на диск (своп), а Linux, когда память совсем кончается, выбирает процесс, который занимает больше всего памяти, и принудительно его убивает (OOM killer). Игровой сервер обычно и есть самый прожорливый процесс на машине, поэтому его завершают первым. Если для контейнера задан лимит памяти, то же самое происходит в момент достижения лимита, даже когда на сервере в целом память есть. Вещи, которые на вид не связаны с игрой, тоже ненадолго останавливают сервер или сбивают таймеры: синхронизация времени (NTP), плановые задания, лимит CPU контейнера, CPU steal на виртуальной машине (время ожидания, пока физический CPU занят другими виртуальными машинами).

Аналогия

Серверная ОС похожа на входные ворота и администрацию парка развлечений. Если к открытию (окончанию техработ) приходят все сразу, очередь у ворот (backlog) переполняется, а когда заканчиваются браслеты (файловые дескрипторы), больше никого не пускают.

Причины лагов на этом слое

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

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

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

Симптомы: Ошибка входа / бесконечная загрузка · Основной ответственный Команда разработки · Разработка сервера · Совместно Команда инфраструктуры · Серверная инфраструктура, Команда разработки · Разработка клиента

Лимит файловых дескрипторов File descriptor limit (ulimit)

Каждому соединению нужен файловый дескриптор (fd, номер, который ОС присваивает открытому файлу или сокету), а число fd, которые может открыть один процесс, ограничено.

Почему: Онлайн достигает лимита файловых дескрипторов процесса → Следствие: Сервер не может принять новые соединения (Too many open files). Заодно не открываются файлы логов и соединения с БД → На экране: Начиная с определённого числа игроков больше никто не может войти: ошибка входа / бесконечная загрузка

Симптомы: Ошибка входа / бесконечная загрузка · Основной ответственный Команда инфраструктуры · Серверная инфраструктура · Совместно Команда разработки · Разработка сервера

Нехватка буферов сокетов в ядре Small socket buffers

Если буферы приёма и отправки маленькие, то при всплеске трафика принятые по UDP пакеты отбрасываются, а отправка по TCP встаёт, потому что в буфере нет места.

Почему: SO_SNDBUF и SO_RCVBUF оставлены по умолчанию или слишком малы → Следствие: При всплеске трафика или короткой остановке принимающего потока буфер приёма UDP переполняется и пакеты выбрасываются, а TCP ждёт, пока в буфере отправки освободится место → На экране: Телепортация (потери UDP) или перемотка (ожидание TCP)

Симптомы: Телепортация, Перемотка · Основной ответственный Команда инфраструктуры · Серверная инфраструктура · Совместно Команда разработки · Разработка сервера

Избыток потоков и переключение контекста Thread oversubscription, context switching

Если потоков намного больше, чем ядер, заметная часть CPU уходит только на то, чтобы ОС запускала их по очереди.

Почему: Потоков сотни или тысячи (например, свой поток на каждое соединение) → Следствие: Растут затраты на переключение контекста (смену выполняемого потока) и число промахов кэша → На экране: CPU занят, но производительность низкая, тики неравномерные: микрофризы, слоумо

Симптомы: Микрофризы, Слоумо · Основной ответственный Команда разработки · Разработка сервера · Совместно Команда инфраструктуры · Серверная инфраструктура

CPU steal (виртуальная машина) CPU steal time

Пока физический сервер (гипервизор) временно отдаёт процессорное время виртуальной машины другим виртуальным машинам (CPU steal), игровой сервер стоит.

Почему: Другие виртуальные машины на том же хосте активно используют CPU → Следствие: Виртуальная машина игрового сервера то и дело не получает CPU на время от единиц до десятков ms → На экране: Необъяснимые всплески времени тика: микрофризы, фризы

Симптомы: Микрофризы, Фриз · Основной ответственный Команда инфраструктуры · Серверная инфраструктура · Совместно Внешние стороны · Внешние стороны

Троттлинг CPU в контейнере (квота CFS) Container CPU throttling (CFS quota)

Если у контейнера задан лимит CPU, то, израсходовав квоту в пределах периода (обычно 100 ms), он принудительно останавливается до конца периода (троттлинг).

Почему: В Kubernetes или похожей системе контейнеру игрового сервера задан лимит CPU (limit) → Следствие: В момент пиковых расчётов тика квота кончается, и контейнер стоит десятки ms до следующего периода → На экране: Средняя загрузка CPU низкая, но время тика периодически скачет: микрофризы, слоумо

Симптомы: Микрофризы, Слоумо · Основной ответственный Команда инфраструктуры · Серверная инфраструктура · Совместно Команда разработки · Разработка сервера

Всплески задержки из-за управления питанием сервера (C-state, управление частотой) CPU power management latency (C-states, frequency scaling)

Простаивающее ядро CPU ради экономии энергии переходит в глубокое состояние сна (C-state) и снижает частоту. Когда приходит пакет или срабатывает таймер, на пробуждение и подъём частоты уходит время, и к обработке даже маленьких пакетов добавляется задержка.

Почему: Политика управления частотой в ОС (governor) или настройки питания в BIOS разрешают глубокие C-state и низкие частоты → Следствие: Каждое пробуждение ядра из глубокого сна добавляет до сотен µs, а если частота зафиксирована на низком уровне, медленнее идёт сам расчёт тика → На экране: Обычно это почти незаметно, но при большом числе межсерверных вызовов задержки складываются, и в часы затишья ответ, как ни странно, приходит позже: задержка ввода. Если частота зафиксирована на низком уровне, при наплыве игроков тики отстают: слоумо

Симптомы: Задержка ввода, Слоумо · Основной ответственный Команда инфраструктуры · Серверная инфраструктура

OOM killer Out-of-memory killer

Когда память заканчивается, Linux выбирает процесс, который занимает больше всего памяти, и принудительно его завершает. Обычно это игровой сервер.

Почему: Память исчерпана из-за утечки или резкого роста потребления, либо контейнер упёрся в лимит памяти → Следствие: Ядро принудительно завершает процесс игрового сервера → На экране: Дисконнект у всех на этом сервере одновременно, возможен роллбэк недавнего прогресса

Симптомы: Дисконнект, Съеденные действия / роллбэк · Основной ответственный Команда разработки · Разработка сервера · Совместно Команда инфраструктуры · Серверная инфраструктура

Остановки из-за освобождения и уплотнения памяти Memory compaction / reclaim stalls (THP)

Процесс останавливается, пока ОС уплотняет память (compaction), чтобы собрать большие страницы (huge pages), или освобождает память, чтобы пополнить запас свободной (reclaim).

Почему: Свободной памяти становится мало, или механизм больших страниц (THP) запускает уплотнение памяти → Следствие: Поток, запросивший память, ждёт, пока закончится освобождение или уплотнение → На экране: Нерегулярные остановки сервера (от единиц до сотен ms)

Симптомы: Фриз, Микрофризы · Основной ответственный Команда инфраструктуры · Серверная инфраструктура · Совместно Команда разработки · Разработка сервера

Скачок системных часов (шаговая коррекция NTP) Wall-clock jump (NTP step)

Если часы сервера разом переводятся на несколько секунд вперёд или назад, таймеры, завязанные на системные часы, срабатывают пачкой или замирают.

Почему: Синхронизация времени резко переводит часы → Следствие: Таймеры срабатывают пачкой или замирают, таймауты определяются неверно → На экране: Сбои баффов и кулдаунов, массовый дисконнект, перемотка

Симптомы: Перемотка, Дисконнект, Съеденные действия / роллбэк · Основной ответственный Команда разработки · Разработка сервера · Совместно Команда инфраструктуры · Серверная инфраструктура

Плановые задания Cron jobs (log rotation, backup, scans)

Сжатие логов, бэкапы и проверки безопасности, которые запускаются каждый день в одно и то же время, занимают CPU и диск.

Почему: В заданное время запускаются задания ОС → Следствие: Они делят CPU и диск с игровым сервером → На экране: В определённое время, например каждый день в 4:00, микрофризы и слоумо

Симптомы: Микрофризы, Слоумо · Основной ответственный Команда инфраструктуры · Серверная инфраструктура

Изменение производительности после обновления ОС, ядра, драйверов или прошивки Performance regression after OS / kernel / driver / firmware update

Игровой код не менялся, но после обновления ОС, ядра, драйверов или прошивки сервер стал работать медленнее. Обновление может поменять значения по умолчанию, планировщик, защиту от уязвимостей CPU (mitigations) и поведение драйверов.

Почему: Регулярный патч безопасности или новый образ сервера меняет ядро, драйверы или прошивку → Следствие: Меняются значения по умолчанию или планировщик, включается новая защита от уязвимостей: на ту же работу уходит больше процессорного времени, а потоки получают CPU в другом порядке → На экране: Сервер, который работал нормально, со дня обновления постоянно чуть медленнее: задержка ввода, а при наплыве игроков микрофризы и слоумо

Симптомы: Задержка ввода, Микрофризы, Слоумо · Основной ответственный Команда инфраструктуры · Серверная инфраструктура

Переполнение таблицы conntrack на сервере conntrack table full

Когда таблица отслеживания соединений (conntrack), в которую файрвол Linux записывает все соединения, достигает лимита, новые пакеты отбрасываются.

Почему: Из-за наплыва подключений и множества коротких соединений растёт число записей → Следствие: Таблица заполнена, новые соединения и часть пакетов отбрасываются → На экране: Ошибка входа, телепортация из-за необъяснимых потерь

Симптомы: Ошибка входа / бесконечная загрузка, Телепортация · Основной ответственный Команда инфраструктуры · Серверная инфраструктура · Совместно Команда разработки · Разработка сервера, Команда разработки · Разработка клиента

Исчерпание эфемерных портов в межсерверных соединениях Ephemeral port exhaustion (TIME_WAIT)

Если игровой сервер часто открывает и закрывает короткие соединения с БД или другими серверами, закрытые соединения ещё какое-то время занимают порты, и новые соединения открыть не удаётся.

Почему: На каждый запрос открывается и закрывается новое соединение → Следствие: Сторона, закрывшая соединение первой, держит порт около 60 секунд (в Linux) в состоянии TIME_WAIT, и свободные порты заканчиваются → На экране: Внутренние запросы не проходят: сбои сохранения и ошибки функций

Симптомы: Съеденные действия / роллбэк, Ошибка входа / бесконечная загрузка · Основной ответственный Команда разработки · Разработка сервера · Совместно Команда инфраструктуры · Серверная инфраструктура

Сокеты и протоколы: TCP, UDP, опции сокетов

Здесь определяется, как игра обменивается данными по сети. На одной и той же линии потеря одного пакета может закончиться «лёгким рывком», а может превратиться в «фриз на секунду, а потом перемотку», в зависимости от протокола и включённых опций сокета.

TCP гарантирует доставку всего и в порядке отправки. Взамен, потеряв один пакет, он не отдаёт игре даже то, что пришло после него, и ждёт, пока потерянный не придёт повторно. UDP не гарантирует ничего. Пришедшее он отдаёт сразу, без ожидания, а с потерянным игра должна разбираться сама. Поэтому динамичные игры сами реализуют поверх UDP ровно столько надёжности, сколько нужно (надёжный UDP), а многие MMO используют TCP, который проще в реализации, и мирятся с его слабостями.

Опции сокета задают детали этого поведения: копить ли мелкие пакеты перед отправкой (TCP_NODELAY), какого размера буферы отправки и приёма (SO_SNDBUF, SO_RCVBUF), когда замечать мёртвое соединение (SO_KEEPALIVE, TCP_USER_TIMEOUT), что делать с оставшимися данными при закрытии (SO_LINGER). Значения по умолчанию в основном рассчитаны на эффективную отправку больших объёмов малым числом пакетов, поэтому играм, которые часто обмениваются мелкими пакетами, они нередко мешают.

Главное

TCP отдаёт игре полученные данные только в порядке отправки. Если пропал пакет 17, то даже когда 18–30 уже пришли, все они ждут, пока 17 не придёт повторно (HOL-блокировка). UDP отдаёт данные по мере прихода, поэтому, даже если 17 так и не придёт, остальные обрабатываются вовремя.

Почему возникают повторные передачи (Wi-Fi, перегрузка, чёрная дыра MTU, ложные повторные передачи и т. п.) и как найти их причину, разобрано отдельно по каждой причине в главе 06 Повторная передача TCP.

Причины лагов на этом слое

HOL-блокировка в TCP Head-of-line blocking

Чтобы сохранить порядок, TCP не передаёт игре пакеты, пришедшие позже, пока заново не получит один потерянный пакет.

Почему: Один пакет теряется → Следствие: Следующие пакеты уже пришли, но ждут в буфере приёма → На экране: Всё замирает, а потом разом прорывается: перемотка

Симптомы: Фриз, Перемотка · Основной ответственный Команда разработки · Разработка сервера · Совместно Команда разработки · Разработка клиента

TCP RTO и экспоненциальный backoff RTO and exponential backoff

С каждой новой неудачной повторной передачей ожидание удваивается, и короткий обрыв связи превращается в долгую остановку.

Почему: Связь ненадолго обрывается, и повторные передачи тоже одна за другой не доходят → Следствие: Ожидание до следующей попытки каждый раз удваивается: 0,3 → 0,6 → 1,2 → 2,4 с (при пинге 100 ms) → На экране: Связь пропала на 1 с, а фриз в игре длится больше 2 с. Если обрыв дольше, в итоге дисконнект

Симптомы: Фриз, Дисконнект · Основной ответственный Команда разработки · Разработка сервера · Совместно Команда разработки · Разработка клиента

Алгоритм Нейгла + отложенный ACK Nagle + delayed ACK (TCP_NODELAY off)

Алгоритм Нейгла, который копит мелкие пакеты перед отправкой, и отложенный ACK, который придерживает подтверждения, мешают друг другу, и каждое сообщение, записанное по частям, задерживается на 40–200 ms.

Почему: Мелкие сообщения пишутся по частям без включённого TCP_NODELAY → Следствие: Отправитель ждёт ACK, а получатель отправляет ACK с задержкой → На экране: Пинг низкий, но все действия одинаково запаздывают: задержка ввода

Симптомы: Задержка ввода · Основной ответственный Команда разработки · Разработка сервера · Совместно Команда разработки · Разработка клиента

Блокирующая отправка из-за медленного клиента Blocking send on a full socket

Если у одного игрока с медленным подключением заполнился буфер отправки, а сервер отправляет данные блокирующим способом (вызов не возвращается, пока в буфере не освободится место), поток сервера ждёт этого одного игрока.

Почему: Буфер отправки медленного клиента заполнен → Следствие: Отправка блокирующая, и поток сервера ждёт, пока в буфере освободится место → На экране: У всех, кого обслуживает этот поток, фриз или слоумо

Симптомы: Фриз, Слоумо · Основной ответственный Команда разработки · Разработка сервера

Политика для медленных клиентов (slow consumer) Slow-consumer policy

Если для клиента постоянно копятся неотправленные данные, сервер выбрасывает устаревшие обновления или разрывает соединение.

Почему: Подключение клиента не справляется с объёмом, который отправляет сервер → Следствие: Сервер выбрасывает устаревшие обновления или при превышении лимита разрывает соединение → На экране: Только у этого игрока телепортация или дисконнект

Симптомы: Телепортация, Дисконнект · Основной ответственный Команда разработки · Разработка сервера

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

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

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

Симптомы: Ошибка входа / бесконечная загрузка, Невидимки / фантомы · Основной ответственный Команда разработки · Разработка сервера · Совместно Команда разработки · Разработка клиента, Команда инфраструктуры · Серверная инфраструктура

IP-фрагментация UDP-пакетов IP fragmentation of large UDP

UDP-пакет больше MTU (размера, который можно отправить за один раз) фрагментируется на уровне IP, и при потере всего одного фрагмента выбрасывается весь пакет.

Почему: Снапшот людного места больше 1 500 байт → Следствие: Пакет уходит несколькими фрагментами, и при потере любого из них выбрасывается целиком → На экране: Чем больше пакет, тем в разы выше доля потерь. Телепортация только в людных местах

Симптомы: Телепортация · Основной ответственный Команда разработки · Разработка сервера

Настройка повторных передач в надёжном UDP Reliable-UDP tuning (KCP, ENet…)

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

Почему: Интервал повторов, их число и размер окна не соответствуют качеству подключения → Следствие: Восстановление запаздывает, либо дублирующие передачи усиливают перегрузку → На экране: Умения «съедаются», перемотка, при перегрузке лаги сильнее

Симптомы: Съеденные действия / роллбэк, Перемотка · Основной ответственный Команда разработки · Разработка сервера · Совместно Команда разработки · Разработка клиента

Медленный старт после простоя Slow start after idle

Если соединение какое-то время простаивало, TCP снова уменьшает окно перегрузки (объём, который можно отправить за раз), и внезапно понадобившийся большой объём данных уходит в несколько заходов.

Почему: По простаивавшему соединению отправляется большой объём данных, например при входе в город → Следствие: Окно перегрузки уменьшено, и передача растягивается на несколько RTT → На экране: Сразу после входа окружающие персонажи и NPC появляются с опозданием на несколько RTT (тем заметнее, чем дальше сервер)

Симптомы: Задержка ввода, Невидимки / фантомы · Основной ответственный Команда инфраструктуры · Серверная инфраструктура · Совместно Команда разработки · Разработка сервера

Резкий спад передачи из-за управления перегрузкой Congestion control backoff

TCP считает потери признаком перегрузки и снижает скорость передачи на 30–50%. Точно так же он реагирует и на потери в Wi-Fi.

Почему: Когда отправлять нужно много, в Wi-Fi или на линии случаются небольшие потери → Следствие: TCP резко снижает скорость передачи и восстанавливает её медленно (CUBIC, алгоритм по умолчанию в Linux и Windows, снижает на 30%) → На экране: В людных местах обновления отстают: перемотка, задержка ввода

Симптомы: Перемотка, Задержка ввода · Основной ответственный Команда инфраструктуры · Серверная инфраструктура · Совместно Команда разработки · Разработка сервера

Потеря последних данных при принудительном закрытии через RST SO_LINGER, abrupt RST

Если сервер резко рвёт соединение, последнее отправленное сообщение или подтверждение сохранения пропадает.

Почему: Сервер закрывает соединение принудительно (RST). Так бывает, если SO_LINGER выставлен в 0 с или сокет закрыт, когда полученные данные ещё не дочитаны → Следствие: Причина кика и последние данные, которые ещё передавались, выбрасываются → На экране: Сообщение «Соединение закрыто из-за неизвестной ошибки» без видимой причины

Симптомы: Дисконнект · Основной ответственный Команда разработки · Разработка сервера

Архитектура с блокирующим вводом-выводом Blocking I/O model

Если поток, ожидая один сокет, не может делать ничего другого, то с ростом числа игроков тормозит всё.

Почему: Поток ждёт чтения и записи по каждому соединению → Следствие: Задержка одного соединения распространяется на другие соединения того же потока → На экране: Чем выше онлайн, тем сильнее у всех слоумо и задержка ввода

Симптомы: Слоумо, Задержка ввода · Основной ответственный Команда разработки · Разработка сервера

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

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

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

Симптомы: Ошибка входа / бесконечная загрузка, Фриз, Дисконнект · Основной ответственный Команда разработки · Разработка сервера · Совместно Команда инфраструктуры · Серверная инфраструктура

Ошибка WSAECONNRESET на UDP-сокете в Windows WSAECONNRESET on a Windows UDP socket

Когда сервер на Windows отправляет UDP уже ушедшему клиенту, обратно приходит уведомление «порт недоступен» (ICMP). Из-за него следующий вызов приёма завершается ошибкой, и если код сервера считает её поломкой самого сокета, страдают все, кто работает через этот сокет.

Почему: Сервер продолжает слать UDP на адрес только что вышедшего клиента, и обратно приходит «порт недоступен» (ICMP) → Следствие: Windows завершает следующий вызов приёма ошибкой WSAECONNRESET (10054), а код сервера прекращает приём или закрывает сокет → На экране: У всех, кто работал через этот сокет, разом фриз или дисконнект

Симптомы: Дисконнект, Фриз · Основной ответственный Команда разработки · Разработка сервера

Процесс игрового сервера: тики и потоки

Программа, которая на самом деле считает игровую логику. Перемещение, бой, ИИ монстров, расчёт зоны видимости и рассылка должны уложиться в один «тик». Чем больше людей собирается в одном месте, тем быстрее растут расчёт видимости и число пакетов к отправке: пропорционально квадрату числа игроков.

Сервер рассчитывает состояние игры с фиксированным интервалом тика. 20-тиковый сервер делает это каждые 50 ms: за это время он применяет ввод всех игроков, двигает монстров, вычисляет, кто кого видит (зона видимости, AOI), и рассылает изменения всем, кто может их видеть. Эти 50 ms и есть бюджет тика. Если бюджет превышен, следующий тик запаздывает. На сервере, который за каждый тик продвигает игровое время на фиксированный шаг, всё время в игре течёт медленнее (слоумо), а сервер, который продвигает время сразу на фактически прошедшее, сохраняет скорость, но пакеты становятся реже, и появляются микрофризы и телепортация. В обоих случаях отклик запаздывает. Если один игровой поток обслуживает весь сервер (канал), страдают все на этом сервере, а если потоки разделены по локациям, страдают игроки этой локации.

Проблема в количестве людей. Если сравнивать всех со всеми, при 100 игроках это около 10 000 проверок, а при 1 000 около 1 000 000 на каждом тике. Поэтому сервер делит карту на сетку и сравнивает только соседние ячейки, но когда все собираются около одной ячейки, как на мировом боссе, осаде или событии на городской площади, сетка помогает меньше, а объём вычислений и данных к отправке взрывается. Если к этому добавляются блокировки, когда несколько потоков ждут одни и те же данные, или синхронные вызовы, когда посреди тика ждут ответа БД, то на время ожидания замирают все, кого обслуживает этот поток.

Аналогия

Тик сервера похож на такт дирижёра. Чем больше музыкантов (игроков) в оркестре, тем больше нот нужно успеть за один такт, а если такт сбивается, замедляется вся пьеса. А если кто-то ушёл на склад (в БД) за листом нот, все ждут его.

Причины лагов на этом слое

Превышение бюджета тика Tick overrun

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

Почему: Работа на один тик (например, 50 ms) не укладывается в бюджет → Следствие: Состояние игры, которое нужно считать 20 раз в секунду, считается только 8 раз → На экране: Слоумо во всей локации (в зависимости от архитектуры сервера микрофризы), умения срабатывают с опозданием

Симптомы: Слоумо, Задержка ввода, Микрофризы · Основной ответственный Команда разработки · Разработка сервера · Совместно Команда инфраструктуры · Серверная инфраструктура

Взрывной рост расчёта видимости (AOI, N²) Area-of-interest explosion

Если выяснять, кто кого видит, сравнивая всех со всеми, то при росте числа игроков в 10 раз расчёты растут в 100 раз.

Почему: Расстояние сравнивается между всеми персонажами, или карта разбита на сетку, но вокруг одной ячейки собираются сотни игроков → Следствие: Для 100 игроков около 10 000 сравнений, для 1 000 около 1 000 000 → На экране: Там, где все собрались вместе (мировой босс, осада), время тика взлетает: слоумо, микрофризы

Симптомы: Слоумо, Микрофризы · Основной ответственный Команда разработки · Разработка сервера

Взрывной рост рассылки (broadcast) Broadcast fan-out (N×N)

Если движение каждого игрока отправлять всем, кто его видит, число обновлений растёт как квадрат числа собравшихся.

Почему: Изменение у одного игрока рассылается всем, кто его видит → Следствие: Если 1 000 игроков видят друг друга, это 1 000 000 обновлений за тик → На экране: Очереди отправки и пропускная способность забиты: задержки и потери (задержка ввода, перемотка, телепортация)

Симптомы: Задержка ввода, Телепортация, Перемотка · Основной ответственный Команда разработки · Разработка сервера · Совместно Команда инфраструктуры · Серверная инфраструктура

Перегрузка однопоточной локации (хотспот) Single-threaded hot zone

Если каждую локацию обслуживает один поток, то при скоплении игроков в одном месте на 100% загружается только одно ядро.

Почему: Одну локацию (канал) обслуживает один поток → Следствие: Когда игроки собираются в одном месте, загружено только это ядро, остальные свободны → На экране: Лагает только эта локация, в других всё нормально

Симптомы: Слоумо, Задержка ввода · Основной ответственный Команда разработки · Разработка сервера · Совместно Команда инфраструктуры · Серверная инфраструктура

Конкуренция за блокировки Lock contention

Если несколько потоков ждут одну блокировку, чтобы работать с одними и теми же данными, то сколько потоков ни добавляй, выполняется только один за раз.

Почему: Несколько потоков одновременно работают с общими данными, например аукционом или хранилищем гильдии → Следствие: Пока поток, захвативший блокировку, не закончит, остальные ждут → На экране: Тормозит только определённая функция, в тяжёлых случаях отстают тики всего сервера

Симптомы: Задержка ввода, Фриз · Основной ответственный Команда разработки · Разработка сервера

Дедлок Deadlock

Если два потока ждут блокировки, захваченные друг другом, они встают навсегда.

Почему: Поток A держит блокировку 1 и ждёт блокировку 2, а поток B держит блокировку 2 и ждёт блокировку 1 → Следствие: Оба встают навсегда, а за ними цепочкой встают и связанные потоки → На экране: Весь сервер стоит, watchdog его перезапускает, у всех дисконнект

Симптомы: Фриз, Дисконнект · Основной ответственный Команда разработки · Разработка сервера

Синхронные вызовы в игровом потоке Synchronous DB / file I/O on the game loop

Если посреди тика ждать ответа БД или записи в файл, на это время останавливается вся игра на сервере.

Почему: Внутри тика поток ждёт запросов и сохранений в БД, записи логов, вызовов внешних API → Следствие: Если БД отвечает 100 ms, тик тоже стоит 100 ms → На экране: Каждый раз, когда тормозит БД или диск, вся открытая локация на миг замирает

Симптомы: Фриз, Микрофризы · Основной ответственный Команда разработки · Разработка сервера

Затор в очереди сообщений Mailbox / job queue backlog

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

Почему: Запросы приходят быстрее, чем обрабатываются → Следствие: Очередь растёт, а при превышении лимита запросы выбрасываются → На экране: Умения и обмены срабатывают с опозданием или «съедаются»

Симптомы: Задержка ввода, Съеденные действия / роллбэк · Основной ответственный Команда разработки · Разработка сервера

Одновременное срабатывание таймеров Synchronized timers

Если респавн всех монстров, окончание всех баффов и награды ровно в начале часа приходятся на один тик, этот тик становится в десятки раз тяжелее.

Почему: Таймеры респавна, окончания эффектов, наград и автосохранения выставлены на одно и то же время → Следствие: В этот один тик работы в десятки раз больше обычного → На экране: В определённое время каждый раз всё на миг замирает

Симптомы: Фриз, Микрофризы · Основной ответственный Команда разработки · Разработка сервера

Лавина поиска пути Pathfinding storms

Когда сотни монстров одновременно гонятся за игроками и рассчитывают путь, это сильно нагружает CPU.

Почему: Из-за сбора монстров «паровозом» и массового спавна монстры одновременно преследуют игроков → Следствие: Каждый монстр рассчитывает путь → На экране: Слоумо только на этом месте фарма

Симптомы: Слоумо · Основной ответственный Команда разработки · Разработка сервера

Затраты на сериализацию и сжатие Serialization / compression cost

Превращение данных для отправки в байты и их сжатие тоже требуют CPU, и при большом числе игроков эти затраты резко растут.

Почему: Для каждого обновления структура преобразуется в байты и сжимается → Следствие: Затраты растут пропорционально квадрату числа игроков → На экране: Отправка запаздывает: задержка ввода

Симптомы: Задержка ввода · Основной ответственный Команда разработки · Разработка сервера

Падение сервера Server process crash

Если процесс сервера падает из-за необработанной ошибки, у всех, кто был на этом сервере, одновременно обрывается соединение.

Почему: Фатальная ошибка: обращение к несуществующему объекту (нулевая ссылка), некорректные данные, нехватка памяти и т. п. → Следствие: Процесс сервера (или зоны) завершается → На экране: Дисконнект у всех одновременно, прогресс после последнего сохранения может уйти в роллбэк

Симптомы: Дисконнект, Съеденные действия / роллбэк · Основной ответственный Команда разработки · Разработка сервера · Совместно Команда инфраструктуры · Серверная инфраструктура

Исчерпание пула потоков Thread pool starvation

Если все рабочие потоки заняты медленными задачами, новые запросы ждут неопределённо долго.

Почему: Рабочие потоки заняты ожиданием ответа внешних API или БД → Следствие: Для новых запросов не остаётся свободных потоков → На экране: Бесконечная загрузка в отдельных функциях, например при входе или в магазине

Симптомы: Ошибка входа / бесконечная загрузка, Задержка ввода, Фриз · Основной ответственный Команда разработки · Разработка сервера

Бесконечный цикл и неконтролируемая логика Infinite loop / runaway logic

Если из-за бага тик не заканчивается, сервер встаёт, и watchdog принудительно его перезапускает.

Почему: Из-за ошибочного условия цикл не завершается, или рекурсия уходит вразнос → Следствие: Тик не заканчивается, сервер стоит → На экране: Фриз, затем дисконнект у всех

Симптомы: Фриз, Дисконнект · Основной ответственный Команда разработки · Разработка сервера

Бой, сосредоточенный на одной цели (мировой босс) Hot entity / combat event fan-out

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

Почему: Сотни игроков без остановки применяют к одному боссу умения, баффы и дебаффы → Следствие: Расчёты здоровья босса, списка агро и дебаффов сходятся в одной точке, а пакеты с цифрами урона и эффектами за каждый удар рассылаются всем, кто это видит → На экране: Умения проходят с опозданием, цифры урона вылетают пачкой, слоумо только вокруг босса

Симптомы: Задержка ввода, Перемотка, Слоумо · Основной ответственный Команда разработки · Разработка сервера

Лавина спавна при входе в людное место Spawn burst when entering a crowd

Когда игрок телепортируется в город, полный людей, сервер должен разом отправить внешность, экипировку и состояние сотен персонажей, которые стали видны.

Почему: Игрок внезапно оказывается в людном месте после телепорта, входа в игру или смены канала → Следствие: Полные данные по сотням персонажей собираются и отправляются за раз, и ПК игрока тоже загружает их разом → На экране: Сразу после прибытия короткий фриз, персонажи появляются с опозданием по одному, ввод запаздывает

Симптомы: Фриз, Задержка ввода, Перемотка · Основной ответственный Команда разработки · Разработка сервера · Совместно Команда разработки · Разработка клиента

Накопление объектов (неубранные предметы и призванные существа) Entity / timer buildup over uptime

Если предметы на земле, призванные существа и отработавшие таймеры, которые должны исчезать, не удаляются и копятся, то чем дольше сервер работает, тем больше работы в каждом тике.

Почему: Предметы на земле, призванные существа, истёкшие таймеры и данные пустых групп вовремя не удаляются → Следствие: Списки, которые обходятся каждый тик, с каждым днём становятся длиннее → На экране: Сразу после техработ всё нормально, а через несколько дней именно этот сервер или локация постепенно начинает тормозить

Симптомы: Слоумо, Микрофризы, Задержка ввода · Основной ответственный Команда разработки · Разработка сервера

Патч изменил характер трафика Patch changes traffic pattern

Если новый контент, эффекты и синхронизируемые поля увеличивают размер и частоту пакетов, сервер, который работал нормально, после патча упирается в MTU, пропускную способность или лимиты по числу пакетов.

Почему: С патчем добавились эффекты умений, синхронизируемые поля и данные предметов, и пакеты стали больше или чаще → Следствие: Большие пакеты превышают MTU и фрагментируются, а возросший объём упирается в пропускную способность, лимит PPS в облаке или буфер отправки → На экране: Сразу после патча в людных местах телепортация, «съеденные» умения и задержка ввода. В инфраструктуре ничего не меняли, а потерь стало больше

Симптомы: Телепортация, Съеденные действия / роллбэк, Задержка ввода · Основной ответственный Команда разработки · Разработка сервера · Совместно Команда инфраструктуры · Серверная инфраструктура, Команда инфраструктуры · Сетевая инфраструктура

Память

Всё, что сервер помнит, то есть персонажи, монстры, предметы и карты, лежит в памяти. Сама память быстрая, но лаг возникает в тот момент, когда сервер останавливается на GC (сборку неиспользуемой памяти), память понемногу утекает (утечка) или её не хватает и начинается своп (часть памяти переносится на диск).

В языках с автоматическим управлением памятью, таких как Java, C# и Go, использованную и брошенную память собирает и возвращает сборщик мусора (GC). В зависимости от устройства GC он может ненадолго останавливать все потоки. Если GC проходит всю кучу (область памяти, которую программа выделяет себе во время работы) за один раз, то чем больше живых данных, тем дольше это длится: от сотен ms до нескольких секунд. Современные GC вроде ZGC сокращают паузы до значений меньше 1 ms, но тратят больше CPU и памяти. Серверы на C++ обходятся без GC, но страдают от утечек, когда копится память, которую забыли освободить, и от фрагментации, когда свободное место дробится на мелкие куски и большой блок выделить уже нельзя. Утечка бывает и при GC, если на ненужный объект где-то продолжает висеть ссылка.

Ещё одна причина медленной памяти: иерархия памяти (насколько далеко хранилище от CPU). Кэш прямо рядом с CPU отвечает за 1 ns, RAM за 100 ns, а повторное чтение памяти, выгруженной на диск (своп), занимает больше чем в 1 000 раз дольше, чем чтение из RAM. Растяните эту разницу до человеческого времени в таблице «Порядки задержек» ниже.

Аналогия

Память похожа на рабочий стол повара. Если продукты под рукой (кэш), всё быстро; если идти к холодильнику (RAM), чуть медленнее; а если стол завален и продукты приходится держать на складе (диск, своп), за каждым приходится долго ходить. А пока идёт мытьё посуды (GC), готовку приходится остановить.

Причины лагов на этом слое

Полная пауза GC на сервере Stop-the-world GC pause

Сервер на Java или C# останавливает все потоки на время сборки мусора (stop-the-world), и на это время замирает весь сервер.

Почему: Куча заполняется, запускается GC → Следствие: Все игровые потоки останавливаются на время сборки (чем больше живых данных, тем дольше) → На экране: У всех игроков сервера одновременно фриз, затем перемотка

Симптомы: Фриз, Перемотка · Основной ответственный Команда разработки · Разработка сервера · Совместно Команда инфраструктуры · Серверная инфраструктура

Паузы GC в скриптовом движке Scripting VM GC (Lua, etc.)

Если на сервере, пусть даже написанном на C++, квесты, AI и умения выполняются скриптами (например, на Lua), то на время работы GC скриптового движка эта зона останавливается.

Почему: В каждой зоне скриптовый движок выполняет квесты, AI и события и создаёт массу временных объектов → Следствие: Когда GC скриптового движка собирает много за один раз, тик этой зоны останавливается → На экране: Короткие периодические подвисания только в определённой зоне или во время определённого события

Симптомы: Микрофризы, Фриз · Основной ответственный Команда разработки · Разработка сервера

Лавина аллокаций Allocation storms

Если во время события создаётся масса временных объектов, GC запускается намного чаще обычного.

Почему: Дроп предметов, боевые логи и награды события резко увеличивают число временных объектов → Следствие: GC запускается в несколько раз чаще, объекты, которые не успели стать мусором, переходят в область Old, и Full GC тоже наступает раньше → На экране: Короткие периодические подвисания только во время событий

Симптомы: Микрофризы, Фриз · Основной ответственный Команда разработки · Разработка сервера

Утечка памяти Memory leak

Неосвобождённая память понемногу накапливается, и через несколько дней это заканчивается трешингом GC, свопом или принудительным завершением процесса.

Почему: Данные персонажей, вышедших из игры, и обработчики событий не освобождаются → Следствие: Свободной памяти становится всё меньше в течение нескольких дней → На экране: Сразу после техработ всё в порядке, с каждым днём лагает сильнее, в итоге сервер падает

Симптомы: Слоумо, Фриз, Дисконнект · Основной ответственный Команда разработки · Разработка сервера · Совместно Команда инфраструктуры · Серверная инфраструктура

Трешинг GC (мало свободного места в куче) GC thrashing (heap nearly full)

Когда живые данные приближаются к пределу кучи, GC почти нечего освобождать, и сборки идут одна за другой без перерыва.

Почему: Из-за роста онлайна на событии или утечки живые данные заполняют кучу почти до предела → Следствие: GC освобождает совсем немного, и сразу снова запускается Full GC, большую часть CPU занимает GC → На экране: Весь сервер несколько минут то уходит в слоумо, то ловит фризы, а затем падает из-за нехватки памяти

Симптомы: Слоумо, Фриз, Дисконнект · Основной ответственный Команда разработки · Разработка сервера · Совместно Команда инфраструктуры · Серверная инфраструктура

Своп Swapping

Когда памяти не хватает и ОС выгружает её часть на диск, при каждом обращении к этой памяти приходится ждать диск, который медленнее больше чем в 1 000 раз.

Почему: Занятая память превышает физическую RAM → Следствие: ОС выгружает часть памяти на диск и читает её обратно, когда она нужна → На экране: Время тика вырастает до сотен ms, у всех игроков сервера слоумо и фризы

Симптомы: Слоумо, Фриз · Основной ответственный Команда инфраструктуры · Серверная инфраструктура · Совместно Команда разработки · Разработка сервера

Промах кэша CPU cache misses

Если данные разбросаны по памяти, CPU каждый раз ждёт медленную RAM.

Почему: Объекты разбросаны по памяти и связаны указателями, обращения к ним идут вразнобой → Следствие: Данных нет в кэше CPU, и их каждый раз приходится читать из RAM (примерно в 100 раз медленнее) → На экране: Та же работа обходится тику в несколько раз дороже, в тяжёлых случаях слоумо

Симптомы: Слоумо · Основной ответственный Команда разработки · Разработка сервера

Фрагментация памяти Heap fragmentation

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

Почему: Много потоков долго выделяют и освобождают блоки памяти разного размера → Следствие: Свободное место раздроблено, вернуть его ОС нельзя, и потребление растёт, как при утечке → На экране: Чем дольше работает сервер, тем сильнее он тормозит из-за свопа и нехватки памяти, а затем принудительно завершается

Симптомы: Слоумо, Дисконнект · Основной ответственный Команда разработки · Разработка сервера

Удалённая память NUMA Remote NUMA access

На сервере с двумя процессорами обращение к памяти, подключённой к другому процессору, идёт медленнее.

Почему: Потоки и их память оказываются на разных процессорных сокетах → Следствие: Обращения к памяти замедляются (в 1,5–2 раза в зависимости от оборудования) → На экране: На одинаковом железе процессы работают с разной скоростью

Симптомы: Слоумо · Основной ответственный Команда инфраструктуры · Серверная инфраструктура

Диск

Логи, сохранения персонажей, данные карт и файлы БД хранятся на диске. Диск медленнее памяти в сотни раз (SSD) и вплоть до 100 000 раз (HDD), поэтому, если игровой сервер устроен так, что ждёт диск, игра встаёт в тот же момент, когда диск становится занят.

Производительность диска измеряют тем, «сколько раз в секунду он может читать и писать» (IOPS). У старого HDD это около 150, у SSD от десятков до сотен тысяч. У облачного диска лимит определяется тем, сколько вы платите (у стандартного gp3 в AWS 3 000). Некоторые облачные диски и небольшие конфигурации серверов сверх обычной скорости дают burst-кредиты на кратковременное повышение производительности, но если пиковая нагрузка затягивается, кредиты кончаются и скорость резко падает. Так выглядят жалобы вида «каждый вечер через несколько часов начинаются лаги».

Главное: кто ждёт. Обычная запись в файл сначала попадает в память ОС и лишь потом сбрасывается на диск, поэтому обычно завершается сразу. Проблемы начинаются, когда просят дождаться, «пока данные реально запишутся на диск» (fsync), или когда заполняется объём, который ОС может держать в памяти. Если в этот момент ждёт сам игровой поток (синхронно), то при задержке диска на 100 ms тик тоже встаёт на 100 ms. Если передать запись отдельному потоку (асинхронно), игра не встаёт, но при внезапном падении сервера ещё не записанное может пропасть (съеденные действия / роллбэк).

Аналогия

Диск похож на склад, а IOPS на число дверей склада. Если дверей мало, те, кто заносит и выносит вещи, стоят в очереди. Burst-кредиты похожи на запас сил для короткого рывка: когда они кончаются, остаётся идти шагом.

Причины лагов на этом слое

Синхронная запись логов Synchronous logging

Если игровой поток на каждой строке лога ждёт, пока диск завершит запись, то при занятом диске останавливается и игра.

Почему: Боевые логи и логи обменов пишутся в файл прямо из игрового потока → Следствие: Если требуется гарантированная запись (fsync) или буфер записи ОС (страничный кэш) заполнен до предела, при занятом диске одна запись длится десятки ms → На экране: Подвисания в боях, где пишется много логов

Симптомы: Микрофризы, Фриз · Основной ответственный Команда разработки · Разработка сервера · Совместно Команда инфраструктуры · Серверная инфраструктура

Лавина fsync fsync storms

Запрос записать данные на диск «гарантированно» занимает от 0,1 ms до десятков ms в зависимости от диска, а когда таких запросов много, очередь растёт.

Почему: Периодические сохранения и массовый выход из игры дают пачку запросов на гарантированную запись → Следствие: Очередь к диску растёт → На экране: Лаги в моменты сохранения, задержки при выходе из игры и смене канала

Симптомы: Микрофризы, Задержка ввода · Основной ответственный Команда разработки · Разработка сервера · Совместно Команда инфраструктуры · Серверная инфраструктура, Команда инфраструктуры · Инфраструктура БД

Исчерпание burst-кредитов облачного диска Burst credit depletion

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

Почему: Диск долго работает выше базовой производительности → Следствие: Burst-кредиты кончаются, производительность резко падает до базовой → На экране: Каждый вечер через несколько часов нагрузки начинаются лаги

Симптомы: Микрофризы, Слоумо, Задержка ввода · Основной ответственный Команда инфраструктуры · Серверная инфраструктура · Совместно Команда инфраструктуры · Инфраструктура БД

Лимит IOPS и насыщение очереди IOPS limit / queue saturation

Если запросов больше, чем диск может обработать за секунду, очередь растёт и задержка резко увеличивается.

Почему: Запросы на чтение и запись приближаются к пределу производительности диска → Следствие: Очередь растёт (обычно резко при утилизации от 90%) → На экране: Задержки сохранения и загрузки, а при синхронных вызовах фризы

Симптомы: Задержка ввода, Фриз · Основной ответственный Команда инфраструктуры · Серверная инфраструктура · Совместно Команда разработки · Разработка сервера, Команда инфраструктуры · Инфраструктура БД

Диск заполнен Disk full

Когда логи и дампы заполняют диск, запись завершается ошибкой, и если к этому не подготовиться, сервер падает.

Почему: Логи, дампы и временные файлы заполняют диск на 100% → Следствие: Запись не удаётся. Без обработки ошибок сервер падает, с обработкой не проходят сохранения → На экране: Дисконнект, роллбэк прогресса

Симптомы: Дисконнект, Съеденные действия / роллбэк · Основной ответственный Команда инфраструктуры · Серверная инфраструктура · Совместно Команда инфраструктуры · Инфраструктура БД, Команда разработки · Разработка сервера

Бэкап, сжатие и сканирование Backup / compression / scans

Когда ночной бэкап, сжатие логов или проверка безопасности занимают диск целиком, чтение и запись игрового сервера застревают.

Почему: Запускается плановый бэкап или сжатие → Следствие: Задание забирает большую часть пропускной способности диска и IOPS → На экране: Лаги каждый день в одно и то же время

Симптомы: Микрофризы, Задержка ввода · Основной ответственный Команда инфраструктуры · Серверная инфраструктура · Совместно Команда инфраструктуры · Инфраструктура БД

Ленивая загрузка на сервере Lazy loading on the server

Если сервер читает данные данжа или карты с диска в момент первого запроса, на этот тик останавливаются все.

Почему: Кто-то впервые входит в данж или локацию → Следствие: Сервер читает данные с диска в игровом потоке → На экране: У всех на этом сервере короткий фриз

Симптомы: Фриз · Основной ответственный Команда разработки · Разработка сервера · Совместно Команда инфраструктуры · Серверная инфраструктура

Запись core dump Core dump writing

При падении сервер пишет на диск несколько GB памяти, и перезапуск может задерживаться на несколько минут.

Почему: Сервер падает и записывает всю память в файл → Следствие: Пока пишутся несколько GB, перезапустить сервер нельзя → На экране: Сервер падает, у всех дисконнект, после чего ещё долго ошибка входа

Симптомы: Ошибка входа / бесконечная загрузка · Основной ответственный Команда инфраструктуры · Серверная инфраструктура · Совместно Команда разработки · Разработка сервера

Задержка позиционирования HDD HDD seek latency

У HDD головка должна перемещаться над пластинами (позиционирование, seek), поэтому каждое чтение или запись разбросанных данных занимает почти 10 ms.

Почему: HDD на старых серверах или в дешёвых хранилищах → Следствие: Около 10 ms на каждое случайное чтение или запись → На экране: Сохранение и загрузка в целом идут медленно

Симптомы: Задержка ввода · Основной ответственный Команда инфраструктуры · Серверная инфраструктура · Совместно Команда инфраструктуры · Инфраструктура БД, Команда разработки · Разработка сервера

База данных

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

Игровой сервер заранее открывает с БД несколько соединений (пул соединений) и использует их по очереди. Если один запрос (обращение к БД) выполняется долго, его соединение остаётся занятым, а когда заняты все соединения пула, остальные запросы ждут в очереди. Чаще всего запросы тормозят по одной из двух причин: либо нет индекса (это как предметный указатель в книге) и приходится читать всю таблицу (полное сканирование), либо несколько запросов одновременно пытаются изменить одну и ту же строку и ждут блокировки.

Чтобы быть надёжной и выдерживать много запросов, БД использует несколько механизмов: реплики, которые берут на себя часть чтения, резервную БД, на которую переключаются при сбое, и контрольные точки, когда изменения периодически скопом записываются на диск. Когда контрольные точки скапливаются, БД ненадолго замедляется. Если реплика отстаёт, появляются жалобы «только что купленного предмета не видно», а если переключиться на резервную БД при отставшей репликации, «зашёл, а всё вернулось к недавнему состоянию»: это симптомы съеденных действий и роллбэка. Если игровой сервер сохраняет персонажа раз в несколько минут, то при падении сервера игроки жалуются: «всё вернулось на 10 минут назад».

Аналогия

БД похожа на окошки в банке. Число окошек (пул соединений) фиксировано, и если один клиент затеял перебрать всю книгу учёта (полное сканирование), все следующие ждут. А если все хотят открыть один и тот же сейф (горячая строка), заходить можно только по одному.

Причины лагов на этом слое

Запрос без индекса Missing index / full table scan

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

Почему: С деплоем новой функции появляется поиск по условию, для которого нет индекса → Следствие: Сканируются все миллионы строк, один запрос занимает от сотен ms до нескольких секунд → На экране: Долго загружаются почта и история обменов, соединения заняты, и в очереди стоят даже другие запросы

Симптомы: Задержка ввода, Ошибка входа / бесконечная загрузка · Основной ответственный Команда разработки · Разработка сервера · Совместно Команда инфраструктуры · Инфраструктура БД

Конкуренция за блокировку горячей строки Hot row lock contention

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

Почему: Из-за события или популярного предмета все изменения приходятся на одну и ту же строку → Следствие: Запросы ждут, пока получат блокировку → На экране: Сбои обменов, «Повторите попытку позже», таймауты

Симптомы: Съеденные действия / роллбэк, Задержка ввода · Основной ответственный Команда разработки · Разработка сервера · Совместно Команда инфраструктуры · Инфраструктура БД

Дедлок в БД Database deadlock

Если две транзакции (операции БД, которые выполняются как единое целое) ждут строки, заблокированные друг другом, БД принудительно отменяет одну из них.

Почему: Обмен A блокирует строки в порядке «предмет → валюта», обмен B в порядке «валюта → предмет» → Следствие: БД обнаруживает дедлок и делает роллбэк одной из транзакций → На экране: Обмены и крафт иногда срываются, предметы возвращаются назад

Симптомы: Съеденные действия / роллбэк, Задержка ввода · Основной ответственный Команда разработки · Разработка сервера · Совместно Команда инфраструктуры · Инфраструктура БД

Исчерпание пула соединений Connection pool exhaustion

Число соединений с БД фиксировано, поэтому, когда медленные запросы занимают соединения, остальные запросы ждут.

Почему: Медленные запросы или наплыв запросов занимают все соединения → Следствие: Новые запросы ждут, пока освободится соединение → На экране: Бесконечная загрузка при входе, задержки сохранения, таймауты

Симптомы: Ошибка входа / бесконечная загрузка, Задержка ввода · Основной ответственный Команда разработки · Разработка сервера · Совместно Команда инфраструктуры · Инфраструктура БД

Отставание репликации Replication lag

Если запись идёт в основную БД, а чтение с реплики, то при отставании реплики только что записанные данные не видны.

Почему: Из-за потока записей в основную БД реплика отстаёт на несколько секунд → Следствие: Если читать только что сохранённые данные с реплики, их там ещё нет → На экране: Только что купленный предмет не виден, на торговой площадке старые цены, баги с двойной выдачей

Симптомы: Съеденные действия / роллбэк · Основной ответственный Команда инфраструктуры · Инфраструктура БД · Совместно Команда разработки · Разработка сервера

Контрольные точки и сброс журнала Checkpoint / log flush stalls

В моменты, когда БД периодически сбрасывает накопленные в памяти изменения на диск, запросы замедляются.

Почему: Изменения накапливаются и периодически записываются на диск → Следствие: В этот момент диск занят, и запросы задерживаются → На экране: Сохранения и загрузки периодически замедляются

Симптомы: Задержка ввода, Микрофризы · Основной ответственный Команда инфраструктуры · Инфраструктура БД

Холодный кэш (сразу после перезапуска) Cold buffer pool after restart

После перезапуска БД кэш в памяти пуст, и какое-то время все запросы читают данные с диска.

Почему: БД перезапускается на техработах → Следствие: Часто используемых данных нет в памяти, они читаются с диска → На экране: Сразу после техработ какое-то время медленно проходят вход и загрузка

Симптомы: Ошибка входа / бесконечная загрузка, Задержка ввода · Основной ответственный Команда инфраструктуры · Инфраструктура БД · Совместно Команда разработки · Разработка сервера

Наплыв входов и запросы N+1 Login storm, N+1 queries

Если для загрузки одного персонажа нужны десятки отдельных запросов, одновременный вход десятков тысяч игроков превращается в миллионы запросов.

Почему: При загрузке персонажа предметы, умения и квесты запрашиваются по отдельности → Следствие: Сразу после техработ одновременные входы резко увеличивают число запросов → На экране: Бесконечная загрузка при входе, застревают даже сохранения тех, кто уже играет

Симптомы: Ошибка входа / бесконечная загрузка, Задержка ввода · Основной ответственный Команда разработки · Разработка сервера · Совместно Команда инфраструктуры · Инфраструктура БД

Тяжёлые пакетные задания Batch jobs during service

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

Почему: Массовая операция запускается в рабочие часы сервиса → Следствие: Блокировки на широкий диапазон, заняты диск и CPU → На экране: В определённые часы срываются обмены и сохранения, медленно идёт загрузка

Симптомы: Задержка ввода, Съеденные действия / роллбэк · Основной ответственный Команда разработки · Разработка сервера · Совместно Команда инфраструктуры · Инфраструктура БД

Переключение БД на резерв Database failover

Пока после отказа основной БД идёт переключение на резервную, запись невозможна, а последние данные, которые не успели реплицироваться, могут пропасть.

Почему: Из-за отказа основной БД резервная повышается до основной → Следствие: Во время переключения запись невозможна от нескольких секунд до нескольких минут, при асинхронной репликации возможна потеря нереплицированных данных → На экране: Ненадолго не проходят все сохранения, роллбэк предметов и опыта

Симптомы: Съеденные действия / роллбэк, Фриз, Дисконнект, Ошибка входа / бесконечная загрузка · Основной ответственный Команда инфраструктуры · Инфраструктура БД · Совместно Команда разработки · Разработка сервера

Потеря прогресса из-за редких сохранений Periodic save window

Если ради снижения нагрузки сохранять прогресс раз в несколько минут, то при падении сервера в промежутке прогресс пропадает.

Почему: Состояние персонажа сохраняется раз в несколько минут → Следствие: В промежутке сервер падает или происходит сбой → На экране: После перезахода персонаж в состоянии нескольких минут назад (роллбэк)

Симптомы: Съеденные действия / роллбэк · Основной ответственный Команда разработки · Разработка сервера · Совместно Команда инфраструктуры · Инфраструктура БД

Cache stampede Cache stampede / thundering herd

Когда кэш популярных данных истекает одновременно, тысячи запросов разом идут в БД.

Почему: Популярные данные в Redis или другом кэше истекают одновременно → Следствие: Запросы, которые заново строят те же данные, разом обрушиваются на БД → На экране: БД перегружена, и одна функция за другой начинает тормозить или перестаёт отвечать

Симптомы: Задержка ввода, Фриз, Ошибка входа / бесконечная загрузка · Основной ответственный Команда разработки · Разработка сервера · Совместно Команда инфраструктуры · Инфраструктура БД

Долго открытая транзакция Long-running transaction / MVCC purge lag

Если одна транзакция долго остаётся открытой, она продолжает держать блокировки, а БД не может очистить (purge) старые версии данных, и всё постепенно замедляется.

Почему: Транзакция остаётся открытой, пока ждёт ответа другого сервера, или на основной БД в рабочее время идёт долгий агрегирующий запрос → Следствие: Захваченные блокировки не освобождаются, старые версии данных, которые нужно удалить, продолжают копиться → На экране: Таймауты в функциях, которые обращаются к этой строке, за несколько часов в целом замедляются сохранения и чтение данных

Симптомы: Задержка ввода, Съеденные действия / роллбэк · Основной ответственный Команда разработки · Разработка сервера · Совместно Команда инфраструктуры · Инфраструктура БД

Медленные команды Redis Redis blocking commands (single-threaded)

Redis обрабатывает команды по одной, поэтому одна медленная команда блокирует все запросы за ней.

Почему: В рабочее время выполняется полный перебор через KEYS, рейтинг или список из миллионов элементов читается или удаляется целиком → Следствие: Пока команда не закончится, все остальные запросы ждут (от десятков ms до нескольких секунд) → На экране: Одновременно подвисают функции, которые используют сессии, рейтинги и кэш, задерживается вход

Симптомы: Фриз, Задержка ввода, Ошибка входа / бесконечная загрузка · Основной ответственный Команда разработки · Разработка сервера · Совместно Команда инфраструктуры · Инфраструктура БД

Замедление запроса из-за смены плана выполнения Query plan regression (stats, parameter sniffing)

Код не менялся, но если БД меняет способ выполнения того же запроса (план выполнения), вчерашний запрос на 2 ms сегодня занимает сотни ms.

Почему: Автоматическое обновление статистики, перезапуск БД или изменение распределения данных заставляют БД построить план заново → Следствие: Выбирается план без индекса, тот же запрос становится медленнее в десятки или сотни раз и надолго занимает соединения → На экране: Деплоя не было, но загрузка в какой-то функции внезапно замедляется, и ждут даже другие запросы

Симптомы: Задержка ввода, Ошибка входа / бесконечная загрузка · Основной ответственный Команда инфраструктуры · Инфраструктура БД · Совместно Команда разработки · Разработка сервера

Блокировка при изменении схемы (DDL) на работающем сервисе Schema change lock (DDL / metadata lock)

Если во время работы сервиса добавить в таблицу столбец или индекс, из-за одной кратковременной блокировки могут встать все запросы к этой таблице.

Почему: Хотфиксом в рабочую таблицу добавляется столбец или индекс → Следствие: Изменение схемы ждёт ранее открытую длинную транзакцию, а все следующие запросы ждут изменение схемы → На экране: Функции, которые используют эту таблицу (инвентарь, почта и т. п.), полностью перестают работать, запросы завершаются по таймауту

Симптомы: Задержка ввода, Съеденные действия / роллбэк, Ошибка входа / бесконечная загрузка · Основной ответственный Команда инфраструктуры · Инфраструктура БД · Совместно Команда разработки · Разработка сервера

Архитектура и эксплуатация серверов

Современные MMO обычно устроены как набор серверов, которые вызывают друг друга: серверы авторизации, шлюза, открытых локаций, данжей, чата, групп, аукциона, кэша и БД. Сбой в одном месте расходится на связанные с ним, а лаги создают и операционные работы вроде деплоя, масштабирования и техработ.

Разделение на серверы не даёт сбою в одном месте распространиться на всё, но взамен появляются цепочки вызовов (сервер по очереди вызывает другие серверы). Игровой сервер вызывает сервер аукциона, а тот вызывает кэш и БД. Если сервер в конце цепочки тормозит, серверы перед ним, ожидая ответа, продолжают занимать потоки и соединения, и в итоге встают даже функции, которые вроде бы ни при чём. Это называют каскадным отказом, и его распространение сдерживают таймаутами и circuit breaker (предохранитель для вызовов: временно блокирует вызовы, которые раз за разом заканчиваются ошибкой).

Операционные работы тоже вызывают лаги. Перезапуск при деплое обновления, несколько минут, которые нужны, чтобы автоматически добавить серверы при наплыве игроков, перенос персонажа на другой сервер при переходе между зонами, невидимая нагрузка от ботов и макросов: всё это игрок видит как «лаги».

Аналогия

Серверная архитектура похожа на компанию, где отделы согласуют документы друг у друга. Если один отдел в конце цепочки согласования (БД) тормозит, отделы перед ним стоят в очереди с бумагами, и в итоге встаёт работа всей компании. Таймаут означает правило «нет ответа больше 10 минут: пока отклонить», а предохранитель означает правило «если отказы идут подряд, какое-то время бумаги в этот отдел не отправлять и сразу возвращать».

Причины лагов на этом слое

Трафик через шлюз или прокси Gateway / proxy hop

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

Почему: Схема клиент ↔ шлюз ↔ игровой сервер → Следствие: Промежуточный сервер добавляет обработку и ожидание, при его перегрузке страдают все → На экране: Пинг растёт у всех, при отказе шлюза дисконнект у всех игроков, которые через него подключены

Симптомы: Задержка ввода, Дисконнект · Основной ответственный Команда разработки · Разработка сервера · Совместно Команда инфраструктуры · Серверная инфраструктура, Команда разработки · Разработка клиента

Переход между зонами (передача на другой сервер) Zone / server handoff

При входе в другую локацию или данж данные персонажа передаются на другой сервер, и на этом этапе возникают задержки и сбои.

Почему: Вход в данж или переход на другой континент меняет обслуживающий сервер → Следствие: Сохранение → передача → загрузка; если целевой сервер перегружен или нет свободного инстанса данжа, приходится ждать → На экране: Долгая загрузка, неудачный вход, дисконнект во время перехода

Симптомы: Ошибка входа / бесконечная загрузка, Фриз, Дисконнект, Откидывание назад · Основной ответственный Команда разработки · Разработка сервера · Совместно Команда инфраструктуры · Серверная инфраструктура

Каскадный отказ Cascading failure

Когда один сервис тормозит, вызывающие его серверы зависают в ожидании ответа, и останавливаются даже функции, которые с ним не связаны.

Почему: Тормозит один сервис, например БД или авторизация → Следствие: Потоки и соединения вызывающих серверов заняты ожиданием ответа, а повторные попытки неудачных запросов добавляют нагрузку → На экране: Тормозят или останавливаются даже функции, которые кажутся никак не связанными

Симптомы: Фриз, Задержка ввода, Ошибка входа / бесконечная загрузка · Основной ответственный Команда разработки · Разработка сервера · Совместно Команда инфраструктуры · Сетевая инфраструктура

Сбой вспомогательного сервера Auxiliary service outage

Если отказывает сервер, который работает отдельно от игрового (чат, группы, аукцион), перестаёт работать только эта функция.

Почему: Выделенный сервер функции тормозит или падает → Следствие: Нет ответа только на запросы этой функции → На экране: Не работает чат, приглашение в группу остаётся без ответа, бесконечная загрузка торговой площадки (бои идут нормально)

Симптомы: Съеденные действия / роллбэк, Ошибка входа / бесконечная загрузка · Основной ответственный Команда разработки · Разработка сервера · Совместно Команда инфраструктуры · Серверная инфраструктура

Деплой и перезапуск Deploy / rolling restart

Если при перезапуске сервера ради обновления не перенести соединения, у всех игроков на этом сервере будет дисконнект, а сохранения перед остановкой и переподключения придут разом.

Почему: Серверы по очереди перезапускаются при деплое хотфикса → Следствие: Сервер останавливается без переноса соединений на другой, и сохранения всех игроков с этого сервера разом идут в БД → На экране: Дисконнект без предупреждения, лавина переподключений

Симптомы: Дисконнект, Ошибка входа / бесконечная загрузка, Задержка ввода · Основной ответственный Команда разработки · Разработка сервера · Совместно Команда инфраструктуры · Серверная инфраструктура

Задержка автомасштабирования Autoscaling lag

При наплыве игроков серверы добавляются автоматически, но подготовка занимает несколько минут, и всё это время существующие серверы перегружены.

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

Симптомы: Слоумо, Ошибка входа / бесконечная загрузка · Основной ответственный Команда инфраструктуры · Серверная инфраструктура · Совместно Команда разработки · Разработка сервера

Перегрузка логирования и мониторинга Logging / monitoring overhead

При сбое логи растут лавиной, и серверы, которые отправляют логи синхронно, из-за этого тормозят ещё сильнее.

Почему: Из-за ошибок резко растёт объём логов и метрик → Следствие: Сборщик логов не успевает, серверы с синхронной отправкой ждут → На экране: Во время сбоя микрофризы и фризы усиливаются из-за логов

Симптомы: Микрофризы, Фриз · Основной ответственный Команда разработки · Разработка сервера · Совместно Команда инфраструктуры · Серверная инфраструктура

Расхождение часов между серверами Clock skew between servers

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

Почему: На сервере с остановившейся синхронизацией времени часы расходятся с другими серверами на сотни ms или несколько секунд → Следствие: Если передавать между серверами абсолютное время (например, момент окончания баффа), проверки расходятся → На экране: После перехода пропадает бафф или кулдаун начинается заново

Симптомы: Съеденные действия / роллбэк · Основной ответственный Команда инфраструктуры · Серверная инфраструктура · Совместно Команда разработки · Разработка сервера

Избыток макросов и ботов Bots and macros

Боты шлют запросы гораздо чаще людей и съедают производительность сервера.

Почему: Массовое подключение ботов, которые без перерыва фармят, ходят и торгуют → Следствие: Растут нагрузка на сервер и на БД → На экране: Тормозит отдельная локация для фарма или весь сервер (слоумо, задержка ввода)

Симптомы: Слоумо, Задержка ввода · Основной ответственный Команда разработки · Разработка сервера · Совместно Команда инфраструктуры · Сетевая инфраструктура

Зависимость от внешних сервисов External dependencies (auth, billing, platform)

Если тормозит или останавливается внешний сервис (вход через платформу, оплата, подтверждение личности), всё застревает на этом этапе.

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

Симптомы: Ошибка входа / бесконечная загрузка, Съеденные действия / роллбэк · Основной ответственный Внешние стороны · Внешние стороны · Совместно Команда разработки · Разработка сервера

Ошибки матчмейкинга и выбора региона Wrong region assignment (matchmaking / GeoDNS)

Если игрока отправили на сервер в дальнем регионе вместо ближнего, у него одного пинг всегда высокий, даже если с подключением всё в порядке.

Почему: Ошибки в данных GeoIP, VPN, выбор сервера для всей группы по среднему пингу участников, правило расширения поиска на дальние регионы при нехватке игроков, выбор по местоположению DNS-резолвера → Следствие: Подключение к серверу в регионе за океаном, хотя есть ближний регион → На экране: В игре с серверами в нескольких регионах только у одного игрока (или одной группы) постоянно высокий пинг, задержка ввода, откидывание назад и съеденные умения

Симптомы: Задержка ввода, Откидывание назад, Съеденные действия / роллбэк · Основной ответственный Команда разработки · Разработка сервера · Совместно Команда разработки · Разработка клиента, Команда инфраструктуры · Сетевая инфраструктура, Внешние стороны · Внешние стороны

Истёкший или неверно настроенный TLS-сертификат TLS certificate expiry / misconfiguration

Если у сервера авторизации, API или патчей истекает сертификат или пропадает промежуточный сертификат, с этого момента у новых подключений клиентов не устанавливается TLS-соединение.

Почему: Срок действия сертификата истёк, сервер отдаёт цепочку без промежуточного сертификата, или на устройстве игрока неверные дата и время → Следствие: Клиент не проходит проверку сертификата и разрывает TLS-соединение → На экране: Ошибка входа или бесконечная загрузка на этапе входа или патча, не работают только функции через HTTPS, например магазин. У тех, кто уже был в игре, обычно всё в порядке

Симптомы: Ошибка входа / бесконечная загрузка, Съеденные действия / роллбэк · Основной ответственный Команда инфраструктуры · Сетевая инфраструктура · Совместно Команда инфраструктуры · Серверная инфраструктура, Команда разработки · Разработка клиента

Лимит очереди на вход и короткое окно переподключения Login queue cap / no reconnect grace

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

Почему: Желающих войти больше, чем сервер авторизации может принять за раз, поэтому есть очередь, а когда она слишком длинная, сервер ради самозащиты перестаёт ставить в неё новых игроков → Следствие: Чем длиннее очередь, тем дольше ожидание, и за это время достаточно короткого обрыва Wi-Fi или мобильной сети, чтобы потерять место → На экране: Ошибка входа / бесконечная загрузка, игра закрывается с ошибкой во время ожидания, ждать приходится снова с конца очереди

Симптомы: Ошибка входа / бесконечная загрузка, Дисконнект · Основной ответственный Команда разработки · Разработка сервера · Совместно Команда разработки · Разработка клиента, Команда инфраструктуры · Серверная инфраструктура

T1Инструменты

Помощник диагностики

Получив жалобу на лаги, выберите всего три признака: «у кого, когда и как это выглядит». Помощник покажет причины из этого справочника, которые подходят лучше всего, по убыванию баллов. Это ещё не окончательный диагноз, но его достаточно, чтобы решить, к какой команде идти первой.

T2Инструменты

Диагностика по метрикам

Когда приходит жалоба или алерт, круг поиска сужают в порядке охват → момент → слой. Сильнее всего на выбор ответственных влияет то, где сосредоточена аномалия. То, с чем она совпала по времени, сужает круг причин, а метрики слоя, в котором видны отклонения, подтверждают вывод. Разделы «На графике» и «Способ проверки» в каждой карточке причины помогают выбрать кандидатов по форме графика и сразу понять, где смотреть.

Порядок диагностики

1 Охват

Где сосредоточена аномалия?

  • Определённая страна или провайдер (ASN) → Команда инфраструктурыСеть Внешние стороныПровайдер
  • Определённый сервер, канал или зона → при нормальных метриках хоста Команда разработкиСервер, при отклонениях Команда инфраструктурыСерверы и ОС
  • Определённая ОС, устройство или сборка → Команда разработкиКлиент
  • Один игрок или один дом → Внешние стороныОкружение игрока (если у нескольких игроков та же картина, Команда разработкиКлиент)
  • Все одновременно → общие ресурсы (БД, балансировщик нагрузки, шлюз) или свежий деплой
2 Момент

С чем совпадает по времени?

3 Слой

Метрики какого слоя отклоняются от нормы?

  1. Сеть: RTT, потери, доля повторных передач, ошибки и отбрасывания на интерфейсах
  2. Хост: CPU по ядрам, CPU steal, softirq, отбрасывания на NIC, нехватка памяти
  3. Игровой сервер: время тика, очередь приёма сокета (Recv-Q), CPU по потокам, GC-лог
  4. БД: задержка запросов, ожидание блокировок, отставание репликации
  5. Клиент: время кадра, нетграф, краш-репорты

Таблица признаков

Что проверитьЧто видноКого звать первым
Очередь приёма сокета на сервере (Recv-Q)Данные копятся, потому что серверный процесс не успевает их читатьКоманда разработкиСервер (остановки тика, GC, блокировки)
Повторные передачи и RTT по соединениямТолько часть соединений, сосредоточены в определённых ASNКоманда инфраструктурыСеть Внешние стороныПровайдер, подключение игрока
Все соединения одного хостаКоманда инфраструктурыСерверы и ОС (NIC, ядро)
Сразу после патча по всему серверу выросли повторные передачи и трафикИзменились размер или частота пакетовКоманда разработкиСервер Команда инфраструктурыСеть (MTU, лимиты)
CPU steal, троттлинг, softirq, отбрасывания на NICРостКоманда инфраструктурыСерверы и ОС
Один поток на 100%, задержка в очереди выполнения, паузы GCРостКоманда разработкиСервер
Задержка БД растёт, число запросов прежнееIOPS, блокировки, другие заданияКоманда инфраструктурыСерверы БД
После патча изменились число или вид запросов к БДN+1, новые запросыКоманда разработкиСервер
Синтетический мониторинг из зарубежных точек (RTT, потери)ПлохоКоманда инфраструктурыСеть Внешние стороныПровайдер
Синтетический мониторинг в норме, плохо только у игроковОкружение игрока или клиентВнешние стороныОкружение игрока Команда разработкиКлиент
Распределение причин дисконнектовТаймауты хартбита↑ / RST↑ / отключения сервером↑NAT, маршрут / оборудование / сервер
Точный период (ровно в начале часа, каждые N минут)Плановые задания, бэкапы, GC, событияТот, кто задал это расписание

Поиск по форме графика

Уже по форме графика мониторинга круг кандидатов сильно сужается. Ниже для каждой из 13 форм собраны причины, которые её дают. Маленькие графики в карточках причин показывают те же формы. Сплошная линия обозначает основную метрику, пунктир показывает метрику, которую смотрят вместе с ней (онлайн, ожидание, ошибки и т. п.), бледный пунктир отмечает обычный уровень.

Всплески с постоянным периодом

Обычно значение низкое, но через равные промежутки подскакивает: каждые несколько секунд, минут или ровно в начале часа.

Сборка мусора на клиенте, Проверки модуля защиты игры (античита), Фоновое сканирование Wi-Fi, Плановые задания, Одновременное срабатывание таймеров, Полная пауза GC на сервере, Паузы GC в скриптовом движке, Лавина fsync, Бэкап, сжатие и сканирование, Контрольные точки и сброс журнала, Тяжёлые пакетные задания, Cache stampede

Случайные всплески

Значение подскакивает нерегулярно, без всякого интервала, и быстро возвращается.

Всплески времени кадра, Чрезмерная экстраполяция (dead reckoning), Расхождение клиентского предсказания с сервером, Лавина догоняющих шагов при фиксированном таймстепе, Фоновые процессы занимают CPU, Нехватка памяти и своп на клиенте, Энергосбережение NIC и проблемы драйверов, Помехи и слабый сигнал Wi-Fi, Частые переключения 5G ↔ LTE (на границе покрытия 5G), Плохое качество линии связи, Слишком маленький кольцевой буфер, Накладные расходы виртуализации и шумные соседи, Нехватка буферов сокетов в ядре, CPU steal (виртуальная машина), Остановки из-за освобождения и уплотнения памяти, Скачок системных часов (шаговая коррекция NTP), Блокирующая отправка из-за медленного клиента, Настройка повторных передач в надёжном UDP, Потеря последних данных при принудительном закрытии через RST, Синхронные вызовы в игровом потоке, Синхронная запись логов, Ленивая загрузка на сервере, Дедлок в БД, Медленные команды Redis, Перегрузка логирования и мониторинга, Ожидание самого медленного игрока в lockstep, Ошибки предсказания в роллбэк-неткоде, Воспроизведение сразу по приходу без меток времени, Слишком строгая серверная проверка, Расхождение расчёта пути при синхронизации команд, Сбой порядка регистрации в зоне видимости, Потеря опорного снапшота, Потеря уведомления об исчезновении (фантомные объекты), Путаница из-за повторного использования ID объектов, Ложные повторные передачи из-за скачков задержки

Ступенька вверх с определённого момента

С конкретного момента (патч, изменение настроек, смена маршрута) значение поднимается на ступень и остаётся там.

Аварии на подводных кабелях и международных линиях, Смена маршрута BGP и сходимость, Задержка и ложные срабатывания защиты от DDoS, Изменение производительности после обновления ОС, ядра, драйверов или прошивки, Патч изменил характер трафика, Запрос без индекса, Замедление запроса из-за смены плана выполнения, Блокировка при изменении схемы (DDL) на работающем сервисе, Зависимость от внешних сервисов, Смена маршрута и неисправный путь ECMP

Плавный рост

Значение понемногу растёт часами и днями. Чем дольше работа без перезапуска, тем оно выше.

Ошибка синхронизации часов, Потеря точности времени во float, Утечка памяти на клиенте, Энергосбережение и тепловой троттлинг, Утечка памяти, Своп, Фрагментация памяти, Диск заполнен, Долго открытая транзакция, Расхождение часов между серверами

Высоко только в определённые часы

В одни и те же часы суток, например в вечерний пик, график поднимается горбом.

Перегруженный радиоканал Wi-Fi, Перегрузка пиринга в часы пик, Ложные срабатывания проверок у абонентов одного провайдера, Переполнение очереди в узком месте (потери от перегрузки)

Растёт вслед за онлайном и нагрузкой

Когда растёт онлайн или число игроков в одном месте, график поднимается ещё круче.

Нагрузка на рендеринг при большом скоплении игроков, Узкое место: обработка пакетов в главном потоке, Переполнение буфера приёма, Другие приложения на устройстве забирают пропускную способность, Bufferbloat (очередь в роутере), Микробёрсты на коммутаторе, Избыток потоков и переключение контекста, Троттлинг CPU в контейнере (квота CFS), IP-фрагментация UDP-пакетов, Архитектура с блокирующим вводом-выводом, Превышение бюджета тика, Взрывной рост расчёта видимости (AOI, N²), Взрывной рост рассылки (broadcast), Перегрузка однопоточной локации (хотспот), Конкуренция за блокировки, Лавина поиска пути, Затраты на сериализацию и сжатие, Бой, сосредоточенный на одной цели (мировой босс), Лавина аллокаций, Конкуренция за блокировку горячей строки, Отставание репликации, Трафик через шлюз или прокси, Переход между зонами (передача на другой сервер), Бюджет отправки и приоритеты для каждого соединения, Переполнение неглубоких буферов всплесками отправки, Несовпадение дуплекса

Упор в лимит (плато)

Производительность или число соединений доходит до некоторого значения и дальше не растёт, а с этого момента растут ожидание и ошибки.

Нехватка видеопамяти (VRAM), Слабый или перегретый роутер, Ограничение скорости и управление трафиком у провайдера, Перегрузка общих линий из-за DDoS, Переполнение таблицы сессий файрвола, Лимиты соединений и портов облачного NAT-шлюза, Перегрузка линии связи ЦОД, Все прерывания NIC на одном ядре, Превышен лимит PPS в облаке, Исчерпание пропускной способности NIC, Лимит файловых дескрипторов, Переполнение таблицы conntrack на сервере, Исчерпание эфемерных портов в межсерверных соединениях, Затор в очереди сообщений, Исчерпание пула потоков, Трешинг GC (мало свободного места в куче), Исчерпание burst-кредитов облачного диска, Лимит IOPS и насыщение очереди, Исчерпание пула соединений, Каскадный отказ, Лимит очереди на вход и короткое окно переподключения, Сбой стриминга из-за нехватки памяти или VRAM, Отбрасывание избытка полисером, Отбрасывание пакетов на принимающем сервере, Отбрасывание пакетов файрволом или conntrack, Перегрузка промежуточного оборудования (файрвол, IPS, защита от DDoS)

Высоко с самого начала

Значение без всплесков всё время держится высоким. Так бывает, когда причина в самой схеме: расстояние, маршрут, архитектура.

Буфер интерполяции отсутствует или слишком короткий, V-Sync и очередь рендеринга, Разрешение таймера, Задержка дисплея, устройств ввода и генерации кадров, Задержка распространения (физическое расстояние), Неоптимальная маршрутизация, Избыточное объединение прерываний, Ожидание объединения пакетов в GRO/LRO, Всплески задержки из-за управления питанием сервера (C-state, управление частотой), Алгоритм Нейгла + отложенный ACK, Промах кэша, Задержка позиционирования HDD, Отклик только после ответа сервера (модель запрос-ответ), Протокол с множеством последовательных обменов (chatty), Нет буферизации ввода умений, Клиентский авторитет, Двойное ожидание тика, Низкая частота отправки снапшотов, Ложные быстрые повторные передачи из-за нарушения порядка, Неподходящая настройка RTO, Удаление опций TCP промежуточным оборудованием

Высоко только у некоторых

У большинства в норме, высоко только у отдельных игроков, регионов, провайдеров или устройств.

Стриминг ассетов отстаёт из-за медленного накопителя, Краш клиента, Проверка пакетов защитным ПО, Вмешательство оверлеев, Задержка перехода состояний RRC (энергосбережение радиомодуля), Слабый сигнал мобильной сети и мёртвые зоны, Ограничения публичного Wi-Fi и корпоративной сети, Спутниковый интернет (низкоорбитальный и геостационарный), Неисправность одного из путей ECMP, Ограничение UDP и DPI на уровне страны или провайдера, Сбои и задержки DNS, Трафик через VPN или игровой ускоритель, Перекос балансировки и ошибки health check, Неисправный кабель и ошибки порта, Несовпадение MTU (пропадают только большие пакеты), Политика для медленных клиентов (slow consumer), Keepalive по умолчанию: 2 часа, Медленный старт после простоя, Перекос распределения в SO_REUSEPORT, Удалённая память NUMA, Избыток макросов и ботов, Ошибки матчмейкинга и выбора региона, Короткое окно реакции, которое съедает пинг, Проверка попадания без компенсации задержки, Чрезмерная компенсация задержки, Архитектура с хостом-игроком, Отказ сервера после опережающего фидбека, Игрок с плохой связью движется на чужих экранах рывками, Перемотка на сервере, который обрабатывает ввод сразу по приходу, Размер буфера ввода на игрока, Один тормозящий участник группы и механики босса, Управление монстром у тормозящего клиента, Раздутые данные отдельного персонажа, Разные каналы, инстансы и фазы, Отбрасывание уведомлений о появлении во время загрузки, Конфликт фиксированного UDP-порта, Ошибка разделения сессий по IP или устройству, Ограничение на несколько клиентов, Конфликт одновременного доступа к файлам кэша и ассетов, Разные настройки отображения, Несовпадение версии клиента или данных, Отложенный показ объектов из-за ошибки оценки серверного времени, Потери на беспроводном участке, Физические ошибки (неисправные кабели, оптические модули и разъёмы), Чёрная дыра MTU (большие пакеты теряются раз за разом), Задержка и потеря ACK (забитая отдача)

Провал, затем пачка

Какое-то время объём полученных данных равен 0, а потом всё прилетает разом.

Ограничение обработки в свёрнутом или неактивном окне, Хендовер между базовыми станциями (в движении), Обслуживание облачного хоста и живая миграция, Проблемы драйвера и прошивки NIC, HOL-блокировка в TCP, TCP RTO и экспоненциальный backoff, Ограничение обработки в фоновом окне, Медленное восстановление потерь в thin stream, Нулевое окно (остановка, похожая на повторную передачу)

Массовый обрыв соединений

Число подключений резко падает, или число обрывов в один момент взлетает.

Сворачивание мобильного приложения в фон, Переключение Wi-Fi ↔ LTE/5G, Истечение записи в таблице NAT, Общий IP провайдера (CGNAT), Таймаут простоя балансировщика, Истечение отслеживания соединений в облачной группе безопасности, Переключение сетевого оборудования на резерв (failover), OOM killer, Ошибка WSAECONNRESET на UDP-сокете в Windows, Дедлок, Падение сервера, Бесконечный цикл и неконтролируемая логика, Запись core dump, Переключение БД на резерв, Потеря прогресса из-за редких сохранений, Сбой вспомогательного сервера, Деплой и перезапуск, Истёкший или неверно настроенный TLS-сертификат, Истечение записи NAT или балансировщика посреди соединения

Всплеск сразу после входа или техработ

Сразу после открытия сервера или старта события значение сильно подскакивает, потом постепенно спадает.

Синхронная загрузка и компиляция шейдеров в главном потоке, Переполнение очереди подключений (backlog), Лавина спавна при входе в людное место, Холодный кэш (сразу после перезапуска), Наплыв входов и запросы N+1, Задержка автомасштабирования, Потеря данных о появлении из-за наплыва сразу после входа, Повторная передача запроса на подключение (SYN)

Сколько можно проверить без игрового кода

Для каждой причины учтён самый простой способ проверки. Инструменты инфраструктуры означают проверку средствами ОС, сети, облака и БД, а также опциями запуска среды выполнения (GC-лог и т. п.), так что игровой код менять не нужно. Логи и метрики игры означают то, что видно, только если игра сама это записывает, например время тика и причины дисконнектов. Чем больше у слоя ячеек «Логи и метрики игры», тем весомее повод попросить команду разработки добавить метрики.

Как читать цифры

Среднее прячет всплески. На сервере с 20 тиками в секунду достаточно замедлиться 1% тиков, и все игроки примерно раз в 5 секунд ощущают запинку, а среднее время тика почти не меняется. Поэтому вместе со средним смотрят перцентили. p50 (медиана) показывает значение, меньше которого половина замеров, а p99 соответствует примерно самому медленному замеру из 100. То, что игроки запоминают как «лаг», обычно лежит в районе p99.

Интервал агрегации тоже прячет всплески. На графике со средним за 1 минуту остановка длиной в 1 с размывается до 1/60. Когда ищут остановки, на том же графике смотрят ещё максимум или p99, а также более короткий интервал.

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

Способ измеренияЧто измеряетНа что обратить внимание
ping (ICMP)Время туда и обратно до устройстваМаршрутизаторы и серверы могут обрабатывать ответы ICMP с задержкой или ограничивать их число, поэтому результат может отличаться от того, что получают игровые пакеты. Если ICMP заблокирован, ответа нет вовсе
mtr·tracerouteЗадержка и потери на каждом участкеЕсли высокие потери только на одном промежуточном узле, а дальше по маршруту всё в норме, скорее всего, этот узел просто ограничивает ответы ICMP. Настоящие потери только те, что тянутся до конца маршрута
TCP RTT (rtt в выводе ss -ti)Время туда и обратно, которое ядро измеряет для каждого соединенияСамый надёжный показатель, потому что это значение реального игрового соединения. Его можно смотреть по каждому игроку на стороне сервера
Пинг в игреВремя туда и обратно, которое игра измеряет своими сообщениямиЕсли мерить внутри игрового цикла, к нему примешивается ожидание кадра и тика. Растёт, когда занят сервер или ПК, даже если подключение в порядке

Что можно сделать сразу и что добавить в игровой код

Без игрового кода
  • Добавить разрезы: к клиентским IP в логах подключений и балансировщика нагрузки добавляют страну и провайдера (ASN), чтобы стали видны случаи «только за рубежом» и «только у одного провайдера».
  • Качество соединений: на сервере через ss -ti или инструменты eBPF собирают RTT и повторные передачи по каждому соединению и смотрят их в разрезе ASN.
  • Заглянуть внутрь сервера снаружи: очереди сокетов, CPU по потокам (pidstat -t), задержка в очереди выполнения, GC-лог, который включается одной опцией запуска.
  • Измерение маршрута: синтетический мониторинг со стороны целевой страны и провайдера (RIPE Atlas, серверы для измерений в облачных регионах) и mtr.
  • Журнал изменений: деплои, патчи, изменения настроек и сетевые работы отмечают вертикальными линиями на всех графиках. С этого начинается проверка версии «началось после патча».
Минимум в игровом коде
  • Сводный отчёт клиента: каждые 30–60 с RTT p50 и p95, джиттер, потери, FPS, число всплесков времени кадра, сборка, сервер и канал.
  • Метрики тика на сервере: время тика p50 и p99, число превышений бюджета тика, число игроков по зонам, очередь отправки по соединениям.
  • Коды причин дисконнекта: таймаут хартбита, RST, отключение сервером, ошибка аутентификации, техработы. Коды одинаковые на обеих сторонах.
  • ID сессии и время: во всех логах ID сессии, персонажа и сервера и синхронизированное время в UTC.
  • Кнопка «Сообщить о лаге»: отправляет RTT, FPS и пропуски тиков за последние 60 с вместе с ID сессии.
T3Инструменты

Инциденты и инструкции

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

Инструкции по ситуациям

Лаги после патча

Когда после определённого патча или деплоя стало больше сообщений о лагах. Подходит, если копятся жалобы вида «с этого обновления что-то не так» или если график с какого-то момента поднимается ступенькой и так и остаётся.

  1. Точно определить время начала и собрать все изменения до и после него: Находят момент, когда пошёл первый поток сообщений о лагах, и момент, когда график поднялся ступенькой, и выписывают все изменения, выкаченные до и после них. Смотрят всё вместе: патч клиента, деплой сервера, изменения настроек, изменения схемы БД (DDL) и перезапуски, работы с сетью и файрволом, замену инфраструктуры (тип инстанса, ядро, драйверы). Если при каждом деплое ставить вертикальную линию на всех графиках с помощью аннотаций (annotation) в инструменте мониторинга, этот шаг проходит быстро. Если игровой патч и инфраструктурные работы вышли в одни и те же техработы, кандидатами остаются оба. Кого звать первым: обе команды, разработки и инфраструктуры, которые вносили изменения.
  2. Разделить по охвату: сборка, устройство, сервер, регион: Смотрят, в каком срезе сосредоточена проблема. Если плохо только у игроков на новой сборке, первым делом подозревают клиент; если только на определённой ОС, видеокарте или устройстве, то производительность клиента или драйверы; если только на определённом сервере, канале или в зоне, то сервер; если только в определённой стране или у определённого провайдера, то сетевой маршрут; если у всех одновременно, то общие ресурсы (БД, балансировщик нагрузки, шлюз) или только что выкаченный деплой сервера. Если в клиентской телеметрии есть номер сборки, ставят рядом пинг, FPS, всплески времени кадра и число дисконнектов на старой и новой сборке. Если пинг прежний, а упал только FPS, дело скорее в производительности клиента, чем в сети. Кого звать первым: если проблема сосредоточена в сборке или устройстве, команда разработки (клиент); если на сервере или канале, то при нормальных метриках хоста команда разработки (сервер), при отклонениях команда инфраструктуры (серверы и ОС); если в стране или у провайдера, команда инфраструктуры (сеть).
  3. Сравнить новую и старую версии в одно и то же время: Если сравнивать только «до» и «после» деплоя, к результату примешиваются колебания по дням недели, времени суток и игровым событиям, и вывод получается размытым. По возможности новую версию сначала выкатывают на часть серверов (канарейка) и в то же самое время сравнивают с серверами на старой версии (контрольная группа): p50 и p99 времени тика, число превышений бюджета тика, CPU, память, долю ошибок. Если версия уже выкачена везде, сравнивают с тем же днём недели и тем же временем суток на прошлой неделе. Среднее по всем серверам скрывает проблемы отдельных серверов и зон, поэтому смотрят в разбивке по серверам и зонам. Кого звать первым: команда разработки (сервер).
  4. Сравнить профиль трафика до и после: Даже не зная серверного кода, по тому, что видно со стороны сети, проверяют, изменил ли патч характер трафика. Сравнивают до и после: пакеты в секунду (pps) и байты на игрока, средний и максимальный размер пакета, число соединений, размер всплеска отправки, который уходит разом на каждом тике. Если UDP-пакеты начали превышать MTU пути (обычно 1 500 байт), возникает IP-фрагментация. Потеря одного фрагмента означает потерю всего пакета, а некоторые NAT и файрволы вообще отбрасывают фрагменты. У игроков, чей путь проходит через участок с маленьким MTU (туннель, VPN), пропадают только большие пакеты. Если pps вырос, проверяют, не упёрлись ли в лимит PPS облачного инстанса или в предел производительности файрвола или оборудования защиты от DDoS. Кого звать первым: если профиль трафика изменился, команда разработки (сервер) с приложенными доказательствами; если профиль прежний, а выросли только потери и повторные передачи, команда инфраструктуры (сеть).
  5. Сравнить типы и число запросов к БД до и после: Если выросла задержка БД, сначала смотрят, выросло ли вместе с ней число запросов (QPS). pg_stat_statements в PostgreSQL и сводка по digest в MySQL Performance Schema объединяют запросы, которые отличаются только значениями, в один тип и собирают по нему число выполнений и суммарное время. Поэтому если сравнить топ запросов до и после патча, видны новые запросы, запросы, число которых выросло в несколько раз (N+1), и запросы, которые читают всю таблицу без индекса (в MySQL столбец SUM_NO_INDEX_USED). Кого звать первым: если изменились QPS или вид запросов, команда разработки (сервер); если запросы те же, а выросла только задержка, команда инфраструктуры (БД: план выполнения, IOPS, блокировки).
  6. Определить слой по метрикам хоста и серверного процесса: Без доступа к коду, по тому, что видно в ОС, отделяют проблемы внутри серверного процесса от проблем хоста. Если растёт очередь приёма серверного сокета (Recv-Q), серверный процесс не успевает читать данные (остановка тика, GC, блокировки). Если один поток загружен на 100%, это узкое место в однопоточном коде. Если в GC-логе выросло время пауз, изменился характер работы с памятью. Проверяют и то, не выкатили ли сборку с повышенным уровнем логирования, из-за чего выросла запись логов. Если же выросли CPU steal, троттлинг или дропы на NIC, смотрят, что в то же время поменялось в инфраструктуре (тип инстанса, ядро, лимиты контейнеров). Кого звать первым: если признаки внутри процесса, команда разработки (сервер); если признаки на хосте, команда инфраструктуры (серверы и ОС).
  7. Подтвердить причину, вернув изменение, и записать результат: Самое вероятное изменение возвращают только на части серверов или у части игроков (роллбэк, выключение фича-флага) или ставят прежнее значение настройки и смотрят, уходит ли вместе с этим симптом. Если лучше стало только там, где изменение вернули, причина подтверждена. Сам возврат тоже может ненадолго замедлить работу из-за перезапуска и холодного кэша, поэтому, если не горит, его делают в спокойные часы. Результат записывают в отчёт об инциденте вместе с ID причины, а лимиты на размер пакетов, число запросов и время тика переносят в чек-лист перед деплоем следующего патча. Кого звать первым: команда, которая внесла изменение.

Запуск в новой стране или регионе

Когда сервис открывают в новой стране или добавляют новый регион или ЦОД. Подходит и для проверки перед запуском, и для разбора жалоб вида «в Корее всё нормально, лагает только у игроков из новой страны».

  1. До запуска измерить качество маршрутов у каждого местного провайдера: Для каждого крупного провайдера (ASN) целевой страны измеряют распределение времени пути туда и обратно (RTT), джиттер и потери до площадок, которые рассматриваются для игровых серверов. Одно среднее скрывает разницу между провайдерами, поэтому смотрят медиану и 95-й перцентиль по каждому провайдеру отдельно для вечернего пика и для ночных часов. В открытой измерительной сети RIPE Atlas можно выбрать страну и ASN и запускать ping и traceroute с зондов по всему миру, а можно поднять временную ВМ в регионе-кандидате и мерить с неё. Промежуточное оборудование иногда ограничивает ответы ICMP, поэтому по возможности меряют и тем же протоколом и портом, что и игра. Если трафик только одного провайдера идёт через подозрительно далёкий город, это проблема пиринга или маршрута. Провайдеры выбирают маршрут подешевле, даже если задержка на нём больше, поэтому трафик даже до близкой точки может идти далёким обходом. Кого звать первым: команда инфраструктуры (сеть), а если маршрут на стороне провайдера, внешние стороны (провайдер, IX).
  2. Сравнить замеры с пределами, на которые рассчитана игра: Измеренные RTT и джиттер сравнивают с окнами реакции в игре (время на уклонение, парирование и т. п.), пределом компенсации задержки, длиной буфера интерполяции и размером буфера ввода. Например, если окно парирования 0,2 с, то абоненты провайдеров, у которых путь туда и обратно вместе с буфером интерполяции дольше этого, опаздывают, даже если реагируют вовремя. Если подогнать игру под них, расширив компенсацию задержки, то уже у тех, в кого попадают, становится больше жалоб «в меня попали, когда я уже был за стеной». Если провайдеров за пределом много, команда инфраструктуры прорабатывает размещение региона или точек присутствия (edge PoP) ближе к игрокам, а команда разработки пересматривает значения окон, интерполяции и компенсации задержки. Ориентиры собраны в главе справочника о моделях синхронизации. Кого звать первым: команда разработки (сервер и клиент: пределы архитектуры), команда инфраструктуры (сеть: размещение регионов и PoP).
  3. Проверить MTU и прохождение UDP: Проверяют, проходит ли через местные сети целиком самый большой пакет игры. Отправляют ping с флагом запрета фрагментации (DF) пакетами разного размера, чтобы измерить MTU пути, и смотрят, нет ли участков с MTU меньше 1 500 байт, например PPPoE, туннелей или мобильной сети. Стандарт для датаграммных протоколов вроде UDP (RFC 8899) рекомендует для IPv4 базовый размер 1 200 байт, который проходит через большинство путей. Если максимальный пакет игры больше, вместе с командой разработки решают, уменьшать его или делить на части. Проверяют и то, не блокируют ли UDP или игровые порты и не ограничивают ли их скорость в публичном Wi-Fi, корпоративных сетях и у отдельных провайдеров, и есть ли запасной путь на случай блокировки (TCP, порт 443). Кого звать первым: команда инфраструктуры (сеть) и команда разработки (сервер: размер пакетов).
  4. Измерить таймаут простоя NAT и CGNAT и подобрать интервал хартбита: Измеряют, через сколько местные домашние роутеры и мобильные сети (CGNAT) удаляют запись NAT для неактивного UDP-соединения. В каждом прогоне тестовое устройство отправляет на сервер один пакет, чтобы создать запись, и дальше ничего не шлёт, а сервер через заданное время (30 с, 60 с, 120 с …) отправляет пакет на устройство. Время, начиная с которого устройство перестаёт получать этот пакет, и есть таймаут простоя этой сети. Стандарт (RFC 4787) требует, чтобы запись UDP не истекала раньше чем через 2 минуты, и рекомендует по умолчанию 5 минут и больше, но значения у оборудования сильно различаются, и некоторые устройства удаляют записи раньше. Запись надёжно обновляется только пакетами, исходящими от устройства, поэтому хартбит отправляет клиент, и проверяют, что его интервал не больше половины самого короткого из значений: измеренного таймаута и таймаутов простоя балансировщика нагрузки и облачной группы безопасности. Кого звать первым: команда разработки (клиент: интервал хартбита; сервер: значения таймаутов), команда инфраструктуры (настройки балансировщика и групп безопасности).
  5. Проверить внешние сервисы и оборудование безопасности на пути местных игроков: Проверяют, с нормальной ли скоростью отвечают местные сервисы входа через платформу, оплаты и подтверждения личности, правильно ли местные DNS разрешают адреса серверов авторизации и патчей и отдаёт ли CDN патчи из точки присутствия рядом с этой страной. Смотрят, не попадают ли диапазоны IP новой страны под правила блокировки по странам и ограничения скорости в защите от DDoS и файрволе, и особенно, не блокируются ли целиком диапазоны CGNAT, где один IP делят многие абоненты. Кого звать первым: команда инфраструктуры (оборудование безопасности, DNS, CDN), внешние стороны (платформы, платёжные компании, провайдеры).
  6. После запуска смотреть в разбивке по странам и ASN: К клиентским IP в логах подключений и логах балансировщика добавляют страну и ASN и смотрят по странам и провайдерам RTT, повторные передачи, число дисконнектов и их причины (таймаут хартбита, RST, кик сервером). Бесплатные базы вроде MaxMind GeoLite ASN переводят IP в ASN и название организации, а сами IP по местным правилам о персональных данных хранят в укрупнённом виде, до /24 или ASN. Если проблемы сосредоточены в одном ASN, первым делом смотрят маршрут этого провайдера (команда инфраструктуры, внешние стороны); если плохо во всей новой стране, то расстояние и пределы, на которые рассчитана игра (команда инфраструктуры, команда разработки); если хуже становится только вечером, то перегрузку пиринга. Если у части игроков пинг высокий постоянно, вместе с командой разработки (сервер) проверяют, не отправило ли их в далёкий регион из-за ошибки GeoIP, VPN или выбора региона по лидеру группы. Если синтетический мониторинг в норме, а плохо только у игроков, дело в окружении игрока или в клиенте.
  7. Проверить, как игроки из далёких регионов влияют на остальных: Когда игроков, подключающихся издалека, становится больше, дело не ограничивается тем, что лагает у них самих. Ввод игрока с плохой связью приходит пачками, на экранах остальных его персонаж движется перемоткой, а на сервере срабатывают проверки скорости и кулдаунов, и появляются откидывание назад и отклонённые умения. В групповых механиках запоздалая реакция одного медленного игрока проваливает всю группу, а в lockstep все ждут самого медленного. После запуска в новой стране смотрят, не стало ли больше жалоб от прежних игроков вида «странно выглядит один персонаж», и вместе с командой разработки решают вопрос с буфером ввода, допусками проверок и разделением матчмейкинга по регионам. Кого звать первым: команда разработки (сервер).

Реальные инциденты

Отобраны только постмортемы, которые опубликовали сами игровые и инфраструктурные компании. Краткие описания не выходят за рамки того, что сказано в оригинале. Подробности смотрите в первоисточнике.

CCP Games 2014: EVE Online: перегрузка сервера во время масштабной битвы флотов в HED-GP

Постмортем от января 2014 года разбирает масштабную битву флотов в системе HED-GP, во время которой сервер был сильно перегружен. Time Dilation (функция, которая замедляет игровое время при перегрузке) дошла до нижнего предела в 10%, и всё поле боя ушло в слоумо, но нагрузка продолжала копиться. Отставание в обработке остановок и повторных срабатываний модулей (Dogma Lateness) доходило до 193 с игрового времени, то есть примерно до 32 минут реального. В битве за 6VDT в июле 2013 года, почти такой же по масштабу, максимум составлял 42 с (около 7 минут реального времени). В CCP оговорились, что полной уверенности нет: инструменты профилирования сами добавляют нагрузку, поэтому в такой ситуации их не запускают. С этой оговоркой были названы две вероятные причины. Первая: бой затянулся, и необработанная нагрузка продолжала накапливаться. Вторая: стало больше дронов. Число выпущенных за бой дронов (без повторов) составило 21 123 в 6VDT и 38 852 в HED-GP, то есть на 84% больше. Когда о действии одного игрока нужно сообщить всем, кто его видит, объём рассылки растёт как квадрат числа участников (O(n²)), а у дронов на одну атаку приходится больше сообщений. К тому же код, которым дрон выбирает цель, часто перебирает все доступные для атаки цели на поле боя, и его стоимость растёт почти как n².

Если в локации, где собралось много игроков, нагрузка превышает пропускную способность сервера, вся локация уходит в слоумо, а чем дольше идёт бой, тем больше копится отставание и тем сильнее задержка ввода. Признаки для проверки: время тика и объём отложенной работы на сервере (ноде), который обслуживает эту локацию, а также число игроков и объектов в ней. Характерно, что в других локациях всё в порядке. Основной ответственный: команда разработки (сервер). Что исправлять: круг получателей рассылки об одном действии и стоимость поиска целей у ИИ. Замедление игрового времени не убирает перегрузку, но все замедляются одинаково, и отдельные действия не застревают в очереди бесконечно. Первоисточник

Riot Games 2015: Обходные маршруты трафика League of Legends и Riot Direct

Техническая статья Riot Games о том, почему интернет плохо подходит для игр в реальном времени. Реальный трафик, о котором сообщил игрок League of Legends, должен был идти напрямую из Сан-Франциско в Портленд, но шёл через Лос-Анджелес, Денвер и Сиэтл, и вместо 14 ms по прямой занимал 70 ms. В Riot объясняют: когда маршрутизатор переполняется и отбрасывает пакеты, другие чемпионы скачут по экрану, а снаряды словно телепортируются. В Riot назвали причинами маршруты и маршрутизаторы. Магистральные операторы и провайдеры отправляют трафик по самому дешёвому маршруту, даже если есть путь с меньшей задержкой, а когда выбранный по BGP маршрут делает большой крюк, растёт и число маршрутизаторов на пути. Нагрузка на маршрутизатор зависит от числа пакетов, их размер значения не имеет. Игровые пакеты весят около 55 байт, поэтому при том же объёме данных их в 27 раз больше, чем пакетов по 1 500 байт, и входные буферы маршрутизаторов они заполняют во столько же раз быстрее. По словам Riot, многие маршрутизаторы при перегрузке первыми отбрасывают UDP-пакеты. В качестве решения в Riot построили собственную сеть Riot Direct: маршрутизаторы в 10 крупных интернет-узлах США, напрямую связанные пирингом с максимально возможным числом провайдеров. Во второй части сказано, что доля игроков с пингом ниже 80 ms чуть больше чем за 9 месяцев выросла с 31% до 50%, а после переезда игровых серверов в Чикаго за одну ночь достигла 80%.

Если даже внутри одной страны пинг заметно выше только у абонентов определённого провайдера, стоит подозревать маршрут. Признаки для проверки: распределение RTT по провайдерам (ASN) и транзитные города в выводе traceroute. Основной ответственный: команда инфраструктуры (сеть). Исправляют прямым пирингом с провайдерами, подключением к IX и выбором места для серверов. Маршрутную политику на стороне провайдера нужно согласовывать с внешней стороной (провайдером). Этот случай показывает и то, что даже перенос серверов ближе к центру географии игроков даёт большой эффект. Первоисточник

Riot Games 2020: Перегрузка edge-хоста на серверах League of Legends в Европе и Бразилии

В конце февраля 2020 года на серверах League of Legends EUW, EUNE и BR случилось несколько сбоев, и число новых матчей резко упало. Все бэкенд-сервисы, включая матчмейкинг и игровые серверы, были в нормальном состоянии, но входящего трафика почти не было. Чтобы не запускать турнирный режим (Clash) на кластерах, которые могли оказаться нестабильными, в Riot перенесли его на неделю. Длительность каждого сбоя в постмортеме не указана. Совпали три вещи. Запрос к одному из сервисов был сформирован неправильно, в определённых случаях раз за разом завершался ошибкой и повторялся, и число запросов резко выросло. Из-за известной несовместимости системы контейнеров с версией ОС текла память внутри ОС. Обновление успели выкатить только примерно на 60% всей контейнерной среды Riot, а на кластерах Европы и Латинской Америки оно ещё шло. Edge-контейнеры, которые принимают интернет-трафик, фильтруют его и передают в бэкенд, разносились по разным хостам внутри одного шарда (группы серверов), но для разных шардов такого правила не было, поэтому во время каждого сбоя edge-контейнеры как минимум трёх шардов оказывались на одном хосте. На этот хост пришлась лавина повторных запросов, а утечка памяти его остановила.

Если все бэкенд-сервисы отвечают «всё в норме, но трафик не приходит», смотрят на то, что стоит перед ними (edge, шлюз, балансировщик нагрузки). Признаки для проверки: перекос числа входящих соединений по хостам и доля ошибок и повторных попыток у определённого запроса. Основной ответственный: команда разработки (сервер: неправильный запрос и логика повторных попыток). Правила размещения контейнеров, обновление ОС и алерты на перекос берёт на себя команда инфраструктуры (серверы и ОС). В Riot исправили код запроса, сделали так, чтобы повторные попытки не нарастали лавиной, и до внедрения распределения между шардами поставили алерт на перекос. Первоисточник

Riot Games 2021: Сбой League of Legends EUW на 5 часов: одна второстепенная БД остановила весь сервер

22 января 2021 года сервер League of Legends EUW чуть больше 5 часов работал со сбоями. Метрики числа вошедших игроков и игроков в матчах разом оборвались, а между двумя перезапусками входов становилось больше, но матчи почти не начинались. На основном сервере БД, которая обслуживала второстепенную функцию, случился аппаратный отказ, а автоматическое переключение этой БД на резервный сервер настроено не было. Пулы соединений у каждой БД были свои, но все они работали через один пул потоков. Задачи, отправленные в отказавшую БД, не завершались и занимали потоки, и в итоге потоки закончились у всей системы. Алерты сыпались потоком, и команда сначала подозревала недавнюю злонамеренную сетевую атаку и аппаратные работы в другом регионе, поэтому алерт по отказавшей БД заметили только примерно через час. Все системы работали в одной JVM, и когда после перезапуска под нагрузкой от переподключений GC останавливал процесс на несколько секунд, в сборе метрик тоже возникали большие пробелы. Очередь на вход к тому же не соблюдала заданный лимит, и приток игроков был неравномерным.

Даже одна второстепенная БД, которую считали неважной, может остановить всё через общий ресурс вроде пула потоков. Признаки для проверки: число ожидающих запросов по каждой БД, загрузка пула потоков и слишком малое число начатых матчей по сравнению с числом входов. Ответственные: команда разработки (сервер: изоляция пулов потоков, таймауты) и команда инфраструктуры (БД: автоматическое переключение). Когда сыплются алерты, легко первым делом заподозрить недавнюю проблему (атаку и т. п.), поэтому причины исключают по одной в порядке диагностики (охват → момент → слой). После перезапуска проверяют и то, ограничивает ли очередь на вход приток игроков так, как настроено. Первоисточник

Roblox 2021: Сбой Roblox на 73 часа: конкуренция в кластере service discovery (Consul)

Сбой начался днём 28 октября 2021 года (по тихоокеанскому времени) с высокой загрузки CPU на одном сервере Consul. В 16:35 онлайн упал вдвое по сравнению с обычным, после чего встал весь сервис. Только 31 октября в 16:45 все игроки снова смогли войти, через 73 часа после начала сбоя. По данным Roblox, сервисом каждый день пользуются 50 миллионов человек. Roblox использует HashiCorp Consul для service discovery (сервисы находят адреса друг друга), health check и как KV-хранилище, причём один кластер Consul обслуживал сразу несколько рабочих нагрузок. Первопричин было две. Первая: новую функцию streaming в Consul, которую несколько месяцев постепенно включали всё шире, накануне сбоя включили и для сервиса маршрутизации трафика, а число нод этого сервиса увеличили на 50%. При очень большом числе и чтений, и записей эта функция вызвала конкуренцию за один общий ресурс (Go channel). На двухсокетных (NUMA) серверах с большим числом ядер, которые поставили на замену прямо во время сбоя, конкуренция была ещё сильнее. Вторая: управление списком свободных страниц (freelist) в BoltDB, где Consul хранит лог Raft, патологически замедлилось, и при каждом добавлении записи до 16 kB на диск записывалось 7,8 MB. Медиана задержки записи в KV, обычно ниже 300 ms, выросла до 2 с, а на медленном сервере-лидере наблюдали и нулевое окно, когда буфер TCP заполнен до конца. Телеметрия зависела от Consul, поэтому вместе с ним пропали и метрики, нужные для поиска причины.

Если тормозит базовая система, от которой зависят многие сервисы (service discovery, хранилище конфигурации, аутентификация), разом останавливаются все функции. Признаки для проверки: задержка записи, смены лидера и загрузка CPU в этой системе, а также изменения настроек прямо перед сбоем. Ответственные: обе команды, разработки (сервер) и инфраструктуры (серверы и ОС). Мониторинг нужно отделить от системы, за которой он следит, тогда метрики будут видны и во время сбоя. При восстановлении кэши пусты, и если впустить всех сразу, система может снова упасть, поэтому в Roblox регулировали долю допускаемых игроков через DNS и увеличивали её шагами примерно по 10%. Первоисточник

Square Enix 2021: Перегрузка на старте дополнения FINAL FANTASY XIV и ошибки очереди на вход

С начала раннего доступа к дополнению Endwalker в декабре 2021 года все миры были крайне перегружены. Очередь на вход росла, а при входе с экрана выбора персонажа и во время ожидания в очереди часто появлялась Error 2002. Случались и падения отдельных миров и зон (Error 3001), и таймауты очереди (Error 4004). Даже на момент объявления 11 декабря, на 8-й день раннего доступа, перегрузка продолжалась. Error 2002 возникает в двух случаях. Первый: в очереди одного логического дата-центра больше 17 000 человек. Этот лимит не даёт очереди разрастись настолько, что упадёт сервер авторизации, и в этом случае клиент полностью закрывается. 7 декабря для лобби-серверов задействовали резервное оборудование, предназначенное для разработки, и подняли лимит. Этих ошибок стало меньше, но очередь, наоборот, выросла. Второй случай: нестабильное подключение у игрока, ожидающего в очереди. Ожидание затянулось, и короткие обрывы связи из-за потерь пакетов на интернет-маршруте или нестабильного Wi-Fi стали случаться чаще. Лобби-сервер ждёт переподключения от нескольких десятков секунд до минуты. Если игрок успевает переподключиться, он продолжает с того же места в очереди, а если нет, встаёт в самый конец. По словам Square Enix, большинство обращений относилось именно к этому случаю. Быстро добавить миры мешал и дефицит полупроводников.

Чем длиннее очередь, тем чаще короткий обрыв связи у ожидающего игрока превращается в ошибку подключения. При одной и той же перегрузке ошибки достаются в основном тем, кто играет через Wi-Fi или нестабильное подключение, и проблема становится проблемой «только у части игроков». Признаки для проверки: длина очереди и время ожидания, а также доля обрывов во время ожидания среди причин отключения. Основной ответственный: команда разработки (сервер: лимит очереди и окно переподключения). Добавление лобби-серверов и серверов миров вместе с ней берёт на себя команда инфраструктуры. Если оставить щедрое окно переподключения, короткие обрывы на линии игрока реже оборачиваются потерей места в очереди. Первоисточник

Cloudflare 2020: Потеря трафика в части городов из-за ошибки в настройке магистрали Cloudflare

Многие игры держат сайт, API и защиту от DDoS у CDN-провайдеров, поэтому такой инфраструктурный сбой задевает и игры. 17 июля 2020 года с 21:12 до 21:39 (UTC), за 27 минут, общий трафик в сети Cloudflare упал примерно на 50%. Пострадали только точки присутствия в части городов США, Европы, России и Бразилии, подключённые к магистрали, остальные работали нормально. Из-за аварии на магистральном участке Ньюарк–Чикаго перегрузился участок Атланта–Вашингтон, и инженер изменил настройку маршрутизатора, чтобы снять с Атланты часть магистрального трафика. Отключить нужно было весь элемент политики (term), однако отключили только условие внутри него (prefix-list). В результате маршрутизатор в Атланте разослал по всей магистрали все маршруты BGP с более высоким приоритетом (local-preference 200). Маршрутам к собственным серверам точки присутствия давали приоритет 100, поэтому весь трафик точек, подключённых к магистрали, ушёл в Атланту. Атланта перегрузилась, а у пострадавших точек почти не осталось трафика для обработки. Когда маршрутизатор в Атланте отключили от магистрали, работа восстановилась. В Cloudflare заявили, что сбой не связан с атакой или взломом.

Если только у игроков определённого города или региона разом начинаются дисконнекты или ошибка входа / бесконечная загрузка, а у остальных всё в порядке, первым делом подозревают недавнее изменение маршрутизации. На графике CPU и трафик взлетают только в одной точке присутствия, а в пострадавших, наоборот, падают почти до нуля. Основной ответственный: команда инфраструктуры (сеть), а если сбой на стороне самого провайдера, то внешние стороны. В Cloudflare решили ограничить число маршрутов, принимаемых в магистральных сессиях BGP (maximum-prefix), и изменили приоритеты так, чтобы одна точка не могла перетянуть на себя трафик других. Первоисточник

Fastly 2021: Ошибки CDN Fastly по всему миру

Многие игры раздают файлы патчей, лаунчер и веб-страницы через CDN, поэтому такой инфраструктурный сбой задевает и игры. 8 июня 2021 года с 09:47 (UTC) 85% сети Fastly начали возвращать ошибки. За 49 минут нормальная работа вернулась на 95% сети, а в 12:35 сбой был устранён. В деплое ПО, начатом 12 мая, был баг, который срабатывал, когда определённая конфигурация клиента Fastly встречалась с определёнными условиями. 8 июня один из клиентов загрузил вполне корректное изменение конфигурации, и условия совпали. Fastly обнаружила аномалию за 1 минуту, а когда вызвавшую сбой конфигурацию клиента нашли и отключили, началось восстановление. Деплой исправления начали в тот же день в 17:25.

Даже код, задеплоенный несколько недель назад, при редком стечении условий в одно мгновение превращается в глобальный сбой. Признаки для проверки на стороне игры: одновременный рост доли HTTP-ошибок у запросов к патчам, лаунчеру и сайту во всех регионах и статусная страница CDN-провайдера. Характерно, что уже установленные игровые соединения, если они идут мимо CDN, продолжают работать, и блокируются только новые подключения, загрузка патчей и вход через веб. Основной ответственный: внешние стороны (CDN-провайдер). Команда разработки и команда инфраструктуры заранее готовят обходной путь: используют два CDN и больше или раздают файлы напрямую с origin-сервера. Первоисточник

Meta 2021: Сбой Facebook: из-за одной команды на магистральных маршрутизаторах пропал даже DNS

Инфраструктурный сбой, уроки которого напрямую применимы к собственной сети и DNS игровой компании. 4 октября 2021 года сервисы Facebook (сейчас Meta) стали недоступны по всему миру. Магистраль, соединяющая ЦОД, полностью отключилась, и из интернета стало невозможно найти DNS-серверы Facebook. Длительность сбоя в постмортеме не указана. Во время планового обслуживания команда, отданная для оценки ёмкости магистрали по всему миру, вопреки замыслу разорвала все соединения магистрали, а инструмент аудита, который должен был блокировать такие команды, из-за бага этого не сделал. DNS-серверы в небольших точках присутствия устроены так, что при потере связи с ЦОД считают себя неисправными и отзывают свои BGP-анонсы. Поэтому DNS-серверы работали, но из интернета до них нельзя было достучаться. Отключились и обычные пути доступа, и внеполосный (out-of-band) доступ, а внутренние инструменты тоже лишились DNS. Инженеров пришлось отправлять в ЦОД лично, и из-за процедур безопасности это заняло ещё больше времени. При восстановлении учитывали, что потребление электроэнергии в каждом ЦОД упало на десятки MW и одномоментный возврат нагрузки мог поставить под удар всё, от систем электропитания до кэшей, поэтому нагрузку поднимали поэтапно.

Если ошибка входа / бесконечная загрузка возникает одновременно во всех регионах и у всех провайдеров, прежде чем разбираться с игровыми серверами, проверяют DNS и маршруты BGP. Это можно проверить и снаружи компании: запросами к DNS извне и по публичным данным о маршрутах BGP. Основной ответственный: команда инфраструктуры (сеть). Заранее проверяют, не зависят ли аварийный внеполосный доступ и внутренние инструменты от того же DNS и той же сети, а при восстановлении поднимают нагрузку поэтапно, чтобы переподключения не нахлынули разом. Первоисточник

AWS 2021: Перегрузка внутренней сети AWS us-east-1

Многие игры держат серверы, вход и данные в публичном облаке, поэтому такой инфраструктурный сбой задевает и игры. 7 декабря 2021 года в 7:30 (тихоокеанское стандартное время) перегрузилась внутренняя сеть региона Северная Вирджиния (us-east-1). С 7:33 выросли ошибки и задержки EC2 API, и запускать новые инстансы стало трудно (запуск инстансов восстановился в 14:40). Затем последовали сбои входа в консоль, невозможность менять настройки Route 53, задержки и частичная потеря метрик CloudWatch. Сетевое оборудование полностью восстановилось в 14:22. Уже работавшие инстансы EC2 и ответы DNS по существующим записям затронуты не были. Автоматическая задача по наращиванию ёмкости одного из сервисов в основной сети вызвала неожиданное поведение у множества клиентов во внутренней сети, и число попыток подключения резко выросло. Оборудование, соединяющее внутреннюю и основную сети, захлебнулось, связь стала запаздывать, а задержки, в свою очередь, увеличивали число попыток подключения и повторов, и перегрузка не спадала. У клиентов был механизм backoff, который при такой перегрузке увеличивает интервал между запросами, но из-за скрытого дефекта он не сработал как надо. Внутренний мониторинг тоже зависел от этой сети, и команда эксплуатации работала без метрик в реальном времени, опираясь на логи.

Если повторные попытки не увеличивают интервал, короткая перегрузка превращается в сбой на несколько часов. Для игры это значит, что уже работающие игровые серверы в порядке, но добавление новых серверов (автомасштабирование), вход, матчмейкинг и оплата через облачные API, а также мониторинг могут встать одновременно. Признаки для проверки: статусная страница облачного провайдера, доля ошибок облачных API и неудачные запуски инстансов. Основной ответственный: внешние стороны (облачный провайдер). Команда разработки добавляет ко всем повторным попыткам экспоненциальную задержку повтора (backoff) со случайным разбросом и лимит числа попыток, а команда инфраструктуры держит запас ёмкости на случай, если масштабирование заблокировано, и готовит запасной вариант в другом регионе. Первоисточник

Cloudflare 2025: Сбой публичного DNS Cloudflare 1.1.1.1

Сбой публичного DNS-резолвера, который пользователи сами прописывают в устройстве или роутере. При таком сбое все игры и сервисы разом перестают работать только у тех, кто использует эту настройку. 14 июля 2025 года с 21:52 до 22:54 (UTC), 62 минуты, резолвер 1.1.1.1 не отвечал по всему миру. В Cloudflare отметили, что для многих пользователей это фактически означало недоступность любых интернет-сервисов. Пострадали запросы по UDP, TCP и DNS over TLS, а DNS over HTTPS, к которому подключаются по доменному имени, работал сравнительно стабильно. 6 июня, при подготовке сервисной топологии (конфигурации, которая определяет, из каких точек присутствия анонсировать диапазоны IP) для другого, ещё не запущенного сервиса, в неё по ошибке попали и диапазоны IP резолвера 1.1.1.1. 14 июля конфигурацию этого сервиса изменили, и вместо всех точек присутствия диапазоны резолвера стала анонсировать одна-единственная точка, к тому же отключённая. По всему миру маршруты BGP были отозваны. Изменение не прошло через канареечный деплой и сразу распространилось на все ЦОД. В 22:20 прежнюю настройку вернули, и трафик восстановился примерно до 77%, но за это время примерно на 23% edge-серверов стёрлись нужные настройки IP. Их пришлось задавать заново, и нормальная работа вернулась только в 22:54. В Cloudflare заявили, что это внутренняя ошибка конфигурации, не связанная с атакой или перехватом маршрутов BGP (hijacking).

Если игровые серверы и другие игроки в порядке, а у части игроков ошибка входа / бесконечная загрузка при подключении к серверам авторизации и патчей, подозревают DNS, которым пользуются эти игроки. Характерно, что уже установленные сессии держатся и не проходят только новые подключения. Это сразу выясняется, если попросить игрока сменить DNS в настройках или вручную запросить адрес сервера. Основной ответственный: внешние стороны (оператор DNS, провайдер). Если команда разработки (клиент) показывает ошибку разрешения имени отдельно от других ошибок, служба поддержки сразу может поставить диагноз. Первоисточник

AWS 2025: Сбой DNS DynamoDB в AWS us-east-1 и долгое восстановление

Многие игры держат серверы, вход и данные в публичном облаке, поэтому такой инфраструктурный сбой задевает и игры. С 23:48 19 октября до 14:20 20 октября 2025 года (тихоокеанское летнее время) в регионе Северная Вирджиния последствия шли в три этапа. До 2:40 20 октября росли ошибки DynamoDB API. С 2:25 до 10:36 не запускались новые инстансы EC2 (проблемы со связью у части новых инстансов ушли в 13:50). С 5:30 до 14:09 росли ошибки подключения у части Network Load Balancer (NLB). В автоматике, которая управляет DNS DynamoDB, было скрытое состояние гонки (race condition). Один из исполнителей, применяющих DNS-планы в разных зонах доступности (DNS Enactor), сильно запоздал и перезаписал новый план устаревшим. Сразу после этого очистка, запущенная другим исполнителем, удалила этот устаревший план, и DNS-запись регионального эндпоинта (dynamodb.us-east-1.amazonaws.com) стала пустой. Автоматика не смогла это исправить, и восстанавливать пришлось вручную. Система управления физическими серверами EC2 зависит от DynamoDB, поэтому за это время истекли аренды (lease), которые поддерживались для каждого физического сервера. Когда DynamoDB вернулась, физических серверов оказалось так много, что повторное получение аренды не успевало завершиться до таймаута, повторные задачи снова копились, и система попала в состояние «коллапса от перегрузки» (congestive collapse). Сетевые настройки новых инстансов распространялись с опозданием, health check NLB то проходили, то нет, и даже исправные ноды раз за разом выпадали из DNS и возвращались.

Ошибка в DNS-записи одного сервиса перекидывается на другие сервисы, которые от него зависят, и даже после устранения причины восстановление занимает ещё несколько часов из-за накопившихся задач и нестабильных health check. Для игры это значит, что уже работающие серверы держатся, но новые серверы не запускаются и автомасштабирование встаёт, а при нестабильных health check балансировщик выводит из ротации исправные серверы. Признаки для проверки: статусная страница облака, доля ошибок API управляемых сервисов, неудачные запуски инстансов и число исправных целей у балансировщика нагрузки. Основной ответственный: внешние стороны (облачный провайдер). Команда инфраструктуры ограничивает число серверов, которые могут разом выпасть из-за проваленных health check, и готовит запасной вариант в другом регионе. Первоисточник

T4Инструменты

Как сообщить о лагах

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

T5Инструменты

Словарь терминов

Слова, которые часто звучат в разговорах с командой разработки и командой инфраструктуры. Введите термин в поле поиска по-русски или по-английски.

Пинг Ping, RTT
Время, за которое ваш сигнал доходит до сервера и возвращается (путь туда и обратно). В пинг, который показывает игра, иногда входит и время ожидания обработки на сервере.
Задержка Latency
Время от отправки пакета до его прибытия. Часто имеют в виду одно направление, поэтому это примерно половина пинга.
Джиттер Jitter
Неравномерность интервалов между приходом пакетов. Даже при одинаковом среднем пинге большой джиттер даёт микрофризы.
Пакет Packet
Порция данных, которую сеть передаёт за один раз. Обычно не больше 1 500 байт, а игровые обновления занимают от десятков до сотен байт.
Потери пакетов Packet loss
Отправленный пакет не доходит и пропадает. В игре на TCP уже при 1% потерь картинка заметно спотыкается раз в несколько секунд или раз в десяток с лишним секунд, а игры на UDP с интерполяцией и повторной отправкой ввода могут скрывать даже потери в несколько процентов.
Пропускная способность Bandwidth
Максимальный объём данных, который линия связи может передать за 1 секунду (Mbps). Не путайте с задержкой: она показывает, как быстро данные доходят.
Тик Tick
Один шаг, за который сервер рассчитывает состояние игры. 20-тиковый сервер считает 20 раз в секунду, каждые 50 ms.
Тикрейт Tick rate
Сколько тиков сервер выполняет за секунду. Чем выше, тем быстрее отклик, но растут стоимость серверов и объём трафика. Чтобы экономить трафик, частоту отправки пакетов иногда делают ниже тикрейта.
Бюджет тика Tick budget
Предел времени, за который нужно завершить один тик. Если его превысить, следующий тик запаздывает и интервал между тиками растёт.
FPS Frames per second
Сколько раз в секунду обновляется изображение. При 60 FPS на кадр приходится 16,7 ms.
Время кадра Frame time
Сколько времени ушло на отрисовку одного кадра. Для ощущений редкие долгие кадры важнее среднего FPS.
Снапшот Snapshot
Сводка «текущего состояния игры», которую сервер отправляет каждый тик: позиции, здоровье, состояния и т. п. Обычно в ней только то, что изменилось относительно уже известного получателю состояния (дельта-сжатие).
Интерполяция Interpolation
Отрисовка промежуточных положений между двумя полученными снапшотами, чтобы движение выглядело плавным. Цена: на экране показывается немного прошлое.
Буфер интерполяции Interpolation buffer
Время, на которое отрисовку намеренно откладывают ради интерполяции. Этот запас поглощает джиттер и одну-две потери. Обычно он равен 2 интервалам между пакетами (100 ms, если пакеты приходят 20 раз за 1 с), а некоторые игры сами увеличивают его, когда растёт джиттер.
Экстраполяция Extrapolation, Dead reckoning
Когда новых пакетов нет, игра по последней скорости угадывает, где объект окажется дальше, и рисует его там. Если прогноз не сбылся, это выглядит как телепортация, поэтому многие игры экстраполируют примерно до 0,25 с и останавливаются (значение по умолчанию в движке Source: 0,25 с).
Клиентское предсказание Client-side prediction
Игра сразу двигает вашего персонажа, не дожидаясь подтверждения сервера.
Серверная коррекция Reconciliation
Когда приходит результат от сервера, клиент сравнивает его с предсказанием и исправляет позицию персонажа: берёт подтверждённую сервером позицию и заново применяет ещё не подтверждённый ввод. При большом расхождении это выглядит как откидывание назад.
Компенсация задержки Lag compensation
При проверке попадания сервер отматывает время назад, к моменту, который видел атакующий, и проверяет, было ли попадание. Чтобы не наказывать тех, в кого стреляют, глубину отмотки ограничивают. В соревновательных шутерах обычно около 0,2–0,25 с, но бывает и до 1 с, как по умолчанию в движке Source.
Авторитетный сервер Authoritative server
Архитектура, в которой окончательное решение принимает только сервер. Это защищает от читов, но каждый результат требует пути до сервера и обратно. Поэтому ожидание маскируют предсказанием и опережающим фидбеком.
Lockstep Deterministic lockstep
Все участники обмениваются только вводом и на одном и том же ходе одинаково всё рассчитывают. Задают фиксированную задержку применения ввода (input delay), а если чей-то ввод опаздывает, ждут все.
Серверный буфер ввода Server-side input buffer
Буфер, в котором сервер копит немного ввода от каждого игрока и берёт по одной команде за тик. Даже игрок с большим джиттером выглядит для других плавно, но его действия подтверждаются на сервере на это время позже.
Listen-сервер Listen server
Схема, в которой ПК одного из игроков одновременно и играет, и работает сервером. У хоста пинг равен 0, но если его подключение или ПК медленные, лагает у всех.
Фазирование Phasing
Функция, которая в одном и том же месте показывает разных NPC и разный ландшафт в зависимости от прогресса по квестам. Если у двух персонажей разный прогресс, отсутствие NPC у одного из них нормально.
Роллбэк-неткод Rollback netcode (GGPO)
Игра предсказывает ввод соперника и идёт дальше, а если реальный ввод оказался другим, возвращается к прошлому кадру и пересчитывает. Часто используется в файтингах. С роллбэком в БД это не связано.
Буферизация ввода Input buffer, spell queue
Игра принимает следующую команду, нажатую чуть раньше окончания кулдауна или анимации, и выполняет её в момент окончания. Так между приёмами в связке не появляется время пути до сервера и обратно.
Опережающий фидбек Client-side feedback
Анимации, звуки и эффекты проигрываются сразу, не дожидаясь подтверждения сервера. Ответа сервера ждут только результаты, которые нужно подтвердить, например урон и награды. Если сервер отказывает, показанное приходится отменять.
TCP Transmission Control Protocol
Протокол, который доставляет данные по порядку и без пропусков. Пока потерянный пакет не получен заново, следующие пакеты игре не передаются.
UDP User Datagram Protocol
Протокол, который доставляет данные как есть, без гарантий. Ожидания нет, зато потери и порядок игра обрабатывает сама.
Надёжный UDP Reliable UDP (KCP, ENet…)
Подход, при котором поверх UDP сами реализуют ровно столько повторной передачи и упорядочивания, сколько нужно.
HOL-блокировка Head-of-line blocking
Один застрявший элемент в начале очереди заставляет ждать всех за ним. Причина перемотки в играх на TCP.
RTO Retransmission timeout
Таймер повторной передачи: сколько TCP ждёт, прежде чем признать пакет потерянным и отправить его снова. В Linux не меньше, чем пинг + 200 ms, после каждой неудачи удваивается.
Алгоритм Нейгла Nagle’s algorithm
Функция TCP, которая копит мелкие данные, пока не придёт подтверждение (ACK) на отправленные ранее, и отправляет их одним пакетом, чтобы экономить пакеты. В играх его обычно нужно отключать.
TCP_NODELAY TCP_NODELAY
Опция сокета, которая отключает алгоритм Нейгла. Мелкие сообщения уходят сразу.
Отложенный ACK Delayed ACK
Функция, при которой подтверждение приёма отправляется с небольшой задержкой, вместе с другими данными. В Linux обычно 40 ms (максимум 200 ms), в старых версиях Windows 200 ms, в современных 40 ms.
Буфер сокета SO_SNDBUF / SO_RCVBUF
Размер места, которое ОС выделяет каждому сокету под данные, ожидающие отправки или чтения. Слишком маленький буфер переполняется, а в слишком большом копятся устаревшие данные и ждут своей очереди.
keepalive SO_KEEPALIVE
Функция TCP, которая проверяет, живо ли неактивное соединение. По умолчанию выключена, а если её включить, со стандартными настройками первая проверка будет только через 2 часа.
RST TCP reset
Сигнал TCP, который немедленно и принудительно закрывает соединение. Ещё не отправленные данные пропадают.
Хартбит Heartbeat
Сигнал «я жив», который игра сама отправляет с постоянным периодом. Нужен, чтобы обнаруживать оборванные соединения и не давать промежуточному оборудованию закрыть соединение.
Таймаут Timeout
Сколько ждать ответа, прежде чем считать попытку неудачной. Слишком короткий таймаут даёт ложные срабатывания, слишком длинный запаздывает с обнаружением.
NAT Network Address Translation
Функция роутера, которая выпускает несколько домашних устройств в интернет с одного публичного IP и записывает соединения в таблицу NAT.
CGNAT Carrier-grade NAT
Крупномасштабный NAT у провайдера, при котором один IP делят несколько абонентов.
MTU Maximum Transmission Unit
Максимальный размер пакета, который можно отправить за один раз. Обычно 1 500 байт, на участках с VPN или PPPoE меньше.
Bufferbloat Bufferbloat
Оборудование копит слишком длинные очереди, и задержка вырастает до сотен ms.
SQM Smart Queue Management (fq_codel, CAKE)
Функция роутера, которая держит очереди короткими и справедливо распределяет отправку между потоками. Решение проблемы bufferbloat.
QoS Quality of Service
Функция, которая даёт приоритет важному трафику, чтобы он уходил первым.
Пиринг Peering
Точки, где сети провайдеров соединяются друг с другом. По вечерам легко перегружаются.
BGP Border Gateway Protocol
Протокол, по которому провайдеры сообщают друг другу, каким маршрутом отправлять трафик в интернете. Когда маршруты меняются, меняются путь пакетов и пинг.
DDoS Distributed Denial of Service
Атака, при которой огромный объём трафика со множества источников выводит сервис из строя.
Центр очистки трафика DDoS scrubbing center
Узел компании, которая защищает от DDoS: во время атаки трафик к серверу сначала идёт туда, атака отсеивается, и дальше передаётся только нормальный трафик. Если узел далеко, маршрут удлиняется.
Файрвол Firewall
Устройство или программа, которая пропускает только разрешённые соединения. Отслеживает соединения в таблице сессий.
Балансировщик нагрузки Load balancer
Устройство, которое распределяет входящие соединения между несколькими серверами.
Таблица сессий Session table, conntrack
Таблица, в которой оборудование или ОС отслеживает текущие соединения. Её размер ограничен.
Микробёрст Microburst
В среднем трафика немного, но в очень короткие моменты (1 ms и меньше) он резко наваливается.
NIC Network Interface Card
Сетевая карта сервера.
Кольцевой буфер Ring buffer
Буфер, где NIC держит полученные пакеты, пока их не заберёт CPU. Фиксированное число слотов используется по кругу, и когда все слоты заняты, новые пакеты отбрасываются.
Прерывание Interrupt
Сигнал, которым устройство сообщает CPU, что появилась работа.
RSS Receive Side Scaling
Функция NIC, которая раскладывает полученные пакеты по нескольким очередям приёма, чтобы их обрабатывали несколько ядер CPU.
PPS Packets per second
Число пакетов в секунду. Игровые серверы часто упираются в этот показатель раньше, чем в пропускную способность.
Ядро Kernel
Центральная часть операционной системы. Отвечает за сеть, память и распределение CPU.
backlog Listen backlog
Очередь, в которой ждут новые запросы на подключение, ещё не принятые сервером. Когда очередь заполнена, Linux молча отбрасывает новые запросы, а Windows отвечает отказом.
TIME_WAIT TIME_WAIT
Состояние, в котором сторона, первой закрывшая соединение, ещё некоторое время (в Linux 60 с) держит эту комбинацию портов на случай запоздавших пакетов.
CPU steal Steal time
Время, которое виртуальная машина прождала, потому что физический сервер отдавал CPU другим виртуальным машинам. Видно в top как значение st.
Троттлинг CPU CFS throttling
Принудительная остановка контейнера до следующего периода, если он израсходовал квоту CPU (quota) внутри заданного периода (CFS period, обычно 100 ms).
Файловый дескриптор File descriptor
Номер (fd), который получает каждый открытый процессом файл или соединение. Их количество ограничено.
Поток Thread
Единица выполнения внутри программы, которая работает независимо. Несколько потоков могут выполняться одновременно.
Переключение контекста Context switch
CPU снимает выполняющийся поток и ставит на его место другой. Это не бесплатно.
Блокировка Lock, Mutex
Механизм, который позволяет работать с общими данными только одному потоку за раз.
Дедлок Deadlock
Состояние, в котором потоки ждут блокировок, захваченных друг другом, и стоят вечно.
Пул потоков Thread pool
Заранее созданный набор рабочих потоков. Если все заняты, новая работа ждёт.
Асинхронный ввод-вывод epoll, IOCP, io_uring
Подход, при котором программа не ждёт окончания ввода-вывода, занимается другой работой и получает уведомление о завершении.
AOI Area of Interest
Зона, которую «видит» каждый игрок. Отправляются только изменения внутри неё, и трафик сокращается. Чтобы дешевле определять, кто попадает в зону, карту обычно делят на сетку и проверяют только ближние ячейки.
Рассылка Broadcast, fan-out
Отправка одного изменения всем, кто может его видеть. Если все собравшиеся видят друг друга, объём отправки растёт пропорционально квадрату числа игроков.
GC Garbage collection
Автоматическое освобождение памяти, которая больше не используется. Во время GC программа может останавливаться.
Куча Heap
Область памяти, которую программа по ходу работы запрашивает по мере необходимости.
Утечка памяти Memory leak
Ошибка, при которой ненужная память не возвращается и её потребление растёт без конца. Бывает и при наличии GC, если на ненужные объекты где-то сохраняются ссылки.
Своп Swap, paging
Когда не хватает RAM, часть памяти выгружается на диск. Обращение к выгруженной памяти более чем в 1 000 раз медленнее, чем к RAM.
OOM killer Out-of-memory killer
Механизм Linux: когда память заканчивается, он выбирает процесс, который занимает больше всего памяти, и принудительно завершает его. В контейнере срабатывает, как только достигнут лимит памяти.
Промах кэша Cache miss
Нужных данных нет в ближнем к CPU кэше, и приходится идти в медленную память.
IOPS I/O operations per second
Сколько операций чтения и записи диск выполняет за 1 секунду. У облачных дисков лимит зависит от оплаченного уровня.
fsync fsync
Вызов, который ждёт, пока данные гарантированно запишутся на диск. Обычная запись сначала попадает в память ОС и уходит на диск позже, и если за это время у сервера пропадёт питание, данные могут потеряться. fsync надёжен, но медленный.
Burst-кредиты Burst credits
Накопленный запас, который позволяет облачному диску или серверу ненадолго работать быстрее базового уровня. Когда запас кончается, производительность падает до базовой.
Индекс Index
Структура в БД для быстрого поиска строк. Без неё приходится читать всю таблицу.
Полное сканирование Full table scan
Запрос, который без индекса проверяет каждую строку таблицы.
План выполнения Query plan
Способ, которым БД решила выполнить запрос: в каком порядке и с какими индексами. Даже при неизменном коде тот же запрос может внезапно замедлиться, если БД сменит план.
Транзакция Transaction
Набор операций в БД, объединённый по принципу «всё или ничего». Обмен предметами обязательно проводят в транзакции. Пока она не завершится, изменённые строки заблокированы, поэтому чем она короче, тем лучше.
Пул соединений Connection pool
Набор заранее открытых соединений с БД. Если все заняты, новый запрос ждёт.
Горячая строка Hot row
Строка, которую одновременно пытаются изменить много запросов. Источник конкуренции за блокировки.
Отставание репликации Replication lag
Насколько реплика БД отстаёт от основной БД.
Роллбэк Rollback
Сохранение отменяется, и данные возвращаются к прежнему состоянию. Игрок воспринимает это как «пропал предмет».
Кэш Cache (Redis etc.)
Копия часто используемых данных в быстром хранилище. Снижает нагрузку на БД.
Контрольная точка Checkpoint
Периодическая запись накопленных в памяти изменений БД на диск разом. В этот момент сохранение и чтение могут ненадолго замедлиться.
Переключение на резерв Failover
Переход на резервный сервер или БД, когда основной вышел из строя. Пока идёт переключение, сохранения ненадолго недоступны, а если репликация отставала, последние данные могут потеряться.
MVCC Multi-version concurrency control
Способ, которым БД не даёт читающим и пишущим мешать друг другу: старые версии строк временно хранятся. Если долго висит открытая транзакция, старые версии копятся и всё замедляется.
Cache stampede Cache stampede
Кэш разом пустеет, и запросы лавиной идут к источнику (БД).
Шлюз Gateway
Промежуточный сервер, который принимает подключения клиентов и передаёт их игровым серверам за собой.
Circuit breaker Circuit breaker
Механизм, который на время прекращает вызовы сервиса, раз за разом отвечающего ошибками, и сразу возвращает ошибку, чтобы не допустить каскадного отказа. Через некоторое время делает один-два пробных вызова и, если сервис восстановился, снова разрешает вызовы.
Каскадный отказ Cascading failure
Сбой в одном месте распространяется по цепочке вызовов на другие сервисы.
Автомасштабирование Autoscaling
Функция, которая автоматически добавляет и убирает серверы в зависимости от нагрузки. На добавление нужно время.
Watchdog Watchdog
Таймер, который следит, не завис ли сервер. Если игровой цикл стоит дольше заданного времени (от нескольких до десятков секунд), watchdog сохраняет снимок состояния (дамп) и принудительно завершает сервер, чтобы его перезапустили.
Утилизация Utilization
Доля времени, когда воркер (то, что обрабатывает запросы: ядро CPU, поток, соединение с БД) занят. Выше 80–90% ожидание резко растёт.
p99 99th percentile
Значение, быстрее которого проходят 99 случаев из 100, а медленнее примерно 1. Лучше среднего показывает лаги, которые ощущают игроки.
V-Sync Vertical sync
Функция, которая выводит кадры в такт обновлению экрана. Убирает разрывы изображения, но добавляет задержку ввода, а если FPS падает ниже частоты обновления, может скакать между 60 и 30 и давать микрофризы.
Переменная частота обновления VRR, G-Sync, FreeSync
Монитор обновляет изображение в тот момент, когда готов кадр. Уменьшает микрофризы и задержку ввода, которые появляются при V-Sync из-за скачков между 60 и 30.
Античит Anti-cheat
Модуль защиты от взлома игры. Если периодическая проверка или хартбит с сервером не проходит, может вызывать микрофризы или дисконнект.
Оверлей Overlay
Функция мессенджеров, программ записи и счётчиков FPS, которая дорисовывает что-то поверх игрового экрана. Встраивается в процесс отрисовки игры и может давать микрофризы.
Компиляция шейдеров Shader compilation
Преобразование программ графических эффектов в код для GPU. Если не сделать её заранее, при первом показе эффекта картинка замирает, а после обновления видеодрайвера сохранённые результаты становятся недействительными и компиляция идёт заново.
Главный поток Main thread, Game thread
Центральный поток игры, который по очереди считает игровую логику и готовит кадр. Если здесь хоть одна операция длится долго, на это время картинка замирает.
Разрешение таймера Timer resolution
Минимальный интервал, через который ОС может разбудить уснувшую программу. В Windows по умолчанию 15,6 ms, поэтому, если программа не изменит его сама, даже просьба «разбуди через 1 ms» выполнится позже.
Тепловой троттлинг Thermal throttling
Защитная функция: при нагреве устройство само снижает частоты CPU и GPU. На телефонах обычно начинается через несколько минут или несколько десятков минут игры.
VRAM Video memory
Собственная память видеокарты. В неё загружают текстуры и модели для отрисовки. Если её не хватает, данные гоняются в память ПК и обратно по медленному пути, и появляются микрофризы.
Нетграф Net graph
Отладочный оверлей, который показывает в игре графики пинга, потерь, FPS и тиков в реальном времени. Если он попал в видео с жалобой на лаги, найти причину намного проще.
Доля повторных передач Retransmission rate
Доля отправленных TCP-пакетов, которые пришлось отправить повторно. Общепринятой нормы нет, но среднее по серверу ниже 0,1% считается здоровым, а выше 1% многие игроки уже легко замечают лаги. Смотрят и на то, во сколько раз значение выросло относительно обычного.
SACK Selective ACK
Функция TCP, с которой получатель подробно сообщает: «этот участок получен, не хватает только вот этого». Даже при нескольких потерях всё восстанавливается за один раз.
RACK-TLP Recent ACK, Tail Loss Probe
Функция TCP, которая определяет потери по времени, а если ACK долго нет, отправляет последний пакет ещё раз, чтобы ускорить восстановление. Включена по умолчанию в современных Linux и Android. В Windows TLP и RACK включены по умолчанию начиная с 10 (1607) и Server 2016, а новый RACK, который восстанавливает и потерянные повторные передачи, есть начиная с Server 2022. Работает только на соединениях с включённым SACK.
Ложная повторная передача Spurious retransmission
Пакет пришёл с опозданием или не по порядку, его сочли потерянным и отправили снова, хотя он не терялся. Линия связи загружается зря, а скорость отправки без нужды снижается.
Нулевое окно Zero window
Буфер получателя заполнен, и он сообщает «пока не присылай». Похоже на повторную передачу, но линия связи в порядке: получающая программа не успевает вовремя читать данные.
thin stream Thin stream
Соединение, по которому, как в играх, изредка отправляются мелкие пакеты. Сигналы для быстрой повторной передачи накапливаются плохо, поэтому при потере соединение надолго замирает.
Полисер Policer
Способ ограничения скорости, при котором пакеты сверх заданной скорости сразу отбрасываются, без постановки в очередь. Способ, при котором пакеты ставятся в очередь и выпускаются медленнее, называется шейпером.
Пейсинг Pacing
Отправка пакетов, равномерно распределённая во времени, без выброса одной пачкой. Не даёт переполнять маленькие буферы.
ECN Explicit Congestion Notification
Функция, при которой перегруженное оборудование, не отбрасывая пакеты, ставит на них отметку «перегрузка», и отправитель снижает скорость. О перегрузке сообщается без потерь. Работает, только если её поддерживают оба конца и оборудование на перегруженном участке.
MSS Maximum Segment Size
Максимальный объём данных в одном TCP-пакете. Обычно 1 460 байт. Если уменьшить его под туннельный участок, можно избежать чёрной дыры MTU.
Хендовер Handover
Переключение телефона в движении с одной базовой станции на другую.
Перцентиль Percentile (p50, p95, p99)
Значение, которое оказывается на заданном проценте позиций, если выстроить все значения по возрастанию. p50 называют медианой, p99 соответствует самому медленному 1 случаю из 100. Показывает всплески, которые прячет среднее.
Хвостовая задержка Tail latency
Длинные задержки, которые случаются изредка, хотя почти всё проходит быстро. В среднем их почти не видно, но именно их игроки запоминают как лаги.
Синтетический мониторинг Synthetic monitoring
Вместо реальных игроков измерительные устройства или серверы в заданных точках периодически отправляют ping, traceroute и т. п. и оценивают качество маршрута. Типичный публичный инструмент: RIPE Atlas.
Интервал агрегации Aggregation interval
Сколько секунд или минут объединено в одну точку графика. Чем длиннее интервал, тем сильнее короткие всплески растворяются в среднем.
Постмортем Postmortem
Разбор после окончания инцидента: что произошло, почему и что изменить. Его пишут ради предотвращения повторов, без поиска виноватых.
C-state CPU idle state
Режим энергосбережения, в который CPU переходит во время простоя. Чем глубже режим, тем больше экономия, но тем дольше выход из него.
Живая миграция Live migration
Облако переносит работающую виртуальную машину на другой хост, например на время обслуживания хоста. В момент переноса возможна короткая остановка.
SNAT Source NAT
NAT, который заменяет адрес источника исходящих пакетов на публичный. Число портов на один публичный адрес ограничено, и когда они заканчиваются, новые соединения не устанавливаются.
NAT-шлюз NAT gateway
Облачный сервис, через который серверы из частной сети выходят в интернет с одного общего публичного адреса. У него есть лимит одновременных соединений к каждому адресату.
Низкоорбитальный спутниковый интернет LEO satellite internet
Интернет через спутники на высоте от сотен до тысяч km. Задержка намного меньше, чем у геостационарных спутников, но при переключении на другой спутник может скакать.
GeoIP IP geolocation
База данных, которая по IP-адресу определяет страну, город и провайдера. В ней бывают неверные или устаревшие записи, из-за которых игрока отправляют на сервер в далёком регионе.
TLS-сертификат TLS certificate
Электронный документ, который подтверждает, что сервер действительно тот, за кого себя выдаёт. У него есть срок действия, и после истечения зашифрованное соединение не устанавливается и войти нельзя.
Генерация кадров Frame generation
Технология, при которой видеокарта вставляет между реально отрисованными кадрами предсказанные и так повышает FPS. Картинка плавнее, но задержка от ввода до экрана может вырасти.
T6Инструменты

Список литературы

Здесь собраны основания для цифр, значений по умолчанию и описаний поведения в этом справочнике. Только авторитетные материалы: стандарты (RFC), документация ядра и ОС, официальная документация облаков, движков и СУБД, доклады и научные статьи. Карточки причин и раздел «Источники» в конце каждой главы ссылаются на те же материалы. Значения по умолчанию меняются от версии к версии, поэтому перед применением сверьтесь с документацией той версии, которой пользуетесь.

Материалов: 616, издателей: 83. Полный перечень в списке литературы текстовой версии.