Текстовая версия справочника: почему в онлайн-играх бывают микрофризы, телепортация и дисконнекты. Причины (228) разобраны по слоям, от вашего экрана до серверной базы данных. Для каждой причины: симптомы, ответственные команды (команда разработки, команда инфраструктуры), цифры и авторитетные источники.
Основная версия с иллюстрациями и интерактивными экспериментами: Анатомия игровых лагов. Здесь те же причины, термины и источники собраны на одной странице, которая читается без JavaScript. У каждой причины есть и отдельная страница (c/ID.html). Всё одним файлом Markdown: llms-full.txt.
Поиск по симптомам
Лаги возникают из четырёх факторов: Задержка (Из-за расстояния, очередей и времени обработки все пакеты приходят с одинаковым опозданием.) Джиттер (В среднем всё в порядке, но одни пакеты приходят быстро, а другие с опозданием. Причины: Wi-Fi, перегруженная линия связи, занятый CPU.) Потери (Пакеты выбрасывают переполненные очереди, радиопомехи и неисправное оборудование. Короткий обрыв связи тоже означает потерю нескольких пакетов подряд.) Остановка (Тик сервера запаздывает или встаёт (GC, блокировки, синхронные вызовы, перегрузка), кадры на ПК игрока замирают. Случается и при исправной линии связи.)
Микрофризы (Причин: 60): Движение теряет плавность: короткие остановки чередуются с рывками.
Телепортация (Причин: 47): Персонаж без промежуточного движения сразу оказывается далеко от прежнего места.
Откидывание назад (Причин: 14): Персонаж бежит вперёд, и его утягивает обратно на только что пройденное место.
Перемотка (Причин: 36): Замерший экран снова оживает, и накопившиеся движения, удары и урон проносятся разом на большой скорости.
Слоумо (Причин: 24): Всё движется медленно. Применение умений и перемещение монстров выглядят растянутыми. В зависимости от устройства сервера скорость может остаться прежней, и тогда проблема проявляется как микрофризы и телепортация.
Задержка ввода (Причин: 76): Между нажатием и результатом проходит заметное время. При этом картинка может оставаться плавной.
Фриз (Причин: 67): Всё на экране ненадолго (от 0,5 с до нескольких секунд) замирает, а потом снова движется.
Съеденные действия / роллбэк (Причин: 36): Действие, которое точно было сделано, как будто не происходило, или его результат отменяется намного позже.
Дисконнект (Причин: 51): Посреди игры соединение рвётся, и игрока возвращает на экран входа или в окно переподключения.
Невидимки / фантомы (Причин: 20): NPC, монстра или игрока, которые должны быть рядом, нет только на вашем экране, или уже исчезнувший объект остался только у вас.
Ответственные команды и коды ответственных
Код
Команда
Ответственные
Охват
cli
Команда разработки
Разработка клиента
Код игрового клиента: кадры, GC, загрузка; интерполяция, экстраполяция, предсказание; сетевая часть клиента (включая отправку хартбитов и автоматическое переподключение)
srv
Команда разработки
Разработка сервера
Код игрового сервера: тики, потоки, блокировки; архитектура синхронизации; приём подключений (цикл accept, аргумент listen); ответы на хартбиты и очистка оборванных соединений; опции сокетов; проектирование запросов и транзакций
net
Команда инфраструктуры
Сетевая инфраструктура
Линии связи и сетевое оборудование ЦОД (коммутаторы, маршрутизаторы, файрволы, балансировщики нагрузки, защита от DDoS), сетевые ACL, маршрутизация VPC и балансировщики нагрузки в облаке, провайдеры и пиринг
sys
Команда инфраструктуры
Серверная инфраструктура
Серверы и облачные инстансы (включая группы безопасности и отслеживание соединений), настройки ОС и ядра, NIC, среда деплоя и мониторинга
dba
Команда инфраструктуры
Инфраструктура БД
Серверы и хранилища БД; настройки, репликация и резервное копирование БД; кэш-серверы
ext
Внешние стороны
Внешние стороны
ПК и домашняя сеть игрока, участки сети провайдеров (вне наших договоров), облачные провайдеры. Исправить напрямую нельзя, поэтому действуем через подсказки игрокам, запросы внешним сторонам и обходные пути
ID cg-hitch · Основной ответственный Команда разработки · Разработка клиента
Расчёт одного кадра занимает в несколько раз больше времени, чем обычно, и картинка на миг замирает.
Почему Наплыв эффектов умений, массовый спавн и полное обновление UI приходятся на один кадр → Следствие Кадр не укладывается в 16,7 ms и занимает 50–300 ms → На экране Картинка на миг замирает, а в следующем кадре все разом сдвигаются
При наплыве игроков, При определённом действии, Изредка, случайно
Ответственные
Основной ответственный Команда разработки · Разработка клиента
Команда разработки: задачи
Разбивать тяжёлую работу на несколько кадров, искать долгие кадры профайлером, ограничить число эффектов.
Цифры для ориентира
При 60 FPS один кадр длится 16,7 ms. Хватает одного кадра длиннее 50 ms, чтобы игроку показалось, что игра «дёрнулась».
На графике
Случайные всплески · Время кадра
Где смотреть
Записать в PresentMon время кадра (FrameTime) и время, которое CPU и GPU потратили на этот кадр (CPUBusy, GPUBusy). На мобильных смотреть метрики медленных сессий и медленного рендеринга в Android vitals
Подтверждает
Время кадра, обычно около 16,7 ms, подскакивает выше 50 ms в моменты эффектов умений, массового спавна и полного обновления UI, а пинг в эти моменты не меняется
Опровергает
Если время кадра ровное, а дёргаются только другие персонажи, проблема на стороне сети, например «Буфер интерполяции отсутствует или слишком короткий». Если всплески идут через равные промежутки, сначала проверить причину «Сборка мусора на клиенте»
Чем проверить
Проверка на стороне игрока
Источников: 3
Slow renderingAndroid (Google) Для 60 FPS кадр нужно отрисовать за 16 ms. Если не успеть, кадр пропускается и картинка дёргается (jank)
Slow Sessions (games only)Android (Google) Android vitals считает кадр игры медленным, если он длиннее 50 ms (20 FPS) или 34 ms (30 FPS)
ID cg-gc · Основной ответственный Команда разработки · Разработка клиента
Пока освобождается использованная и уже ненужная память (мусор), вся игра стоит. Характерный признак: микрофризы через равные промежутки.
Почему Каждый кадр создаются и выбрасываются временные строки, массивы и списки → Следствие Когда мусора накапливается много, GC останавливает главный поток и освобождает память → На экране Регулярные микрофризы раз в несколько секунд или десятков секунд
Основной ответственный Команда разработки · Разработка клиента
Команда разработки: задачи
Сократить аллокации (избегать конкатенации строк, LINQ, захвата переменных в лямбдах), использовать пулы объектов, держать включённым инкрементальный GC (по умолчанию с Unity 2020), запускать GC заранее, когда пауза не мешает, например на экране загрузки.
Цифры для ориентира
Обычно от единиц ms до 100 ms за раз, на слабых телефонах и в играх, которые расходуют много памяти, дольше (в эксперименте около 150–170 ms). GC в Unity при каждом запуске проверяет всю кучу, поэтому чем больше памяти занимает игра, тем дольше пауза.
На графике
Всплески с постоянным периодом · время кадра, моменты запуска GC
Где смотреть
В development-сборке смотреть маркеры GC.Collect и GC.Alloc в профайлере Unity. В Unreal смотреть stat GC и stat Hitches (пишет в лог кадры дольше порога t.HitchFrameTimeThreshold)
Подтверждает
В каждом долгом кадре есть участок GC.Collect примерно той же длины, что и всплеск, а всплески повторяются через равные промежутки от нескольких секунд до десятков секунд. В людных местах растёт GC.Alloc на кадр
Опровергает
Если в долгих кадрах нет участка GC, это «Синхронная загрузка и компиляция шейдеров в главном потоке» или «Нагрузка на рендеринг при большом скоплении игроков»
Чем проверить
Нужны логи и метрики игрового сервера или клиента
Подробнее
Типично для клиентов на C#, например на Unity. Главный виновник: код, который каждый кадр заново создаёт строки боевого лога, цифры урона и тексты UI. Если микрофризы бывают только в людных местах, значит, где-то есть код, который создаёт тем больше мусора, чем больше вокруг игроков. Инкрементальный GC собирает мусор понемногу в каждом кадре (в Unity по умолчанию 3 ms), но если мусор появляется быстрее, чем собирается, в итоге всё равно случается одна большая пауза. В Unreal Engine тоже есть собственный GC, который убирает неиспользуемые игровые объекты. С настройками по умолчанию он запускается примерно раз в минуту (зависит от версии движка и настроек) и может давать рывок раз в минуту. В клиентах, где игровая логика написана на скриптовом языке вроде Lua, отдельно работает ещё и GC этого языка.
Источников: 5
Garbage collection modesUnity Инкрементальный GC включён по умолчанию и собирает мусор частями за несколько кадров. Если его выключить, главный поток стоит всё время проверки кучи, вплоть до сотен ms
Profiler markers referenceUnity GC.Collect: время, пока код программы стоит из-за сборки мусора (от менее 1 ms до сотен ms), GC.Alloc: аллокация в управляемой куче
Stat Commands in Unreal EngineEpic Games stat GC (статистика сборки мусора), stat Hitches (пишет в лог кадры дольше t.HitchFrameTimeThreshold)
ID cg-sync-load · Основной ответственный Команда разработки · Разработка клиента
Перед первой отрисовкой новой локации, монстра или эффекта игра останавливается, чтобы прочитать файлы и скомпилировать шейдеры.
Почему Вход в новую локацию, первое появление незнакомого умения, снаряжения или монстра → Следствие Главный поток ждёт чтения файлов и компиляции шейдеров → На экране Фриз на 0,1–1 с только в первый раз, со второго раза всё нормально
В движении и при смене локации, При определённом действии
Ответственные
Основной ответственный Команда разработки · Разработка клиента
Команда разработки: задачи
Загружать асинхронно, подгружать заранее (прогрев), компилировать шейдеры заранее на экране загрузки или при первом запуске, использовать экраны загрузки.
Цифры для ориентира
Компиляция одного шейдера занимает десятки ms, в тяжёлых случаях больше 100 ms. Загрузка текстуры, в зависимости от скорости накопителя, от десятков до сотен ms.
На графике
Всплеск сразу после входа или техработ · число всплесков времени кадра (сразу после патча или обновления драйвера)
Где смотреть
Дважды записать в PresentMon один и тот же маршрут и сравнить первое прохождение со вторым. В development-сборке Unreal включить r.PSOPrecache.Validation и смотреть stat PSOPrecache и строки «PSO PRECACHING MISS» в логе, в Unity смотреть в режиме Timeline профайлера участки загрузки и шейдеров в долгих кадрах
Подтверждает
Всплески на 0,1–1 с только в новых местах и при первом применении умения, во второй раз их нет. Сразу после патча или обновления графического драйвера жалоб много, потом становится меньше
Опровергает
Если всплеск каждый раз в одном и том же месте, кэш шейдеров ни при чём. Если он повторяется при каждом перемещении и только на ПК с медленным накопителем, это «Стриминг ассетов отстаёт из-за медленного накопителя», а если выделенная память GPU заполнена, это «Нехватка видеопамяти (VRAM)»
Чем проверить
Нужны логи и метрики игрового сервера или клиента
Подробнее
На ПК графический драйвер сохраняет однажды собранный шейдер в кэш шейдеров и потом использует его повторно. Поэтому сразу после обновления графического драйвера или выхода патча игры этот кэш становится недействительным, и даже у тех, у кого всё было нормально, какое-то время снова бывают рывки. Типичная жалоба: «после патча дёргается в каждом новом месте».
Источников: 5
Shader loadingUnity При первом использовании варианта шейдера графический драйвер собирает его для GPU, и игра может заметно замереть. Собранный вариант кэшируется, и повторной остановки нет
Direct3D 12 Return CodesMicrosoft D3D12_ERROR_DRIVER_VERSION_MISMATCH: кэш PSO, созданный другой версией драйвера, повторно использовать нельзя (после обновления драйвера нужна перекомпиляция)
PSO Precaching for Unreal EngineEpic Games С включённым r.PSOPrecache.Validation команда stat PSOPrecache показывает статистику пропущенных PSO, а в лог пишется «PSO PRECACHING MISS». Создание PSO во время игры дольше 20 ms (порог по умолчанию) считается рывком (hitch)
ID cg-asset-stream · Основной ответственный Команда разработки · Разработка клиента · Совместно Внешние стороны · Внешние стороны
На медленном накопителе вроде HDD текстуры и модели открытого мира читаются медленнее, чем перемещается игрок. Объекты появляются с опозданием, или игра дёргается, ожидая окончания чтения.
Почему Быстрое перемещение на маунте или телепортом либо вход в людное место, где сразу нужно много новых текстур и моделей → Следствие Медленный накопитель вроде HDD не успевает читать с нужной скоростью, запросы на чтение копятся, а завершения некоторых загрузок главный поток ждёт → На экране Текстуры какое-то время размытые, здания и персонажи появляются с опозданием, а пока игра ждёт чтения, бывают микрофризы и фризы
В движении и при смене локации, При наплыве игроков
Ответственные
Основной ответственный Команда разработки · Разработка клиента · Совместно Внешние стороны · Внешние стороны
Команда разработки: задачи
Стримить асинхронно, чтобы главный поток не ждал чтения, читать заранее с учётом направления и скорости движения, сначала показывать низкое разрешение (мип-уровни) и упрощённые модели, а потом подменять их, при отставании стриминга во время быстрого перемещения ненадолго ограничивать скорость или показывать экран загрузки, указать в минимальных и рекомендуемых требованиях, нужен ли SSD.
Внешние стороны: задачи
Посоветовать игрокам ставить игру на SSD и проверить, не идут ли на том же диске загрузки или антивирусная проверка.
Цифры для ориентира
По данным Microsoft, старые жёсткие диски читают десятки MB в секунду, NVMe SSD несколько GB в секунду, а игры прошлого поколения тратили на стриминг около 50 MB в секунду. Если игра рассчитана на скорость SSD и читает гораздо больше, на HDD чтение легко отстаёт от перемещения.
На графике
Высоко только у некоторых · число всплесков времени кадра (по типу накопителя), задержка чтения с диска
Где смотреть
Во время быстрого перемещения записывать вместе счётчики PhysicalDisk\Avg. Disk sec/Read (среднее время одного чтения) и Current Disk Queue Length в Системном мониторе Windows и время кадра в PresentMon. В development-сборке смотреть stat Streaming и stat AsyncLoad в Unreal, в профайлере Unity предупреждения AssetBundle.asset/allAssets (результат запрошен до окончания загрузки, и главный поток ждёт)
Подтверждает
При быстром перемещении задержка чтения и очередь диска резко растут, и в те же моменты подскакивает время кадра или с опозданием появляются текстуры и объекты. На SSD в той же сцене этого нет
Опровергает
Если диск простаивает, а текстуры размытые, это «Нехватка видеопамяти (VRAM)». Если со второго посещения того же места всё нормально, это «Синхронная загрузка и компиляция шейдеров в главном потоке»
Чем проверить
Проверка на стороне игрока
Подробнее
Если фриз бывает только в первый раз, а дальше всё нормально, это ближе к причине «Синхронная загрузка и компиляция шейдеров в главном потоке». Если он повторяется при каждом перемещении и только на ПК с медленным накопителем, причина именно эта. Размытые текстуры даёт и другая причина, «Нехватка видеопамяти (VRAM)»: текстуры выгружаются из видеопамяти и загружаются обратно. Поэтому ожидание чтения с диска и занятость видеопамяти смотрят вместе. Чтение может замедлять и антивирус: проверка в реальном времени вмешивается каждый раз, когда игра открывает файл.
Источников: 8
DirectStorage is coming to PCMicrosoft Старые жёсткие диски читают десятки MB в секунду, NVMe SSD несколько GB в секунду, бюджет стриминга ассетов в играх прошлого поколения около 50 MB в секунду. Игры с открытым миром на ходу подгружают и выгружают дальние пейзажи
Texture and mesh loadingUnity Синхронная загрузка читает данные и передаёт их на GPU в главном потоке за один кадр, что даёт заметную остановку. Асинхронная загрузка стримит данные на протяжении нескольких кадров
Texture Streaming Overview for Unreal EngineEpic Games Стример повышает и понижает разрешение текстур (мип-уровни) в зависимости от положения камеры. Большая часть расчётов идёт в асинхронных рабочих потоках, а первыми загружаются мип-уровни, видимые на экране
Profiler markers referenceUnity Предупреждение AssetBundle.asset/allAssets: результат запрошен до окончания загрузки, и главный поток останавливается и ждёт
Stat Commands in Unreal EngineEpic Games stat Streaming (память и количество стримящихся текстур), stat AsyncLoad (статистика асинхронной загрузки)
ID cg-crowd · Основной ответственный Команда разработки · Разработка клиента
Когда в кадр попадают сотни игроков, как на осаде или у мирового босса, клиент не справляется уже с самой отрисовкой.
Почему В одном кадре сотни персонажей и наложенные друг на друга эффекты → Следствие Затраты на анимацию, тени, таблички с именами и эффекты растут пропорционально числу игроков → На экране FPS падает с 60 до 15, микрофризы во всех движениях, ввод тоже запаздывает
Основной ответственный Команда разработки · Разработка клиента
Команда разработки: задачи
Упрощать по расстоянию (LOD), ограничить число отображаемых персонажей, добавить опцию упрощённых эффектов, реже обновлять анимацию.
Цифры для ориентира
Даже если на одного персонажа уходит 0,02–0,1 ms, на 300 персонажей это 6–30 ms. При 60 FPS бюджет кадра составляет 16,7 ms, так что уже одно это занимает больше 1/3 бюджета, а в худшем случае превышает его.
На графике
Растёт вслед за онлайном и нагрузкой · время кадра, число персонажей в кадре
Где смотреть
Сравнить в PresentMon время кадра и CPUBusy, GPUBusy до и во время осады или боя с мировым боссом. В development-сборке Unreal смотреть stat Unit (время игрового потока, потока рендеринга и GPU)
Подтверждает
Чем больше персонажей в кадре, тем выше время кадра, а ограничение числа отображаемых персонажей или упрощённые эффекты сразу помогают
Опровергает
Если всплески не зависят от числа персонажей, это «Всплески времени кадра» или «Сборка мусора на клиенте». Если FPS в норме, а запаздывают только движения других игроков, это «Узкое место: обработка пакетов в главном потоке»
Чем проверить
Проверка на стороне игрока
Источников: 4
Introduction to level of detailUnity Без LOD даже мелкие на экране объекты рисуются с той же детализацией, LOD снижает нагрузку на отрисовку
ID cg-net-mainthread · Основной ответственный Команда разработки · Разработка клиента · Совместно Команда разработки · Разработка сервера
Если за кадр обрабатывается только фиксированное число полученных пакетов, при наплыве пакеты всё время переносятся на следующие кадры.
Почему В людном месте приходят тысячи обновлений в секунду → Следствие Главный поток упирается в лимит обработки на кадр и не успевает всё прочитать → На экране Движения других игроков отображаются всё позже и пачками
Основной ответственный Команда разработки · Разработка клиента · Совместно Команда разработки · Разработка сервера
Команда разработки: задачи
Клиент: принимать и разбирать пакеты в отдельном потоке, устаревшие обновления позиции одного объекта схлопывать и применять только последнее. Сервер: в людных местах реже отправлять обновления дальних персонажей, чтобы уменьшить объём трафика.
Цифры для ориентира
Когда необработанные пакеты копятся, отставание на целую секунду набегает за несколько секунд.
На графике
Растёт вслед за онлайном и нагрузкой · число необработанных полученных пакетов, задержка от приёма до применения
Где смотреть
Писать в лог число пакетов, которые клиент не успел обработать за кадр, и задержку от прихода пакета до применения в игре, смотреть вместе с числом игроков поблизости
Подтверждает
В людных местах число необработанных пакетов и задержка применения постоянно растут, а пинг и интервал отправки с сервера в это время в норме
Опровергает
Если задержки применения нет, а сами пакеты приходят поздно, причина на участке сети. Если сильно растёт время кадра, это «Нагрузка на рендеринг при большом скоплении игроков»
Чем проверить
Нужны логи и метрики игрового сервера или клиента
Источников: 2
Actor Priority in Unreal EngineEpic Games Когда пропускной способности не хватает, акторы реплицируются не все и не каждый раз: приоритет определяется по расстоянию до наблюдателя и времени с последней репликации
Replication Graph in Unreal EngineEpic Games В играх с большим числом игроков и реплицируемых объектов (MMORPG и т. п.) объекты группируют по местоположению и отправляют только нужные, иначе CPU сервера становится узким местом
ID cg-no-buffer · Основной ответственный Команда разработки · Разработка клиента · Совместно Команда разработки · Разработка сервера
Если отрисовывать пакеты сервера сразу после получения, джиттер (неравномерность интервалов между пакетами) целиком виден на экране.
Почему Полученная позиция рисуется сразу, или буфер короче джиттера → Следствие На опоздавших пакетах движение останавливается, на пришедших пачкой скачет вперёд → На экране Другие персонажи двигаются рывками
Основной ответственный Команда разработки · Разработка клиента · Совместно Команда разработки · Разработка сервера
Команда разработки: задачи
Клиент: завести буфер интерполяции, автоматически подстраивать его длину под состояние подключения. Сервер: применять компенсацию задержки (проверку попадания с отмоткой времени назад), чтобы попадание засчитывалось правильно, даже если игрок стрелял по картинке, отстающей на длину буфера.
Цифры для ориентира
Обычно длину буфера берут примерно равной двум интервалам отправки пакетов сервером (при 20 пакетах в секунду это 100 ms).
На графике
Высоко с самого начала · интервал прихода пакетов, число опустошений буфера интерполяции
Где смотреть
Записывать на клиенте распределение интервалов прихода пакетов сервера и число кадров, когда следующего снапшота для интерполяции не было и движение остановилось или перешло на экстраполяцию
Подтверждает
Разброс интервалов часто превышает длину буфера интерполяции, каждый раз буфер пустеет, и другие персонажи дёргаются. С более длинным буфером это случается реже
Опровергает
Если буфера достаточно, а рывки остаются, проверить, не сбивается ли сам интервал отправки на сервере (запаздывание тиков)
Чем проверить
Нужны логи и метрики игрового сервера или клиента
Подробнее
Чем длиннее буфер, тем плавнее движение, но тем дальше в прошлом игрок видит противника. Поэтому вместе с буфером используют компенсацию задержки: при проверке попадания сервер отматывает время назад, к «прошлому, которое видел этот игрок».
Physics (Netcode for Entities 6.5)Unity Компенсация задержки: сервер берёт мир коллизий в том состоянии, которое клиент видел на этом тике, и по нему проверяет попадание
ID cg-extrap · Основной ответственный Команда разработки · Разработка клиента
Пока пакеты не приходят, клиент продолжает двигать объект с последней известной скоростью, а обнаружив ошибку, возвращает его назад.
Почему Пакеты перестали приходить, и объект продолжает двигаться с последним направлением и скоростью → Следствие На самом деле противник остановился или сменил направление → На экране Персонаж противника долго идёт в одну сторону, а потом резко переносится в настоящую позицию или проходит сквозь стену. Если пакеты приходят неравномерно, он то убегает вперёд, то его тянет обратно, и движение выглядит дрожащим
Основной ответственный Команда разработки · Разработка клиента
Команда разработки: задачи
Ограничить время экстраполяции (например, 200–250 ms), при ошибке плавно сводить позицию к настоящей.
Цифры для ориентира
При скорости 6 m/s ошибка всего в 300 ms даёт расхождение 1,8 m.
На графике
Случайные всплески · время экстраполяции, расстояние коррекции позиции
Где смотреть
Записывать, сколько времени другие персонажи рисовались по экстраполяции и на какое расстояние поправлялась позиция после прихода нового пакета
Подтверждает
На каждом перерыве в пакетах время экстраполяции растёт без ограничения, а коррекция после него достигает нескольких метров
Опровергает
Если экстраполяция короткая, а телепортация всё равно есть, велики сами потери и задержка пакетов: смотреть подключение и маршрут
Чем проверить
Нужны логи и метрики игрового сервера или клиента
Источников: 2
Interpolation and extrapolation (Netcode for Entities 6.5)Unity Если следующий снапшот не пришёл вовремя, экстраполяция продолжает движение с тем же направлением и скоростью и часто ошибается, поэтому её ограничивают (в Unity по умолчанию 20 тиков, при 60 Hz около 1/3 с)
Peeking into VALORANT's NetcodeRiot Games Если опоздавшие или потерянные данные восполняются догадкой и она неверна, картинка расходится с сервером, и персонаж при коррекции скачет или будто скользит
ID cg-predict · Основной ответственный Команда разработки · Разработка клиента · Совместно Команда разработки · Разработка сервера
Клиент заранее показал движение персонажа игрока, но сервер посчитал иначе, и персонажа утягивает на серверную позицию.
Почему Клиент двигает персонажа до подтверждения сервера (предсказание) → Следствие Сервер по-другому считает коллизии, скорость движения или баффы либо не получает команду → На экране Когда приходит подтверждение, персонажа откидывает назад
Основной ответственный Команда разработки · Разработка клиента · Совместно Команда разработки · Разработка сервера
Команда разработки: задачи
Клиент: использовать тот же код движения, что и на сервере, отправлять ввод с дублированием, сглаживать коррекцию. Сервер: использовать тот же код движения, что и на клиенте, отсеивать дубли ввода по номеру и обрабатывать каждый ввод один раз.
Цифры для ориентира
Расстояние, на которое откидывает персонажа: «время расхождения × скорость движения». Потеря всего нескольких команд даёт 1–3 m.
На графике
Случайные всплески · число серверных коррекций (ошибок предсказания)
Где смотреть
Записывать число коррекций позиции, отправленных сервером, и расстояние коррекции. В Unreal считать коррекции ClientAdjustPosition от сервера, в Unity Netcode for Entities считать, сколько раз из-за ошибки предсказания состояние возвращалось назад и пересчитывалось
Подтверждает
Коррекции скапливаются в моменты жалоб на откидывание назад, а с определёнными баффами, на определённых участках ландшафта или при умениях перемещения коррекция раз за разом получается большой
Опровергает
Если коррекции скапливаются только при больших потерях, дело в потере пакетов ввода (подключение). Если коррекций нет, а утягивает только других персонажей, это «Чрезмерная экстраполяция (dead reckoning)»
Чем проверить
Нужны логи и метрики игрового сервера или клиента
Источников: 3
Introduction to prediction (Netcode for Entities 6.5)Unity Клиент и сервер предсказывают одним и тем же кодом симуляции. Если состояние расходится с серверным (ошибка предсказания), клиент возвращается назад и пересчитывает, и коррекция становится видна
ID cg-fixed-step · Основной ответственный Команда разработки · Разработка клиента
После одной остановки игра разом досчитывает накопившиеся шаги и из-за этого снова отстаёт.
Почему Симуляция идёт с фиксированным шагом, и игра один раз останавливается → Следствие Накопившиеся шаги считаются разом в одном кадре → На экране Долгие кадры идут один за другим, и картинка скачет, или срабатывает лимит, и мир замедляется
Основной ответственный Команда разработки · Разработка клиента
Команда разработки: задачи
Ограничить число догоняющих шагов за кадр, остаток времени закрывать интерполяцией.
На графике
Случайные всплески · время кадра, число фиксированных шагов за кадр
Где смотреть
В профайлере development-сборки смотреть вместе время кадра и число фиксированных шагов за кадр (в Unity число маркеров фазы FixedUpdate, например FixedBehaviourUpdate)
Подтверждает
После одного долгого кадра идёт череда долгих кадров с несколькими шагами в каждом, а при достижении лимита (Maximum Allowed Timestep в Unity) игровое время течёт медленнее реального
Опровергает
Если долгий кадр одиночный, это «Всплески времени кадра» или «Сборка мусора на клиенте»
Чем проверить
Нужны логи и метрики игрового сервера или клиента
Подробнее
Типичный пример фиксированного шага: физика Unity (FixedUpdate), по умолчанию 0,02 с, то есть 50 раз в секунду. Верхний предел для догоняющих шагов задаёт параметр Maximum Allowed Timestep в настройках Time (максимальное время, которое можно догнать за один кадр, по умолчанию около 0,33 с). Если кадр длиннее, лишнее время отбрасывается, и игровые часы на столько же отстают от реальных.
Handling variation in timeUnity Maximum Allowed Timestep по умолчанию 1/3 с (0,3333333): даже если игра простояла 1 секунду, игровое время продвинется только на 0,333 с. Этот предел разрывает порочный круг, когда догоняющие шаги снова замедляют игру
Profiler markers referenceUnity FixedBehaviourUpdate: участок выполнения MonoBehaviour.FixedUpdate, маркеры физики вызываются в фазе FixedUpdate
ID cg-clock · Основной ответственный Команда разработки · Разработка клиента
Если клиент неверно оценивает серверное время, сбиваются момент интерполяции и проверка кулдаунов.
Почему Время сервера синхронизируется один раз при входе и не корректируется, даже когда меняется пинг → Следствие Момент интерполяции и время окончания кулдауна расходятся с сервером → На экране Противник иногда дёргается, умение отклоняется, хотя кулдаун уже прошёл
Основной ответственный Команда разработки · Разработка клиента
Команда разработки: задачи
Регулярно синхронизировать время (измерять время пути туда и обратно и корректировать), подводить часы постепенно, без резких скачков, измерять прошедшее время монотонными часами (monotonic clock) вместо системного времени ПК.
На графике
Плавный рост · ошибка оценки серверного времени
Где смотреть
Регулярно записывать разницу между серверным временем, которое оценил клиент, и серверным временем (номером тика), которое сервер прислал в пакете
Подтверждает
Ошибка растёт со временем после входа или скачком меняется в момент подводки часов ПК, и примерно тогда же растёт число жалоб на отклонённые умения и рывки
Опровергает
Если ошибка остаётся небольшой, а умения всё равно отклоняются, дело в решении сервера или задержке
Чем проверить
Нужны логи и метрики игрового сервера или клиента
Подробнее
Если прошедшее время измерять по дате и времени ПК (wall clock), игровое время скачет в момент, когда Windows подводит часы по интернет-времени или пользователь меняет время вручную. Прошедшее время нужно измерять монотонными часами, которые никогда не идут назад (monotonic clock, Stopwatch и т. п.).
Acquiring high-resolution time stampsMicrosoft QueryPerformanceCounter (его использует Stopwatch): часы для измерения прошедшего времени, не синхронизируемые с внешним временем. Системное время нужно только тогда, когда требуется время UTC
Time synchronization (Netcode for Entities 6.5)Unity Серверное время оценивается по времени пути туда и обратно, а подстройка идёт за счёт небольшого изменения скорости хода часов, без резких переводов времени
ID cg-float-time · Основной ответственный Команда разработки · Разработка клиента
Если игровое время хранится в формате с плавающей точкой низкой точности (float), то чем дольше работает клиент, тем хуже разрешение времени (наименьшая различимая разница во времени), и движения и эффекты начинают дрожать.
Почему Время с запуска игры накапливается во float или как есть передаётся в шейдеры → Следствие Чем дольше работает клиент, тем больше наименьшая разница, которую может выразить float → На экране Только в клиенте, проработавшем несколько дней, дрожат персонажи, анимации и эффекты с бегущей текстурой, а после перезапуска всё нормально
Основной ответственный Команда разработки · Разработка клиента
Команда разработки: задачи
Хранить прошедшее время в double (64 бита) или в целых числах, время для шейдеров периодически сбрасывать (зацикливать), гонять многодневные автотесты.
Цифры для ориентира
У 32-битного float чуть больше 7 значащих цифр, поэтому через сутки работы (около 86 400 с) разрешение времени становится около 8 ms, то есть примерно половиной кадра при 60 FPS (16,7 ms), а через неделю около 60 ms, что уже больше одного кадра.
На графике
Плавный рост · жалобы на дрожание в зависимости от времени работы клиента
Где смотреть
Вместе с жалобой на дрожание узнавать, сколько клиент работал без перезапуска, и сравнивать до и после перезапуска. На стороне разработки: тест, в котором время старта игры выставлено на несколько дней назад
Подтверждает
Дрожание есть только в клиентах, проработавших несколько дней, пропадает после перезапуска и тем сильнее, чем дольше работает клиент
Опровергает
Если дрожит сразу после запуска, это «Буфер интерполяции отсутствует или слишком короткий» или «Разрешение таймера»
Чем проверить
Проверка на стороне игрока
Подробнее
Особенно часто встречается в мобильных MMO, где игроки включают автобой и не выключают игру по несколько дней. Time.time в Unity тоже float, поэтому в Unity есть отдельное значение Time.timeAsDouble в double, и рекомендуется использовать его.
Источников: 2
Time.timeAsDoubleUnity Версия Time.time в double: при долгой работе точнее float, поэтому в большинстве случаев рекомендуется она
ID cg-vsync · Основной ответственный Команда разработки · Разработка клиента · Совместно Внешние стороны · Внешние стороны
Отрисованные GPU кадры по несколько штук ждут в очереди и выводятся в такт монитору, поэтому ввод доходит до экрана с опозданием.
Почему Графический драйвер заранее держит в очереди 1–3 кадра → Следствие Ввод доходит до экрана на столько же позже → На экране Пинг низкий, а управление ватное и запаздывает
Основной ответственный Команда разработки · Разработка клиента · Совместно Внешние стороны · Внешние стороны
Команда разработки: задачи
Поддержать режим низкой задержки, сократить очередь кадров, дать опцию ограничения FPS чуть ниже частоты обновления, на телефонах включить frame pacing.
Внешние стороны: задачи
Посоветовать игрокам с монитором с переменной частотой обновления ставить ограничение FPS чуть ниже частоты обновления и включить режим низкой задержки в графическом драйвере.
Цифры для ориентира
При 60 Hz каждый кадр в очереди добавляет 16,7 ms. Если CPU работает быстрее GPU или частоты экрана и очередь из трёх кадров (по умолчанию в DirectX 11) заполнена, добавляется 50 ms. При V-Sync с двойной буферизацией кадр, на который ушло 17 ms, ждёт следующего обновления экрана (33,3 ms), а пока на экране ещё раз показывается предыдущий кадр.
На графике
Высоко с самого начала · задержка от ввода до экрана
Где смотреть
Сравнивать в PresentMon MsClickToPhotonLatency и MsAllInputToPhotonLatency (от ввода мышью или клавиатурой до вывода на экран) и DisplayLatency, переключая V-Sync, режим низкой задержки и ограничение FPS. MsPCLatency (от получения ввода ПК до отправки на экран) записывается, только если игра отправляет события PC Latency
Подтверждает
С включённым V-Sync или без ограничения FPS эта задержка растёт на один-два кадра (десятки ms), а в режиме низкой задержки или с ограничением чуть ниже частоты обновления уменьшается. Пинг не меняется
Опровергает
Если задержка внутри ПК низкая, а управление всё равно запаздывает, это «Задержка дисплея, устройств ввода и генерации кадров». Если высокий пинг, дело в сети
Чем проверить
Проверка на стороне игрока
Подробнее
V-Sync (вертикальная синхронизация) выводит новый кадр только в момент, когда монитор обновляет изображение. Разрывы картинки пропадают, но ввод запаздывает на время ожидания этого момента, а если FPS опускается ниже 60, частота скачет между 60 и 30 и появляются микрофризы. Монитор с переменной частотой обновления подстраивает обновление под готовность кадра и сокращает это ожидание. На телефонах происходит то же самое. Если игра на 30 FPS не может равномерно выводить кадры на экран 60 Hz, в среднем выходит 30 FPS, но кадры держатся на экране неравномерно, например 49, 16 и 33 ms, и появляются микрофризы (пример из документации Android для разработчиков). Помогает библиотека Frame Pacing для Android (выравнивание интервалов вывода кадров) или такая же опция движка.
Reduce latency with DXGI 1.3 swap chainsMicrosoft Present блокируется, пока очередь не освободится, и от отрисовки до показа проходит почти на кадр больше. Сократить это помогает swap chain с ожиданием (waitable swap chain)
Frame Pacing libraryAndroid (Google) На экране 60 Hz при отсутствии нового кадра снова показывается предыдущий. Пример игры на 30 FPS, у которой время кадра скачет: 49, 16, 33 ms
PresentMon Capture Application (README-CaptureApplication.md)Intel MsPCLatency (от получения ввода ПК до отправки на экран), MsClickToPhotonLatency (от клика мышью до экрана), MsAllInputToPhotonLatency (от ввода с клавиатуры или мыши до экрана), DisplayLatency (от отправки кадра до вывода на монитор)
ID cg-leak · Основной ответственный Команда разработки · Разработка клиента
Чем дольше работает игра, тем больше памяти она занимает, всё сильнее тормозит и в итоге принудительно закрывается.
Почему При переходах между локациями текстуры, UI и эффекты не освобождаются → Следствие GC запускается чаще, памяти ОС не хватает, начинается своп → На экране Через несколько часов игры микрофризы нарастают, потом игра принудительно закрывается (игроку это кажется дисконнектом)
Основной ответственный Команда разработки · Разработка клиента
Команда разработки: задачи
Замерять расход памяти при смене локаций, находить и исправлять неосвобождаемые текстуры, UI и эффекты, гонять долгие автотесты (soak-тесты).
На графике
Плавный рост · память процесса игры
Где смотреть
Несколько часов записывать в Системном мониторе счётчик Process(игра)\Private Bytes. На мобильных смотреть причину завершения в ApplicationExitInfo на Android (REASON_LOW_MEMORY) и отчёты jetsam на iOS
Подтверждает
С каждым переходом между локациями память растёт и не возвращается, и чем дольше работает игра, тем больше микрофризов и принудительных закрытий
Опровергает
Если память стабильна, а с долгой работой появляется только дрожание, это «Потеря точности времени во float»
Чем проверить
Проверка на стороне игрока
Подробнее
Телефоны обычно держатся за счёт сжатия памяти. Если памяти всё равно не хватает, ОС сразу закрывает игру (вылет). Чем меньше ОЗУ у устройства, тем раньше это происходит.
Источников: 4
Memory allocation among processesAndroid (Google) Android держится за счёт сжатия памяти в zRAM, а когда памяти не хватает, low memory killer завершает процессы. Если завершено приложение на переднем плане, это выглядит как краш
Identifying high-memory use with jetsam event reportsApple Если нехватка памяти не проходит, iOS принудительно завершает приложения (jetsam). Приложение, превысившее свой лимит памяти, становится кандидатом на завершение
ApplicationExitInfoAndroid (Google) REASON_LOW_MEMORY: процесс приложения завершён системным low memory killer (устройства без поддержки сообщают REASON_SIGNALED и SIGKILL)
ID cg-crash · Основной ответственный Команда разработки · Разработка клиента · Совместно Внешние стороны · Внешние стороны
Игра закрывается из-за необработанной ошибки. Игроку это кажется дисконнектом, хотя сервер работает нормально.
Почему Обращение по нулевой ссылке, нехватка памяти, ошибка графического драйвера → Следствие Процесс игры принудительно завершается → На экране Жалобы «вылетел из игры». У остальных в это же время всё в порядке
Основной ответственный Команда разработки · Разработка клиента · Совместно Внешние стороны · Внешние стороны
Команда разработки: задачи
Собирать краш-репорты, вести статистику по устройствам и драйверам, исправлять сначала самые частые ошибки.
Внешние стороны: задачи
Если краши скапливаются на определённой версии графического драйвера, посоветовать игрокам обновить драйвер.
На графике
Высоко только у некоторых · число крашей (по устройствам, графическим драйверам и сборкам)
Где смотреть
Смотреть краш-репорты и частоту крашей в Android vitals по устройствам, драйверам и сборкам. На ПК игрока смотреть в Просмотре событий в журнале «Приложение» события с кодом 1000 (имя сбойного модуля) и записи «Display driver stopped responding and has recovered»
Подтверждает
На момент жалобы на дисконнект есть запись о краше, а другие игроки на том же сервере в это время играют нормально. Краши скапливаются на определённых устройствах, версиях драйвера или модулях
Опровергает
Если записи о краше нет и просто оборвалось соединение, это «Истечение записи в таблице NAT» или проблема с подключением
Чем проверить
Нужны логи и метрики игрового сервера или клиента
Источников: 3
CrashesAndroid (Google) Краш: неожиданное завершение приложения из-за необработанного исключения или сигнала (SIGSEGV и т. п.), статистика собирается в Android vitals в Play Console
ID cg-anticheat · Основной ответственный Команда разработки · Разработка клиента · Совместно Команда разработки · Разработка сервера
Модуль защиты от взлома работает вместе с игрой и периодически выполняет проверки. Если проверка тяжёлая или хартбит (периодический сигнал «я жив») с сервером защиты запаздывает, появляются микрофризы или дисконнект.
Почему Модуль защиты периодически проверяет память игры, запущенные программы и драйверы → Следствие Во время проверки игровой поток стоит, или хартбит не уходит вовремя → На экране Рывки через равные промежутки, в тяжёлых случаях дисконнект с сообщением об ошибке защиты
С постоянным периодом, Сразу после входа или техработ, Изредка, случайно
Ответственные
Основной ответственный Команда разработки · Разработка клиента · Совместно Команда разработки · Разработка сервера
Команда разработки: задачи
Клиент: выполнять тяжёлые проверки вне игрового потока небольшими порциями, сравнивать статистику микрофризов и вылетов по версиям модуля защиты (если они скапливаются сразу после обновления, сообщить разработчику модуля). Сервер: допускать один-два опоздавших хартбита.
Цифры для ориентира
Лёгкая проверка обычно занимает меньше 1 ms, а тяжёлая проверка в игровом потоке, в зависимости от реализации, может забирать за раз от десятков до сотен ms.
На графике
Всплески с постоянным периодом · время кадра, число киков античитом
Где смотреть
Измерить интервал между всплесками времени кадра в PresentMon и собрать причины киков античитом, полученные сервером (в EOS это AuthenticationFailed / Authentication Timed Out и др. в ClientActionReason), по версиям модуля защиты и конфигурациям
Подтверждает
Короткие остановки повторяются через равные промежутки независимо от происходящего в игре, а сразу после обновления модуля защиты на определённых конфигурациях растут микрофризы и кики по таймауту аутентификации
Опровергает
Если интервал одинаковый на всех конфигурациях и не зависит от версии модуля защиты, это «Сборка мусора на клиенте» или «Фоновые процессы занимают CPU»
Чем проверить
Нужны логи и метрики игрового сервера или клиента
Подробнее
Модуль защиты встроен глубоко в ОС в виде драйвера и может конфликтовать с антивирусом, оверлеями и модулями защиты других игр. Если сразу после обновления модуля защиты жалобы на микрофризы и вылеты скапливаются на определённых конфигурациях, его стоит заподозрить первым.
Источников: 2
Using the Anti-Cheat InterfacesEpic Games Если сервер не получает сообщения античита от клиента за заданное время (RegisterTimeout), он кикает игрока по таймауту аутентификации (частая причина: клиент завис на загрузке). Если проблема в недавнем обновлении модуля, возвращаются к предыдущей версии модуля
ID co-background · Основной ответственный Внешние стороны · Внешние стороны · Совместно Команда разработки · Разработка клиента
Когда ядра заняты антивирусной проверкой, обновлением Windows, программой для стримов или видео в браузере, игровой поток не получает процессорного времени и ждёт.
Почему Другие программы надолго занимают ядра CPU → Следствие Игровой поток ждёт, пока планировщик выделит ему ядро → На экране Кадры запаздывают, обработка полученных пакетов тоже
Основной ответственный Внешние стороны · Внешние стороны · Совместно Команда разработки · Разработка клиента
Команда разработки: задачи
Настроить приоритет игровых потоков, писать в лог, снятый в момент микрофризов, общую загрузку CPU на ПК, чтобы отличать случаи, когда виноваты другие программы.
Внешние стороны: задачи
Посоветовать игрокам включить игровой режим Windows и закрывать во время игры ненужные программы (антивирусную проверку, обновление Windows, программу для стримов, видео в браузере).
Цифры для ориентира
Windows обычно выделяет потоку ядро на срок от единиц до десятков ms за раз. Если планировщик хотя бы раз отложит игровой поток, кадр потерян.
На графике
Случайные всплески · общая загрузка CPU на ПК, время кадра
Где смотреть
Смотреть столбец «ЦП» на вкладке «Процессы» Диспетчера задач и записывать счётчик Processor Information(_Total)\% Processor Time в Системном мониторе вместе со временем кадра в PresentMon. Если подозревается антивирус, записать трассу командой New-MpPerformanceRecording и посмотреть в Get-MpPerformanceReport файлы и процессы с самым долгим сканированием
Подтверждает
В моменты микрофризов подскакивает загрузка CPU другими программами (антивирусная проверка, обновление, программа для стримов), или файлы из папки игры оказываются в начале списка по времени сканирования. Если закрыть эту программу или добавить игру в исключения, проблема пропадает
Опровергает
Если загрузка CPU низкая, а весь экран дёргается и звук хрипит, это «Энергосбережение NIC и проблемы драйверов» (задержки DPC)
Чем проверить
Проверка на стороне игрока
Подробнее
Windows даёт программе в активном окне (на переднем плане) чуть более высокий приоритет, но если задач больше, чем ядер, ждёт и игра. Антивирус чаще мешает через «защиту в реальном времени», чем нагрузкой на CPU. Он проверяет файл каждый раз, когда игра его открывает, и остановки при чтении ассетов становятся длиннее.
Источников: 6
MultitaskingMicrosoft Windows выделяет каждому потоку квант времени и по его окончании переключается на следующий поток, квант около 20 ms (зависит от ОС и CPU)
Priority BoostsMicrosoft Процессу активного окна (переднего плана) приоритет поднимается как минимум до уровня фоновых процессов
Performance analyzer for Microsoft Defender AntivirusMicrosoft Запись через New-MpPerformanceRecording, затем Get-MpPerformanceReport показывает файлы, пути и процессы, которые сильнее всего влияют на время сканирования
ID co-power · Основной ответственный Внешние стороны · Внешние стороны · Совместно Команда разработки · Разработка клиента
Из-за работы ноутбука от батареи, режима энергосбережения на телефоне или нагрева устройства падает скорость CPU и GPU. Характерный признак перегрева: сначала всё нормально, а тормоза начинаются заметно позже.
Почему Устройство работает от батареи или в режиме энергосбережения либо нагрелось → Следствие Частоты CPU и GPU снижаются на 30–50% в зависимости от устройства → На экране В режиме энергосбережения сразу, а при перегреве спустя от нескольких минут до примерно 20 минут игры FPS падает и появляются микрофризы
Основной ответственный Внешние стороны · Внешние стороны · Совместно Команда разработки · Разработка клиента
Команда разработки: задачи
Автоматически подстраивать графические настройки, сдерживать нагрев ограничением FPS, заранее снижать настройки по уровню нагрева, который сообщает ОС (thermalState в iOS, API теплового состояния в Android), на ноутбуках с двумя графическими чипами пометить исполняемый файл, чтобы использовалась дискретная графика (экспортировать NvOptimusEnablement и AmdPowerXpressRequestHighPerformance).
Внешние стороны: задачи
Посоветовать игрокам выключить энергосбережение, а ноутбук держать подключённым к сети. На жалобы «ноутбук мощный, а FPS низкий» попросить проверить, на каком графическом чипе работает игра, и назначить для игры высокопроизводительный GPU в настройках графики Windows.
На графике
Плавный рост · FPS, частоты CPU и GPU
Где смотреть
Записывать в PresentMon CPUFrequency, GPUFrequency, CPUTemperature и GPUTemperature вместе со временем кадра в течение 20–30 минут, а по столбцу «Ядро ГП» на вкладке «Процессы» Диспетчера задач проверить, на каком графическом чипе работает игра. На мобильных записывать вместе с FPS тепловой API Android (getThermalHeadroom, тепловое состояние) и thermalState в iOS
Подтверждает
FPS падает с того момента, когда после роста температуры снижаются частоты, или частоты низкие только от батареи и в режиме энергосбережения. Либо игра работает на встроенной графике
Опровергает
Если частоты и температура не меняются, а FPS падает, это «Фоновые процессы занимают CPU» или «Утечка памяти на клиенте»
Чем проверить
Проверка на стороне игрока
Подробнее
Ноутбуки с двумя графическими чипами ради экономии энергии иногда запускают игру на медленной встроенной графике. На жалобу «ноутбук мощный, а FPS низкий» первым делом проверяют, на каком графическом чипе работает игра.
Источников: 5
Thermal APIAndroid (Google) Устройство держит высокую производительность ограниченное время, затем из-за нагрева включается троттлинг. Рекомендуется заранее снижать нагрузку по тепловому состоянию
thermalStateApple Текущий уровень нагрева, который сообщает iOS. При повышении уровня приложение должно сокращать потребление ресурсов
ID co-timer · Основной ответственный Команда разработки · Разработка клиента
Стандартный таймер Windows работает с шагом 15,6 ms, поэтому «подождать всего 1 ms» на деле растягивается до следующего тика таймера, то есть до 15,6 ms.
Почему Ограничение FPS и отправка пакетов сделаны через Sleep (короткое ожидание) → Следствие ОС будит поток только с шагом 15,6 ms → На экране Интервалы между кадрами и между отправками ввода неравномерные
Основной ответственный Команда разработки · Разработка клиента
Команда разработки: задачи
Использовать таймеры высокого разрешения, выдерживать интервалы кадров по событиям или V-Sync вместо Sleep.
Цифры для ориентира
С шагом 15,6 ms интервал 16,7 ms выдержать нельзя, поэтому интервал между кадрами прыгает между 15,6 ms и 31,2 ms.
На графике
Высоко с самого начала · распределение интервалов между кадрами
Где смотреть
Смотреть распределение MsBetweenPresents (интервал между кадрами) в PresentMon и пункт «Platform Timer Resolution» в отчёте powercfg /energy (процессы, изменившие разрешение таймера)
Подтверждает
Интервалы между кадрами скапливаются на значениях, кратных 15,6 ms (15,6 ms и 31,2 ms), и игра не запрашивает более высокое разрешение таймера
Опровергает
Если интервалы разбросаны равномерно, дело скорее в причине «Фоновые процессы занимают CPU» или в тяжёлых кадрах, чем в таймере
Чем проверить
Проверка на стороне игрока
Подробнее
В старых версиях Windows, если одна программа переключала таймер на 1 ms, это действовало на все программы. Отсюда и поверье «с открытым браузером игра идёт плавнее». Начиная с Windows 10 версии 2004 настройка действует только на запросившую программу, а Windows 11 может не выполнять запрос окна, которое свёрнуто или полностью перекрыто и не издаёт звука.
Источников: 6
_WDF_TIMER_CONFIG (wdftimer.h)Microsoft Точность обычного таймера равна интервалу системного тика, по умолчанию 15,6 ms, у таймера высокого разрешения 1 ms
timeBeginPeriod function (timeapi.h)Microsoft До Windows 10 версии 2004 настройка глобальная, начиная с неё действует только на запросивший процесс. Windows 11 не гарантирует высокое разрешение процессам со свёрнутыми или перекрытыми окнами
Results for the Idle Energy Efficiency AssessmentMicrosoft Разрешение системного таймера по умолчанию 15,6 ms, процессы, изменившие его, видны в пункте «Platform Timer Resolution» отчёта об энергопотреблении
Powercfg command-line optionsMicrosoft powercfg /energy: анализирует систему и создаёт отчёт об энергопотреблении (HTML)
ID co-mobile-bg · Основной ответственный Команда разработки · Разработка клиента · Совместно Команда разработки · Разработка сервера
Если ненадолго свернуть игру, чтобы посмотреть уведомление, через несколько секунд ОС приостанавливает приложение (suspend), а сервер тем временем отключает игрока.
Почему Игру свернули, чтобы прочитать сообщение или ответить на звонок → Следствие Движок останавливает игровой цикл, а вскоре ОС приостанавливает и само приложение, и его сетевую активность → На экране По возвращении уже дисконнект и переподключение
Основной ответственный Команда разработки · Разработка клиента · Совместно Команда разработки · Разработка сервера
Команда разработки: задачи
Клиент: по возвращении сразу автоматически переподключаться по токену сессии, не дожидаясь старого соединения (продолжать без повторного входа), и разом получать актуальное состояние. Сервер: когда хартбиты прекращаются, закрывать соединение, но ещё недолго сохранять сессию персонажа (окно переподключения, без немедленного кика) и при переподключении в это окно подхватывать её по токену сессии.
Цифры для ориентира
Движок обычно останавливается в момент сворачивания. iOS приостанавливает приложение через несколько секунд, а если оно запросило дополнительное время, обычно в пределах десятков секунд. Android 14 и новее замораживает (freeze) ушедшее с экрана приложение примерно через 10 секунд.
На графике
Массовый обрыв соединений · число обрывов (таймаут хартбита), записи о приостановке приложения
Где смотреть
Сопоставить по ID сессии время приостановки и возврата приложения из лога клиента (в Unity OnApplicationPause) с причиной и временем обрыва на сервере. На Android смотреть также причину завершения процесса в ApplicationExitInfo (REASON_LOW_MEMORY и др.)
Подтверждает
Незадолго до обрыва по таймауту хартбита на сервере клиент ушёл в приостановку, а сразу после возврата переподключился
Опровергает
Если обрыв случился, пока приложение было на экране, это «Истечение записи в таблице NAT», «Общий IP провайдера (CGNAT)» или «Переключение Wi-Fi ↔ LTE/5G»
Чем проверить
Нужны логи и метрики игрового сервера или клиента
Подробнее
Если памяти не хватает, телефон может и вовсе завершить свёрнутую игру. Поэтому после перехода в камеру, приложение для оплаты или авторизации игра запускается заново. На слабых устройствах это бывает чаще.
Источников: 5
Extending your app’s background execution timeApple При уходе в фон на applicationDidEnterBackground даётся 5 секунд, затем приложение приостанавливается. Если нужно больше, время запрашивают через beginBackgroundTask (остаток виден в backgroundTimeRemaining)
Cached apps freezerAndroid (Google) Android 14 и новее замораживает процесс приложения, перешедший в кэшированное состояние, через 10 секунд. После заморозки все потоки стоят
Application.runInBackgroundUnity По умолчанию false, и в фоне игра останавливается. На Android игра в фоне останавливается при любой настройке, iOS эту настройку игнорирует
ApplicationExitInfoAndroid (Google) REASON_LOW_MEMORY: процесс приложения завершён системным low memory killer (устройства без поддержки сообщают REASON_SIGNALED и SIGKILL)
ID co-netswitch · Основной ответственный Команда разработки · Разработка сервера · Совместно Команда разработки · Разработка клиента, Команда инфраструктуры · Сетевая инфраструктура
Когда игрок выходит из дома, Wi-Fi пропадает и устройство переключается на LTE или 5G. IP-адрес меняется, и старое соединение перестаёт работать.
Почему Сигнал Wi-Fi слабеет, и устройство переключается на мобильную сеть → Следствие IP-адрес меняется, и через соединение, открытое со старого адреса, обмениваться данными больше нельзя → На экране Короткий фриз, затем дисконнект или переподключение
Основной ответственный Команда разработки · Разработка сервера · Совместно Команда разработки · Разработка клиента, Команда инфраструктуры · Сетевая инфраструктура
Команда разработки: задачи
Сервер: по токену сессии узнавать того же игрока и после смены адреса, а соединение со старого адреса сразу закрывать, рассмотреть протоколы, которые переживают смену адреса (например, миграцию соединения в QUIC). Клиент: заметив смену сети, сразу переподключаться по токену сессии, не дожидаясь таймаута хартбита.
Команда инфраструктуры: задачи
Если используется миграция соединения QUIC, настроить балансировщик нагрузки так, чтобы он выбирал сервер по ID соединения вместо адреса и порта (при выборе по адресу и порту пакеты с нового адреса уходят на другой сервер).
На графике
Массовый обрыв соединений · число обрывов и переподключений, смена IP при переподключении
Где смотреть
Найти в логе подключений сервера переподключения с тем же токеном сессии, но с другого IP, и сопоставить их со временем колбэка смены сети по умолчанию на клиенте (registerDefaultNetworkCallback)
Подтверждает
IP при переподключении сразу после обрыва меняется с диапазона Wi-Fi (домашнего подключения) на диапазон мобильного оператора или наоборот, а прямо перед этим приходит колбэк смены сети
Опровергает
Если IP не изменился, а обрыв был, это «Хендовер между базовыми станциями (в движении)» или «Слабый сигнал мобильной сети и мёртвые зоны»
Чем проверить
Нужны логи и метрики игрового сервера или клиента
Источников: 3
Read network stateAndroid (Google) При смене сети по умолчанию новые соединения идут через новую сеть, а соединения через прежнюю в итоге принудительно рвутся. Смену отслеживают через registerDefaultNetworkCallback
RFC 9000: QUIC: A UDP-Based Multiplexed and Secure TransportIETF Благодаря ID соединения оно сохраняется при смене IP-адреса и порта (глава 9). Балансировщик, распределяющий только по адресу и порту, может отправить пакеты с нового адреса на другой сервер (раздел 5.2.3)
ID co-security · Основной ответственный Внешние стороны · Внешние стороны · Совместно Команда разработки · Разработка клиента
Когда антивирус или файрвол проверяет каждый пакет, задержка растёт, а при слишком строгих правилах игра принимается за атаку и блокируется.
Почему Защитная программа проверяет каждый входящий и исходящий пакет → Следствие К каждому пакету добавляется задержка, а если проверка не успевает, пакеты отбрасываются → На экране Пинг беспорядочно скачет, или подключение блокируется
Основной ответственный Внешние стороны · Внешние стороны · Совместно Команда разработки · Разработка клиента
Команда разработки: задачи
Вести список совместимости с защитными программами, при установке добавлять игру в исключения брандмауэра Windows.
Внешние стороны: задачи
Посоветовать игрокам добавить игру в исключения защитной программы. Если программа принимает игру за атаку, попросить её разработчика исправить ложное срабатывание.
Цифры для ориентира
В норме проверка пакета занимает меньше 1 ms. Проблемы начинаются, когда модуль проверки не успевает, содержит ошибку или принимает игровой трафик за атаку.
На графике
Высоко только у некоторых · RTT и ошибки подключения (по игрокам)
Где смотреть
Сравнить, ненадолго выключив защитную программу или добавив игру в исключения. В Windows, если в политике аудита включить Audit Filtering Platform Connection и Audit Filtering Platform Packet Drop, в журнале безопасности появляются события 5157 (соединение заблокировано) и 5152 (пакет заблокирован), а число отброшенных пакетов видно в Системном мониторе по счётчику WFPv4\Packets Discarded/sec
Подтверждает
Есть записи о блокировке соединений или пакетов к адресу игрового сервера, или с выключенной защитной программой скачки пинга и ошибки входа пропадают
Опровергает
Если то же самое на других устройствах в том же доме независимо от защитной программы, дело в роутере или подключении
Чем проверить
Проверка на стороне игрока
Источников: 6
About Windows Filtering PlatformMicrosoft Архитектура, в которой хуки сетевого стека Windows и движок фильтрации пропускают или блокируют пакеты. Сторонние разработчики защитных программ могут встраивать свои модули фильтрации (callout)
Windows Firewall RulesMicrosoft По умолчанию входящие соединения блокируются, поэтому приложению нужно правило-исключение. Обычно его создаёт установщик приложения
ID co-rcvbuf · Основной ответственный Команда разработки · Разработка клиента
Если игра занята и поздно забирает пакеты из сокета (интерфейса ОС для приёма и отправки данных по сети), буфер ОС переполняется.
Почему Кадры запаздывают, и игра поздно читает сокет → Следствие Буфер приёма ОС заполняется: UDP-пакеты отбрасываются, а TCP уменьшает окно приёма и заставляет отправителя остановиться → На экране Телепортация (UDP) или перемотка (TCP)
Основной ответственный Команда разработки · Разработка клиента
Команда разработки: задачи
Вынести приём в отдельный поток, подобрать размер буфера (SO_RCVBUF).
Цифры для ориентира
Буфер приёма по умолчанию, в зависимости от ОС и настроек, от десятков до сотен KB. Обновления в людном месте могут достигать сотен KB в секунду.
На графике
Растёт вслед за онлайном и нагрузкой · число UDP-пакетов, отброшенных буфером приёма, время кадра
Где смотреть
Записывать в Системном мониторе Windows Microsoft Winsock BSP\Dropped Datagrams (число UDP-пакетов, отброшенных из-за нехватки буфера приёма сокета) и UDPv4\Datagrams Received Errors вместе со временем кадра, а в игре считать пропуски в порядковых номерах полученных пакетов
Подтверждает
В людных местах или сразу после долгого кадра растёт Dropped Datagrams, и в те же моменты появляются пропуски в номерах пакетов. Потерь на линии связи в это время нет
Опровергает
Если Dropped Datagrams не растёт, а номера всё равно пропадают, это потери на маршруте
Чем проверить
Проверка на стороне игрока
Источников: 5
socket(7) — Linux manual pageLinux man-pages SO_RCVBUF задаёт максимальный размер буфера приёма сокета, значение по умолчанию берётся из rmem_default, максимум из rmem_max (Android тоже работает на ядре Linux)
RFC 9293: Transmission Control Protocol (TCP)IETF Поле окна TCP показывает, сколько ещё байт готов принять получатель. При 0 отправитель только шлёт пробы нулевого окна (zero window probe) и ждёт
Low Latency Workloads Management and OperationsMicrosoft Dropped Datagrams и Dropped Datagrams/sec из набора счётчиков Microsoft Winsock BSP: число UDP-пакетов, отброшенных потому, что они приходили быстрее, чем приложение успевало их обрабатывать, или не хватило буфера приёма сокета
ID co-swap · Основной ответственный Внешние стороны · Внешние стороны · Совместно Команда разработки · Разработка клиента
Если вместе с игрой открыты десятки вкладок браузера, ОС выгружает часть памяти игры на диск.
Почему Оперативной памяти в целом не хватает → Следствие ОС переносит на диск память игры, которая сейчас не используется → На экране Когда игра снова обращается к этой памяти, фриз на десятки или сотни ms в зависимости от накопителя
Основной ответственный Внешние стороны · Внешние стороны · Совместно Команда разработки · Разработка клиента
Команда разработки: задачи
Сокращать расход памяти, предупреждать игрока, когда свободной памяти мало.
Внешние стороны: задачи
Сообщить игрокам минимальные требования, посоветовать закрывать во время игры другие программы (вкладки браузера и т. п.).
На графике
Случайные всплески · жёсткие ошибки страниц, расход памяти
Где смотреть
Записывать вместе со временем кадра счётчик Memory\Pages Input/sec в Системном мониторе (число страниц, прочитанных с диска для обработки жёстких ошибок страниц) и на вкладке «Производительность» Диспетчера задач использование памяти и значение «Выделено» (commit)
Подтверждает
В моменты фризов Pages Input/sec подскакивает, а память почти заполнена. Если закрыть браузер и другие программы, проблема пропадает
Опровергает
Если память свободна, а Pages Input/sec не растёт, это «Синхронная загрузка и компиляция шейдеров в главном потоке» или «Стриминг ассетов отстаёт из-за медленного накопителя»
Чем проверить
Проверка на стороне игрока
Источников: 3
Introduction to the page fileMicrosoft Файл подкачки: файл на диске, в который из ОЗУ выгружаются изменённые и редко используемые страницы памяти
Working SetMicrosoft Обращение к странице, которой нет в ОЗУ, вызывает ошибку страницы. Жёсткая ошибка устраняется только чтением с диска, например из файла подкачки
ID co-vram · Основной ответственный Команда разработки · Разработка клиента · Совместно Внешние стороны · Внешние стороны
Если графическим настройкам нужно больше памяти, чем есть на видеокарте, ОС выгружает текстуры в оперативную память ПК и загружает обратно, и появляются микрофризы.
Почему Высокое качество текстур, множество разного снаряжения и эффектов в людном месте забивают память видеокарты → Следствие ОС переносит неиспользуемые сейчас текстуры в оперативную память ПК, а когда они нужны, возвращает их по медленной шине PCIe → На экране Рывки при каждом появлении новой сцены или нового персонажа, текстуры какое-то время размытые
При наплыве игроков, В движении и при смене локации
Ответственные
Основной ответственный Команда разработки · Разработка клиента · Совместно Внешние стороны · Внешние стороны
Команда разработки: задачи
Выбирать настройки по умолчанию под объём видеопамяти, при выходе за бюджет памяти автоматически снижать качество текстур, в людных местах упрощать текстуры персонажей.
Внешние стороны: задачи
Посоветовать игрокам снизить качество текстур, а при запуске двух клиентов снизить настройки ещё сильнее.
Цифры для ориентира
Память видеокарты читает сотни GB в секунду, а шина PCIe между ней и оперативной памятью ПК, в зависимости от поколения, передаёт около 16–64 GB в секунду, то есть более чем в десять раз медленнее.
На графике
Упор в лимит (плато) · выделенная память GPU, общая память GPU
Где смотреть
Смотреть графики выделенной и общей памяти графического процессора в разделе GPU на вкладке «Производительность» Диспетчера задач (на вкладку «Подробности» можно добавить такие же столбцы по процессам) вместе со временем кадра в PresentMon
Подтверждает
Пока выделенная память GPU упирается в предел и график становится плоским, а общая растёт, рывки частые. При снижении качества текстур они пропадают
Опровергает
Если выделенная память не заполнена, это «Стриминг ассетов отстаёт из-за медленного накопителя» или «Синхронная загрузка и компиляция шейдеров в главном потоке»
Чем проверить
Проверка на стороне игрока
Подробнее
Признак: в разделе GPU Диспетчера задач Windows «Выделенная память графического процессора» заполнена, а «Общая память графического процессора» растёт. Если на одном ПК запущены два клиента, память заполняется быстрее (см. причину «Сбой стриминга из-за нехватки памяти или VRAM»).
Источников: 4
ResidencyMicrosoft У процесса есть бюджет видеопамяти, и при его превышении ядро ОС переносит часть кучи дискретного GPU в оперативную память ПК (это крайняя мера, поэтому рекомендуется следить за бюджетом)
GPUs in the task managerMicrosoft Выделенная память GPU в Диспетчере задач означает VRAM видеокарты, общая память GPU означает оперативную память ПК, которую делят GPU и CPU
CUDA C++ Best Practices GuideNVIDIA Пропускная способность видеопамяти (V100: 898 GB/s) намного выше, чем у PCIe x16 3-го поколения (16 GB/s), поэтому рекомендуется сокращать обмен с оперативной памятью ПК
ID co-wifi-scan · Основной ответственный Внешние стороны · Внешние стороны · Совместно Команда разработки · Разработка клиента
ОС периодически перебирает радиоканалы в поисках соседних сетей Wi-Fi, и на это время связь ненадолго прерывается.
Почему ОС или драйвер через равные промежутки ищут окружающие сети Wi-Fi → Следствие На время поиска приём и передача ненадолго останавливаются → На экране Пинг скачет строго через равные промежутки (например, каждые 60 секунд)
Основной ответственный Внешние стороны · Внешние стороны · Совместно Команда разработки · Разработка клиента
Команда разработки: задачи
Во время игры запрашивать режим, который сокращает сканирование (на Android режим Wi-Fi с низкой задержкой WIFI_MODE_FULL_LOW_LATENCY, в Windows режим потоковой передачи мультимедиа через WlanSetInterface; на некоторых устройствах и драйверах это не помогает).
Обычно от десятков до сотен ms за раз. Если всплески подозрительно регулярные, эту причину проверяют первой.
На графике
Всплески с постоянным периодом · RTT до роутера
Где смотреть
Во время игры несколько минут пинговать адрес роутера (основной шлюз в выводе ipconfig) командой ping /t и измерить интервал между всплесками. Повторить то же по кабелю
Подтверждает
Пинг до роутера строго через равные промежутки (например, 60 секунд) подскакивает на десятки или сотни ms, а по кабелю этого нет
Опровергает
Если интервал между всплесками нерегулярный, это «Помехи и слабый сигнал Wi-Fi». Если до роутера всё ровно, а скачет только дальше, дело в подключении или на участке провайдера
Чем проверить
Проверка на стороне игрока
Источников: 5
WDI low latency connection qualityMicrosoft Сканирование и роуминг уводят радиомодуль с рабочего радиоканала, поэтому в режиме низкой задержки время вне него и сканирование ограничиваются
WlanSetInterface function (wlanapi.h)Microsoft API Windows, который включает и выключает фоновое сканирование (wlan_intf_opcode_background_scan_enabled) и режим потоковой передачи мультимедиа
Wi-Fi low-latency modeAndroid (Google) В режиме низкой задержки энергосбережение Wi-Fi отключается, а оптимизация сканирования и роуминга зависит от реализации у производителя устройства
pingMicrosoft /t: отправлять эхо-запросы непрерывно, пока их не остановят
ipconfigMicrosoft Без параметров показывает для каждого адаптера адреса IPv4 и IPv6 и основной шлюз
ID co-driver · Основной ответственный Внешние стороны · Внешние стороны · Совместно Команда разработки · Разработка клиента
Если сетевая карта или модуль Wi-Fi уходят в энергосбережение между пакетами, на пробуждение нужно время.
Почему Включено энергосбережение сетевого адаптера, или драйвер устарел → Следствие Задержка выхода из энергосбережения (wake-up), иногда перезапуск устройства → На экране Нерегулярные задержки, изредка фриз на несколько секунд
Основной ответственный Внешние стороны · Внешние стороны · Совместно Команда разработки · Разработка клиента
Команда разработки: задачи
В клиенте для Android во время игры запрашивать режим Wi-Fi с низкой задержкой (WIFI_MODE_FULL_LOW_LATENCY), чтобы отключить энергосбережение Wi-Fi.
Внешние стороны: задачи
Посоветовать игрокам обновить сетевой драйвер и отключить энергосбережение сетевого адаптера в Диспетчере устройств, а если весь экран дёргается и звук хрипит, найти виновный драйвер с помощью LatencyMon.
На графике
Случайные всплески · время DPC и ISR, RTT до роутера
Где смотреть
Записать трассу в Windows Performance Recorder (WPR), найти на графике DPC/ISR в Windows Performance Analyzer (WPA) драйверы с долгим выполнением (столбец Module) и проверить в Диспетчере устройств настройки управления электропитанием сетевого адаптера
Подтверждает
В моменты рывков DPC и ISR сетевого драйвера длятся по несколько ms, или после отключения энергосбережения нерегулярные задержки пропадают
Опровергает
Если DPC короткие, а с отключённым энергосбережением ничего не меняется, это «Помехи и слабый сигнал Wi-Fi» или «Фоновое сканирование Wi-Fi»
Чем проверить
Проверка на стороне игрока
Подробнее
Если драйвер долго занимает CPU обработкой прерываний (в Windows это называют задержкой DPC), игровой поток всё это время тоже не может использовать ядро. Тогда при низкой загрузке CPU весь экран дёргается, а звук хрипит. Найти виновный драйвер помогают инструменты вроде LatencyMon, и чаще всего это драйверы Wi-Fi или сетевой карты.
Источников: 4
Introduction to NDIS Selective SuspendMicrosoft Windows может переводить простаивающий сетевой адаптер в состояние пониженного энергопотребления (выборочная приостановка)
Guidelines for Writing DPC RoutinesMicrosoft Пока выполняется DPC, все потоки на этом ядре стоят, поэтому рекомендуется не превышать 100 µs за раз
Wi-Fi low-latency modeAndroid (Google) В режиме Wi-Fi с низкой задержкой фреймворк Android явно отключает энергосбережение Wi-Fi
CPU AnalysisMicrosoft График DPC/ISR в WPA: длительность каждого непрерывного выполнения DPC или ISR и модуль (Module), в котором находится эта функция
ID co-other-apps · Основной ответственный Внешние стороны · Внешние стороны · Совместно Команда разработки · Разработка клиента
Если на том же ПК идёт синхронизация с облаком, большая загрузка или скачивание патча игры, игровые пакеты ждут в очереди.
Почему Другие приложения загружают или отдают данные на максимальной скорости → Следствие Игровые пакеты копятся в очередях ПК и роутера → На экране Пинг взлетает, задержка ввода, перемотка
Основной ответственный Внешние стороны · Внешние стороны · Совместно Команда разработки · Разработка клиента
Команда разработки: задачи
Собственный лаунчер и патчер: во время игры приостанавливать фоновые загрузки или ограничивать их скорость.
Внешние стороны: задачи
Посоветовать игрокам ограничить скорость загрузок и отключать автообновления во время игры.
На графике
Растёт вслед за онлайном и нагрузкой · RTT, объём трафика ПК
Где смотреть
Записывать в Системном мониторе Network Interface\Bytes Sent/sec и Bytes Received/sec вместе с пингом. Метод тот же, что в тесте на bufferbloat: держать пинг запущенным и намеренно запустить большую передачу данных
Подтверждает
Пока загрузка или отдача близка к скорости подключения, пинг растёт на десятки или сотни ms, а после остановки передачи сразу возвращается
Опровергает
Если трафик ПК низкий, а пинг растёт, это «Bufferbloat (очередь в роутере)» из-за другого устройства в доме или проблема на участке провайдера
Чем проверить
Проверка на стороне игрока
Источников: 4
IntroductionBufferbloat.net Если роутер или другое сетевое оборудование копит слишком много данных, задержка резко растёт (bufferbloat)
Delivery Optimization referenceMicrosoft Загрузка обновлений Windows (оптимизация доставки) по умолчанию динамически подстраивается под доступную пропускную способность, а для фоновых и активных загрузок можно задать верхний предел пропускной способности
ID co-unfocused · Основной ответственный Команда разработки · Разработка клиента
Когда игрок переключается на другое окно или сворачивает игру, и сама игра, и Windows ради экономии энергии замедляют её работу. По возвращении накопившиеся пакеты приходят разом, или соединение уже оборвано.
Почему Переключение на другое окно через Alt+Tab или сворачивание игры → Следствие Пока игру не видно, она сильно снижает FPS или останавливается, а Windows тоже понижает приоритет невидимых программ → На экране В момент возвращения перемотка, а если игра была свёрнута долго, дисконнект
Основной ответственный Команда разработки · Разработка клиента
Команда разработки: задачи
Продолжать приём пакетов и хартбиты в отдельном потоке, даже когда окно не видно, проверить настройку движка «Run In Background», при возвращении разом переходить к актуальному состоянию.
Цифры для ориентира
Если в невидимом окне FPS снижается до 5–10, один кадр длится 100–200 ms. Игра, которая обрабатывает пакеты раз в кадр, читает их с таким же опозданием.
На графике
Провал, затем пачка · интервал между кадрами (до и после переключения окна), число обработанных пакетов
Где смотреть
С запущенным PresentMon переключиться через Alt+Tab или свернуть игру и посмотреть интервал между кадрами, пока окно не видно. Писать в лог игры моменты смены фокуса окна и сопоставлять их с причинами обрывов
Подтверждает
Пока окно не видно, интервал между кадрами растёт до 100 ms и больше или запись прерывается, а в момент возвращения накопившиеся пакеты обрабатываются разом, и получается перемотка. Если игра свёрнута долго, соединение рвётся по таймауту хартбита
Опровергает
Если то же самое и с открытым окном, это «Фоновые процессы занимают CPU» или проблема в сети
Чем проверить
Проверка на стороне игрока
Подробнее
Windows 11 не гарантирует таймер 1 ms программам, чьё окно свёрнуто или полностью перекрыто и не издаёт звука. На ноутбуке, работающем от батареи, такие программы переводятся на самую экономичную частоту, а на CPU с ядрами разных типов могут работать на медленных энергоэффективных ядрах. Если из двух клиентов на одном ПК странно ведёт себя только фоновый, посмотрите также причину «Ограничение обработки в фоновом окне».
Источников: 4
Quality of ServiceMicrosoft Программы, окна которых не видны и не слышны, получают Low QoS: при работе от батареи они выполняются на самой экономичной частоте CPU и на энергоэффективных ядрах
timeBeginPeriod function (timeapi.h)Microsoft Windows 11 не гарантирует процессам со свёрнутыми или перекрытыми окнами разрешение таймера выше стандартного
Application.runInBackgroundUnity В Unity по умолчанию false, поэтому, когда окно уходит в фон, игровой цикл останавливается
ID co-overlay · Основной ответственный Внешние стороны · Внешние стороны · Совместно Команда разработки · Разработка клиента
Мессенджеры, лаунчеры, программы записи и счётчики FPS встраиваются в рендеринг игры (хукинг), чтобы рисовать свой UI поверх игровой картинки. Работы в каждом кадре становится больше, а иногда оверлей конфликтует с игрой, и она дёргается или принудительно закрывается.
Почему Включены оверлеи мессенджера, игрового лаунчера, утилиты видеокарты или программы записи → Следствие При каждом выводе кадра на экран оверлей вклинивается и дорисовывает свой UI → На экране Кадры немного запаздывают, в момент всплывающего уведомления бывают рывки, графические ошибки или принудительное закрытие игры (игроку это кажется дисконнектом)
Основной ответственный Внешние стороны · Внешние стороны · Совместно Команда разработки · Разработка клиента
Команда разработки: задачи
Собирать вместе с краш-репортами и логами микрофризов список запущенных оверлеев.
Внешние стороны: задачи
На жалобу попросить игрока выключить все оверлеи и проверить ещё раз.
На графике
Высоко только у некоторых · время кадра и число крашей (у игроков с включёнными оверлеями)
Где смотреть
Выключить все оверлеи и сравнить время кадра в PresentMon в той же сцене, а при крашах посмотреть имя сбойного модуля (Faulting module name) в событии с кодом 1000 в Просмотре событий
Подтверждает
С выключенными оверлеями рывки и графические ошибки пропадают, или сбойным модулем в краше оказывается DLL программы с оверлеем
Опровергает
Если с выключенными оверлеями всё то же самое, это графический драйвер или «Краш клиента»
Чем проверить
Проверка на стороне игрока
Подробнее
Если микрофризы или вылеты бывают только у отдельных игроков и железом это не объяснить, первым делом подозревают конфликт оверлея с модулем защиты игры.
Источников: 3
Steam Overlay (Steamworks Documentation)Valve Оверлей Steam автоматически подключается через хуки к играм, запущенным из Steam, и из-за такого способа может выявлять ошибки работы с памятью в том, как игра использует API рендеринга, что приводит к крашам
ID co-display-input · Основной ответственный Внешние стороны · Внешние стороны · Совместно Команда разработки · Разработка клиента
Если пинг в норме, а управление ватное, задержку между вводом и экраном может добавлять обработка изображения в телевизоре, беспроводной контроллер или генерация кадров.
Почему Игровой режим телевизора выключен, используется Bluetooth- или другой беспроводной контроллер, или включена генерация кадров (DLSS Frame Generation, FSR Frame Generation) → Следствие Телевизор выводит кадр позже из-за обработки изображения, беспроводной ввод опаздывает на период опроса и из-за помех, а генерация кадров ждёт следующий кадр, чтобы построить промежуточный → На экране Пинг и FPS хорошие, но нажатие доходит до экрана с опозданием: задержка ввода
Основной ответственный Внешние стороны · Внешние стороны · Совместно Команда разработки · Разработка клиента
Команда разработки: задачи
Сделать генерацию кадров опцией и предупреждать, что с ней может вырасти задержка ввода, вместе с генерацией кадров интегрировать функции низкой задержки от производителей GPU (NVIDIA Reflex, AMD Anti-Lag 2), показывать в игре задержку от ввода до экрана на стороне ПК, в сборках для Android TV и приставок запрашивать у телевизора режим низкой задержки (ALLM) через Window.setPreferMinimalPostProcessing(true).
Внешние стороны: задачи
Посоветовать игрокам включить игровой режим (ALLM) на телевизоре или мониторе, в соревновательном контенте использовать проводной контроллер и выключать генерацию кадров, держать Bluetooth-устройства поближе, а Wi-Fi использовать в диапазоне 5 GHz.
Цифры для ориентира
Только на передачу одного кадра на экран 60 Hz уходит 16,7 ms, на 120 Hz 8,3 ms. Старые контроллеры Xbox опрашивали и отправляли ввод каждые 8 ms. Задержка от обработки изображения в телевизоре у всех моделей разная, и одной цифрой её не назвать. Игровой режим как раз сокращает эту обработку. AMD рекомендует использовать генерацию кадров, если исходная частота кадров не ниже 60 FPS.
На графике
Высоко с самого начала · задержка от ввода до экрана
Где смотреть
Сравнить MsAllInputToPhotonLatency в PresentMon (от ввода с клавиатуры или мыши до вывода на экран) с включённой и выключенной генерацией кадров и по FrameType (записывается, только если его сообщают драйвер или SDK) посмотреть, есть ли среди кадров сгенерированные промежуточные. Беспроводной участок контроллера и обработка внутри телевизора в это значение не входят, поэтому эту часть проверять, включая игровой режим телевизора и меняя контроллер на проводной
Подтверждает
Пинг в норме, а с выключенной генерацией кадров задержка от ввода до экрана уменьшается, или с игровым режимом телевизора и проводным контроллером ощутимая задержка пропадает
Опровергает
Если после всех этих изменений ничего не меняется, а пинг высокий или скачет, дело в сети. Если задержка на стороне ПК высокая из-за V-Sync или очереди кадров, это «V-Sync и очередь рендеринга»
Чем проверить
Проверка на стороне игрока
Подробнее
Сетевую задержку видно по пингу, а эта задержка в пинг не попадает. Поэтому при жалобе «пинг низкий, а лагает» её проверяют первой. Генерация кадров примерно вдвое поднимает число FPS на экране, но для построения промежуточного кадра нужно дождаться следующего настоящего, поэтому ввод доходит до экрана дольше (AMD указывает, что рост задержки заложен в саму технологию). Bluetooth-устройства используют тот же диапазон 2,4 GHz, что и Wi-Fi, и при помехах ввод может прерываться или дёргаться. О V-Sync и очереди рендеринга, которые увеличивают задержку внутри ПК, см. причину «V-Sync и очередь рендеринга».
Источников: 9
Auto Low Latency Mode (ALLM)HDMI Licensing Administrator ALLM позволяет устройству автоматически переключать дисплей в режим низкой задержки (обычно его называют игровым режимом). В этом режиме телевизор отключает часть обработки изображения, чтобы уменьшить задержку
Xbox Series X: What’s the Deal with Latency?Microsoft Задержка ввода складывается по всему пути контроллер → консоль → HDMI → телевизор. Старые контроллеры опрашивали и отправляли ввод каждые 8 ms. Передача одного кадра по HDMI занимает 16,6 ms при 60 Hz и 8,3 ms при 120 Hz. ALLM автоматически включает игровой режим телевизора
AMD FSR Frame GenerationAMD Для генерации кадров рекомендуется исходная частота от 60 FPS (ниже 30 FPS её следует избегать). AMD Radeon Anti-Lag 2 согласует работу CPU и GPU и снижает системную задержку
NVIDIA DLSSNVIDIA DLSS Frame Generation рассчитана на работу вместе с NVIDIA Reflex (функцией низкой задержки), чтобы отзывчивость сохранялась
PresentMon Capture Application (README-CaptureApplication.md)Intel MsAllInputToPhotonLatency (задержка от ввода до экрана), DisplayLatency (от отправки кадра до вывода на монитор), FrameType (отличает кадры, нарисованные приложением, от интерполированных драйвером или SDK)
PresentMon Console Application (README-ConsoleApplication.md)Intel MsAllInputToPhotonLatency считается от ввода с клавиатуры и мыши, FrameType записывается, только если приложение или драйвер отправляют события Intel-PresentMon (--track_frame_type)
Window.setPreferMinimalPostProcessingAndroid (Google) Окно, для которого важна задержка (например, игра), запрашивает у дисплея минимальную обработку изображения. При подключении по HDMI отправляются сигналы ALLM и Game Content Type, и телевизор переходит в режим низкой задержки
ID hn-wifi · Основной ответственный Внешние стороны · Внешние стороны · Совместно Команда разработки · Разработка клиента
При слабом сигнале или помехах пакеты на беспроводном участке приходится отправлять повторно по нескольку раз, и они приходят неравномерно.
Почему Стены, расстояние, микроволновка, Bluetooth и соседские роутеры ухудшают качество радиосигнала → Следствие Передача на беспроводном участке не удаётся → несколько повторных передач → На экране Пакеты приходят неравномерно (джиттер), персонажи двигаются рывками, а в тяжёлых случаях из-за потерь телепортируются
Основной ответственный Внешние стороны · Внешние стороны · Совместно Команда разработки · Разработка клиента
Команда разработки: задачи
Автоматически подстраивать длину буфера интерполяции под состояние подключения, при большом джиттере или потерях показывать на экране индикатор состояния сети.
Каждая повторная передача добавляет примерно 1–4 ms. При слабом сигнале пакет много раз пересылается на низкой скорости и к тому же ждёт, пока освободится радиоканал, поэтому бывают всплески по 50–200 ms. Подвох в том, что средний пинг при этом выглядит нормальным.
На графике
Случайные всплески · RTT до роутера
Где смотреть
Несколько минут пинговать адрес роутера (основной шлюз в выводе ipconfig) командой ping /t и посмотреть уровень сигнала и радиоканал своего роутера через netsh wlan show networks mode=bssid. Сравнить с кабельным подключением на том же месте
Подтверждает
Уже пинг до роутера беспорядочно скачет на десятки или сотни ms, иногда бывают потери, уровень сигнала низкий. По кабелю или рядом с роутером проблема пропадает
Опровергает
Если до роутера ровно, а скачет только дальше, дело в подключении или на участке провайдера. Если всплески идут только через равные промежутки, это «Фоновое сканирование Wi-Fi»
Чем проверить
Проверка на стороне игрока
Подробнее
Если в mesh-системе Wi-Fi узлы связаны друг с другом по радио (беспроводной бэкхол), ретранслирующий узел не может передавать, пока принимает, и делит эфирное время с соседними участками на том же радиоканале. Под нагрузкой пропускная способность падает, а задержка растёт. В устройствах с отдельным радиодиапазоном под бэкхол это выражено слабее, а если соединить узлы кабелем (Ethernet), этот участок перестаёт быть беспроводным. Адаптеры для передачи по электросети (PLC) тоже, как Wi-Fi, передают только после проверки, свободна ли среда (CSMA/CA), а качество связи постоянно меняется из-за помех от бытовой техники и её включения и выключения, отсюда повторные передачи и джиттер.
RFC 8325: Mapping Diffserv to IEEE 802.11IETF CSMA/CA в 802.11: передача только при свободном радиоканале, а если он занят, передача откладывается до его освобождения и ещё на случайный интервал (backoff)
Capacity of Ad Hoc Wireless Networks (MobiCom 2001)ACM При многократной ретрансляции по 802.11 узел не может передавать, пока принимает, а соседние участки мешают друг другу, поэтому пропускная способность цепочки ретрансляторов теоретически падает до 1/3 (в моделировании примерно до 1/7)
Electri-Fi Your Data: Measuring and Combining Power-Line Communications with WiFi (IMC 2015)ACM Серийное оборудование для передачи по электросети (IEEE 1901, HomePlug AV) использует CSMA/CA, как Wi-Fi, и из-за кратковременной неравномерности доступа джиттер может расти. Качество связи меняется из-за помех от бытовой техники и её включения и выключения (в масштабе от минут до часов)
ID hn-channel · Основной ответственный Внешние стороны · Внешние стороны · Совместно Команда разработки · Разработка клиента
Там, где рядом десятки роутеров (например, в многоквартирном доме), они делят один радиоканал, и каждому приходится ждать своей очереди на передачу.
Почему Десятки роутеров работают на одном радиоканале 2,4 GHz → Следствие Перед передачей нужно ждать, пока другие устройства закончат и радиоканал освободится → На экране Вечером, когда люди возвращаются домой, растёт джиттер (неравномерность интервалов между пакетами), появляются микрофризы
Основной ответственный Внешние стороны · Внешние стороны · Совместно Команда разработки · Разработка клиента
Команда разработки: задачи
При росте джиттера автоматически удлинять буфер интерполяции.
Внешние стороны: задачи
Посоветовать игрокам диапазоны 5 GHz или 6 GHz, менее загруженный радиоканал, кабельное подключение.
На графике
Высоко только в определённые часы · RTT и джиттер до роутера
Где смотреть
Посмотреть радиоканалы и уровень сигнала соседних сетей Wi-Fi через netsh wlan show networks mode=bssid и сравнить пинг до роутера вечером и днём
Подтверждает
На том же радиоканале 2,4 GHz видно много соседних роутеров, а джиттер до роутера растёт только вечером. При переходе на 5 GHz, 6 GHz или менее загруженный радиоканал он уменьшается
Опровергает
Если скачет в любое время суток, это «Помехи и слабый сигнал Wi-Fi». Если до роутера всё в порядке, а вечером плохо только дальше, это «Перегрузка пиринга в часы пик»
RFC 8325: Mapping Diffserv to IEEE 802.11IETF В 802.11 при занятом радиоканале передача откладывается до его освобождения и выполняется после случайной задержки backoff (CSMA/CA)
ID hn-bufferbloat · Основной ответственный Внешние стороны · Внешние стороны · Совместно Команда разработки · Разработка клиента
Когда кто-то из домашних выкладывает видео или качает большой файл, в очереди роутера скапливаются пакеты на сотни ms, и игровые пакеты ждут за ними.
Почему Подключение забито: домашние выгружают видео или делают облачный бэкап, игрок сам ведёт стрим, идёт большая загрузка → Следствие Роутер или модем складывает лишние пакеты в длинную очередь → На экране Игровые пакеты тоже ждут в конце очереди, и пинг взлетает до сотен ms
Основной ответственный Внешние стороны · Внешние стороны · Совместно Команда разработки · Разработка клиента
Команда разработки: задачи
Если пинг вдруг вырастает до сотен ms, показывать на экране состояние сети (с подсказкой, что подключение может быть занято большой передачей данных).
Внешние стороны: задачи
Посоветовать игрокам роутер с SQM (fq_codel, CAKE) или QoS, скорость в SQM выставлять на 90–95% от скорости подключения (только тогда очередь возникает внутри роутера и SQM работает), ограничить скорость отдачи.
Цифры для ориентира
На подключении с отдачей 10 Mbps буфер в 1 MB даёт очередь длиной до 800 ms.
На графике
Растёт вслед за онлайном и нагрузкой · RTT, загрузка подключения на отдачу и приём
Где смотреть
Держа пинг запущенным, полностью загрузить подключение тестом скорости или воспользоваться веб-тестом, который измеряет задержку под нагрузкой (по рекомендациям Bufferbloat.net). Смотреть вместе с загрузкой на отдачу и приём в интерфейсе роутера
Подтверждает
Пока отдача или приём забивают подключение, пинг растёт до сотен ms, а после окончания передачи возвращается (подозрительно, если задержка под нагрузкой больше 50 ms). С включённым SQM проблема пропадает
Опровергает
Если подключение свободно, а пинг всё равно скачет, это «Помехи и слабый сигнал Wi-Fi» или «Плохое качество линии связи»
Чем проверить
Проверка на стороне игрока
Подробнее
Чаще всего забивается отдача: у кабельных и мобильных подключений исходящая скорость часто намного ниже входящей. В домах с быстрым оптоволокном узким местом становится участок Wi-Fi, и то же самое происходит в беспроводной очереди роутера. Игровые пакеты маленькие и почти не занимают пропускную способность, но ждать в очереди им приходится так же. Если забита только отдача, запаздывает только ввод игрока, а движения других выглядят нормально. На телефоне то же самое бывает, когда резервное копирование фото или обновление приложений на этом же телефоне заполняет очереди модема телефона и базовой станции.
Источников: 4
Setting up SQM for CeroWrt 3.10Bufferbloat.net Скорость в SQM нужно снизить до 95% от измеренной (или до 85% от заявленной провайдером), чтобы узкое место переместилось из оборудования провайдера внутрь роутера, иначе эффекта не будет
SQM (Smart Queue Management)OpenWrt Скорости приёма и отдачи указывать на уровне 90% от измеренных, дисциплина очереди рекомендуется cake (на слабом CPU fq_codel)
Tests for BufferbloatBufferbloat.net Если держать пинг запущенным, загрузить подключение тестом скорости и пинг вырастет, это bufferbloat. При задержке под нагрузкой больше 50 ms (или оценке ниже B) рекомендуется принимать меры
ID hn-nat · Основной ответственный Команда разработки · Разработка клиента · Совместно Команда разработки · Разработка сервера
Роутер удаляет из таблицы NAT неактивные соединения, по которым какое-то время не было пакетов. Это частая причина дисконнекта в тот момент, когда игрок после простоя снова начинает двигаться.
Почему Роутер записывает соединение «домашнее устройство ↔ внешний сервер» в таблицу NAT (таблицу трансляции адресов) → Следствие Если пакетов какое-то время нет, запись удаляется (для UDP обычно через 30–120 секунд) → На экране Пакеты сервера больше не попадают в домашнюю сеть, дисконнект
Основной ответственный Команда разработки · Разработка клиента · Совместно Команда разработки · Разработка сервера
Команда разработки: задачи
Клиент: отправлять хартбиты с интервалом не больше половины самого короткого таймаута простоя (запись NAT для UDP гарантированно обновляют только исходящие из дома пакеты, поэтому отправляет клиент), при обрыве автоматически переподключаться. Сервер: отвечать на хартбиты, а если их долго нет, первым закрывать соединение. Если запись NAT удалилась и внешний адрес и порт сменились, узнавать того же игрока по токену сессии (идентификатору, полученному при входе) и продолжать сессию.
На графике
Массовый обрыв соединений · число обрывов (таймаут хартбита), время простоя перед обрывом
Где смотреть
Собрать причины обрывов на сервере и время от последнего пакета по соединению до обрыва (время простоя) и посмотреть их распределение. В тесте увеличивать интервал между UDP-пакетами до 30, 60 и 120 секунд и найти интервал, при котором ответы перестают приходить
Подтверждает
Рвутся только простаивавшие соединения, и время простоя скапливается сразу за определённым значением в диапазоне 30–120 секунд. Если сделать интервал хартбита короче, обрывы пропадают
Опровергает
Если рвётся и во время активной игры, дело в подключении или маршруте. Если короткие значения скапливаются только у определённого мобильного оператора, это «Общий IP провайдера (CGNAT)»
ID hn-router · Основной ответственный Внешние стороны · Внешние стороны
Когда на дешёвый роутер приходятся десятки устройств и тысячи соединений, он сам перестаёт справляться.
Почему Десятки устройств, P2P-программы и торренты открывают тысячи соединений → Следствие CPU и таблица сессий роутера забиты → На экране Задержки и потери при обработке пакетов, новые соединения не устанавливаются
Основной ответственный Внешние стороны · Внешние стороны
Внешние стороны: задачи
Посоветовать игрокам перезагрузить роутер (временная мера), заменить его, закрыть программы, которые открывают много соединений (P2P, торренты).
На графике
Упор в лимит (плато) · CPU и число соединений роутера, RTT до роутера
Где смотреть
Посмотреть в веб-интерфейсе роутера загрузку CPU, число соединений (сессий) и подключённых устройств (если роутер это показывает) и сравнить пинг до самого роутера до и после перезагрузки
Подтверждает
При большом числе соединений уже пинг до роутера скачет или теряются пакеты, новые подключения не проходят. После перезагрузки какое-то время всё нормально, потом снова плохо
Опровергает
Если до роутера всё в порядке, а плохо только дальше, дело в подключении или на участке провайдера
Чем проверить
Проверка на стороне игрока
Источников: 2
An Experimental Study of Home Gateway Characteristics (IMC 2010)ACM Число TCP-соединений к одному порту сервера, которое пропускает домашний роутер, от 16 до примерно 1 024 (медиана 135). Пропускная способность дешёвых устройств бывает всего несколько Mbps
Netfilter Conntrack Sysfs variablesLinux kernel Максимальное число записей в таблице conntrack в Linux (nf_conntrack_max) и время хранения записей по состояниям по умолчанию
ID hn-handover · Основной ответственный Внешние стороны · Внешние стороны · Совместно Команда разработки · Разработка клиента, Команда разработки · Разработка сервера
В автобусе или метро связь прерывается на время смены базовой станции.
Почему При перемещении меняется базовая станция, к которой подключён телефон → Следствие Обычно перерыв длится десятки ms, но если из-за плохого сигнала переключение не удалось, связь может пропасть на время от сотен ms до нескольких секунд → На экране Фриз, затем телепортация, а при долгом перерыве дисконнект
Основной ответственный Внешние стороны · Внешние стороны · Совместно Команда разработки · Разработка клиента, Команда разработки · Разработка сервера
Команда разработки: задачи
Клиент: выставить таймауты, которые переживают короткие обрывы, быстро переподключаться. Сервер: не выкидывать игрока сразу после обрыва на несколько секунд, при переподключении продолжать ту же сессию.
Внешние стороны: задачи
Объяснить игрокам, что обрывы в дороге (в автобусе, метро) возникают из-за смены базовых станций.
На графике
Провал, затем пачка · число полученных пакетов, RTT
Где смотреть
Уточнить, был ли игрок в дороге (в автобусе, метро) в момент обрыва, и посмотреть в логе клиента время перерывов в приёме и изменения типа сети и сигнала
Подтверждает
Только в дороге приём пропадает на время от сотен ms до нескольких секунд, а потом данные приходят пачкой. На месте не воспроизводится
Опровергает
Если то же самое и на месте, это «Слабый сигнал мобильной сети и мёртвые зоны» или «Частые переключения 5G ↔ LTE (на границе покрытия 5G)»
ID hn-rrc · Основной ответственный Команда разработки · Разработка клиента
Если связи какое-то время нет, телефон переводит радиосоединение в экономичное состояние, а при следующем пакете поднимает его снова, и пакет опаздывает.
Почему После короткой паузы в обмене данными телефон переводит радиосоединение в режим энергосбережения → Следствие Чтобы отправить следующий пакет, соединение нужно снова поднять → На экране Заметно запаздывает только первое действие после простоя
Основной ответственный Команда разработки · Разработка клиента
Команда разработки: задачи
Поддерживать соединение активным лёгкой периодической отправкой (ценой расхода батареи).
Цифры для ориентира
В LTE радиомодуль обычно уходит в энергосбережение примерно после 10 секунд без обмена данными, а возврат занимает от десятков до сотен ms (по измерениям примерно 0,3–0,6 с). В 3G больше 1 секунды.
На графике
Высоко только у некоторых · RTT первого запроса после простоя (мобильные)
Где смотреть
Разбить внутриигровой RTT по интервалу с предыдущим обменом данными. На мобильных сравнить RTT первого пакета после паузы дольше 10 секунд и пакетов, отправленных подряд
Подтверждает
В мобильной сети только первый пакет после паузы опаздывает на сотни ms, а следующие сразу за ним в норме. В Wi-Fi разницы нет
Опровергает
Если опаздывают и пакеты, отправленные подряд, дело в сигнале, подключении или маршруте
Optimize network accessAndroid (Google) Задержка смены состояния радиомодуля и время tail зависят от технологии (3G, LTE, 5G) и настроек оператора. Пример для 3G: из экономичного состояния в полную мощность около 1,5 с, из режима ожидания в полную мощность больше 2 с
ID hn-weak-cell · Основной ответственный Внешние стороны · Внешние стороны · Совместно Команда разработки · Разработка клиента
В лифте, под землёй или в глубине здания растёт число повторных передач, падает скорость, и в итоге дело доходит до дисконнекта.
Почему Игрок переходит туда, где сигнал слабый → Следствие Больше повторных передач по радио, скорость падает, связь на мгновения пропадает → На экране Из-за джиттера и потерь микрофризы и телепортация, в итоге дисконнект
Основной ответственный Внешние стороны · Внешние стороны · Совместно Команда разработки · Разработка клиента
Команда разработки: задачи
Доработать сценарий переподключения, показывать качество сети.
Внешние стороны: задачи
Объяснить игрокам, что проблема возникает там, где слабый сигнал (в лифте, под землёй, в глубине здания).
На графике
Высоко только у некоторых · RTT и потери (по игрокам на мобильных)
Где смотреть
Уточнить, где был игрок в момент обрыва (в лифте, под землёй, внутри здания) и что показывал индикатор сигнала, и сравнить, повторив то же действие там, где сигнал хороший
Подтверждает
RTT и потери растут и связь рвётся только там, где сигнал слабый. Там, где сигнал хороший, проблема пропадает
Опровергает
Если то же самое при хорошем сигнале, дело на участке провайдера или на стороне сервера
ID hn-5g-flip · Основной ответственный Внешние стороны · Внешние стороны · Совместно Команда разработки · Разработка клиента
Внутри зданий со слабым сигналом 5G или на границе покрытия 5G телефон часто переключается между 5G и LTE, и при каждом переключении пинг скачет или связь ненадолго прерывается.
Почему Игрок там, где сигнал 5G то есть, то нет (внутри здания, на границе покрытия 5G) → Следствие Телефон постоянно переключается между 5G и LTE, и каждый раз возникает короткий перерыв → На экране Даже на месте пинг беспорядочно скачет, иногда бывают фризы и телепортация
Основной ответственный Внешние стороны · Внешние стороны · Совместно Команда разработки · Разработка клиента
Команда разработки: задачи
При росте джиттера автоматически удлинять буфер интерполяции, писать в лог, снятый в момент лагов, смену типа сети (5G, LTE), чтобы различать причины.
Внешние стороны: задачи
Посоветовать игрокам для сравнения включить в настройках предпочтительный режим LTE, рекомендовать Wi-Fi.
Цифры для ориентира
Одно переключение занимает от десятков до сотен ms. 5G в Корее в основном работает в связке с LTE (NSA), поэтому 5G-часть легко то подключается, то отваливается.
На графике
Случайные всплески · RTT, смена типа сети (5G, LTE)
Где смотреть
Переключить телефон в режим предпочтения LTE и сравнить на том же месте. Надёжнее, если клиент записывает вместе с RTT изменения индикатора сети в TelephonyDisplayInfo на Android (OVERRIDE_NETWORK_TYPE_NR_NSA и др.)
Подтверждает
Моменты всплесков RTT совпадают с переключениями индикатора 5G ↔ LTE, а в режиме предпочтения LTE всплесков нет
Опровергает
Если индикатор сети не меняется, а пинг всё равно скачет, это «Слабый сигнал мобильной сети и мёртвые зоны» или проблема с подключением
5G 통신서비스 품질평가 결과 발표과학기술정보통신부 По данным на 2020 год 5G в Корее предоставляется по схеме NSA, а переход на SA только планируется
TelephonyDisplayInfoAndroid (Google) OVERRIDE_NETWORK_TYPE_NR_NSA: индикатор сети, когда устройство подключено к LTE и может установить или уже установило двойное подключение (EN-DC) к 5G (NR)
ID hn-captive · Основной ответственный Внешние стороны · Внешние стороны · Совместно Команда разработки · Разработка клиента, Команда разработки · Разработка сервера
Страница входа в Wi-Fi кафе или корпоративный файрвол блокируют подключение к игре.
Почему Авторизация на странице входа ещё не пройдена, или файрвол блокирует игровые порты и UDP → Следствие Попытки подключения блокируются полностью или проходят только частично → На экране Ошибка входа, или авторизация проходит, но в игру не пускает
Основной ответственный Внешние стороны · Внешние стороны · Совместно Команда разработки · Разработка клиента, Команда разработки · Разработка сервера
Команда разработки: задачи
Клиент: при блокировке объяснять причину (не пройдена авторизация на странице входа, заблокирован UDP и т. п.), при блокировке UDP автоматически переходить на запасной путь. Сервер: предоставить запасной путь, например TCP 443.
Внешние стороны: задачи
Посоветовать игрокам в публичном Wi-Fi сначала пройти авторизацию на странице входа, а в закрытых сетях вроде корпоративной использовать другую сеть.
На графике
Высоко только у некоторых · число неудачных подключений (по сетям)
Где смотреть
Попросить игрока подключиться через другую сеть, например мобильный интернет, и проверить в логе подключений сервера, дошёл ли первый UDP-пакет и проходит ли подключение по запасному пути TCP 443
Подтверждает
Не подключается только через определённый Wi-Fi (кафе, офис), а через другую сеть подключается сразу. Не пройдена авторизация на странице входа, или до сервера не доходит только UDP
Опровергает
Если не подключается ни через одну сеть, дело в аккаунте, сервере или причине «Сбои и задержки DNS». Если не подключается вся страна или все абоненты провайдера, это «Ограничение UDP и DPI на уровне страны или провайдера»
Чем проверить
Проверка на стороне игрока
Источников: 2
RFC 8952: Captive Portal ArchitectureIETF Captive portal: сеть, в которой доступ ограничен, пока не выполнены условия вроде согласия с правилами или авторизации
ID isp-distance · Основной ответственный Команда инфраструктуры · Серверная инфраструктура · Совместно Команда инфраструктуры · Сетевая инфраструктура, Команда разработки · Разработка сервера
Даже свет в оптоволокне проходит всего около 200 000 km в секунду. Если сервер далеко, задержка будет большой, каким бы хорошим он ни был.
Почему Сервер далеко (зарубежный сервер, другой континент) → Следствие Время пути туда и обратно растёт с расстоянием (не меньше 10 ms на каждые 1 000 km) → На экране Постоянная задержка ввода на каждое действие, невыгодное положение при проверке попаданий
Основной ответственный Команда инфраструктуры · Серверная инфраструктура · Совместно Команда инфраструктуры · Сетевая инфраструктура, Команда разработки · Разработка сервера
Команда разработки: задачи
Законы физики кодом не исправить, можно только смягчить последствия: дать игроку выбрать ближайший региональный сервер, компенсацией задержки (отмоткой времени назад) уменьшить невыгодное положение при проверке попаданий.
Команда инфраструктуры: задачи
Серверы и ОС: ставить региональные серверы там, где много игроков. Сеть: размещать точки подключения (edge) ближе к игрокам, выбирать линии и маршруты с минимальными обходами.
Цифры для ориентира
Сеул–Токио около 30 ms, Сеул–Сингапур около 75 ms, Сеул–запад США около 140 ms, Сеул–Европа около 230–270 ms (туда и обратно, по реальным маршрутам). Вдоль прямой до Европы почти нет крупных кабелей, и трафик идёт через Юго-Восточную Азию и Суэц или через США, поэтому задержка намного больше, чем следует из расстояния.
На графике
Высоко с самого начала · RTT (по странам и регионам)
Где смотреть
Определить страну по IP подключения и посмотреть распределение RTT по странам, измерить ping и traceroute до сервера с VM в ближайшем к этой стране облачном регионе или с зондов RIPE Atlas (их выбирают по стране и ASN)
Подтверждает
RTT для далёких стран высокий в любое время суток и близок к минимальной задержке по расстоянию (10 ms туда и обратно на 1 000 km) и к публичной статистике задержек
Опровергает
Если RTT намного выше, чем объясняет расстояние, это «Неоптимальная маршрутизация», если растёт только по вечерам, это «Перегрузка пиринга в часы пик»
ITU-T G.114: One-way transmission timeITU Значение для планирования: задержка распространения по оптоволокну 5 µs/km (около 200 000 km в секунду, 10 ms туда и обратно на 1 000 km)
Azure network round-trip latency statisticsMicrosoft Azure Медианы измеренного времени туда и обратно от Сеула (Korea Central): Токио 30 ms, Сингапур 68 ms, запад США 124–136 ms, Европа 234–244 ms
Probe Selection (RIPE Atlas REST API)RIPE NCC Зонды для измерений RIPE Atlas выбирают по стране, региону, ASN или диапазону адресов и запускают с них ping и traceroute
ID isp-satellite · Основной ответственный Внешние стороны · Внешние стороны · Совместно Команда разработки · Разработка клиента, Команда разработки · Разработка сервера
В спутниковом интернете радиосигнал летит в космос и обратно. Через геостационарный спутник один только путь туда и обратно занимает больше 0,5 с. Низкоорбитальные спутники вроде Starlink обычно быстрые, но в моменты перераспределения маршрута задержка скачет, а связь может ненадолго прерываться.
Почему Подключение дома, на судне или в самолёте через геостационарный или низкоорбитальный спутниковый интернет либо через бортовой Wi-Fi, работающий через спутник → Следствие Геостационарная орбита находится на высоте около 36 000 km, поэтому сам путь сигнала длинный. На низкой орбите маршрут терминал–спутник–наземная станция часто перераспределяется, и в эти моменты ненадолго появляются задержка и потери → На экране Через геостационарный спутник большая задержка ввода на любое действие, через низкоорбитальный обычно всё нормально, но через равные промежутки времени микрофризы и телепортация
Только у меня, Все в одном доме, Один регион или провайдер
Когда
Всегда, С постоянным периодом
Ответственные
Основной ответственный Внешние стороны · Внешние стороны · Совместно Команда разработки · Разработка клиента, Команда разработки · Разработка сервера
Команда разработки: задачи
Клиент: автоматически удлинять буфер интерполяции под джиттер, дублировать отправку ввода, чтобы переживать короткие потери, показывать качество соединения. Сервер: учитывать задержку спутниковых подключений при выборе окон проверки и предела компенсации задержки, ставить таймаут, который не выкидывает игрока из-за паузы около 1 с.
Внешние стороны: задачи
Предупредить игроков, что у спутникового интернета задержка бывает большой или периодически скачет, и посоветовать для соревновательного контента по возможности использовать наземное проводное подключение.
Цифры для ориентира
Для геостационарного спутника (высота 36 000 km) один только путь сигнала через космос занимает 260 ms в одну сторону, так что туда и обратно выходит больше 520 ms (ITU-T G.114). У низкоорбитального Starlink, по официальным данным (средние значения за 15 с), медиана в часы пик в США 33 ms, и даже худший 1% (p99) ниже 65 ms (2024 год). По замерам исследователей задержка менялась в моменты перераспределения маршрута каждые 15 с, и возникали обрывы короче 1 с. В замерах бортового интернета 2018 года средняя задержка туда и обратно при спутниковом подключении составила 750 ms.
На графике
Высоко только у некоторых · RTT и джиттер (по ASN операторов спутникового интернета)
Где смотреть
Проверить, принадлежит ли ASN адреса подключения оператору спутникового интернета, и отдельно построить распределение и временной ряд RTT для его абонентов. Несколько минут подряд измерять ping до сервера с зондов RIPE Atlas в этой ASN или попросить игрока держать ping включённым и замерить интервал между скачками
Подтверждает
У геостационарных операторов RTT всегда выше 500 ms, у низкоорбитальных обычно десятки ms, но примерно каждые 15 с RTT меняется или связь ненадолго обрывается
Опровергает
Если оператор не спутниковый, а RTT всегда высокий, это «Задержка распространения (физическое расстояние)» или «Неоптимальная маршрутизация», если скачет нерегулярно, дело в сигнале Wi-Fi или мобильной сети
Чем проверить
Инструменты инфраструктуры (игровой код не нужен)
Подробнее
До низкоорбитального спутника недалеко (один участок у Starlink 1,8–3,6 ms), поэтому обычная задержка бывает близка к задержке наземных линий. Зато если точка выхода в интернет от наземной станции (PoP) далеко от игрового сервера, маршрут удлиняется, а обход через межспутниковые лазерные линии связи добавляет задержку. Исследователи считают, что колебания с периодом 15 с вызваны перераспределением маршрутов, которое происходит одновременно по всему миру, и с переключением между спутниками не связаны. Задержка бортового Wi-Fi сильно зависит от технологии (спутник или наземные базовые станции). Если используется геостационарный спутник, путь туда и обратно получается таким же долгим, как описано выше.
Источников: 5
ITU-T G.114: One-way transmission timeITU Значения для планирования: задержка распространения на спутниковом участке в одну сторону при высоте 400 km 12 ms, 14 000 km 110 ms, 36 000 km (геостационарная орбита) 260 ms
Improving Starlink’s LatencyStarlink Медиана в часы пик в США 48,5 ms → 33 ms, самый медленный 1% (p99) больше 150 ms → меньше 65 ms (2024 год), распространение на одном спутниковом участке 1,8–3,6 ms, обход по лазерным линиям связи добавляет задержку, расстояние от наземной станции до точки выхода в интернет (PoP) тоже влияет на задержку
A Multifaceted Look at Starlink Performance (WWW 2024)ACM Starlink каждые 15 с одновременно по всему миру перераспределяет маршруты, на этих границах колеблются задержка и пропускная способность и бывают обрывы короче 1 с (переключение между спутниками тут ни при чём), задержка на участке терминал ↔ спутник ↔ наземная станция около 40 ms
Probe Selection (RIPE Atlas REST API)RIPE NCC Зонды для измерений RIPE Atlas выбирают по стране, региону, ASN или диапазону адресов и запускают с них ping и traceroute
ID isp-routing · Основной ответственный Команда инфраструктуры · Сетевая инфраструктура · Совместно Внешние стороны · Внешние стороны
Из-за договоров о соединении между провайдерами трафик даже до близкого сервера идёт в обход через далёкие точки.
Почему Провайдер игрока и провайдер сервера не соединены напрямую → Следствие Трафик идёт через другую страну или другой город, растут расстояние и число устройств на пути → На экране Пинг заметно выше только у абонентов определённого провайдера
Основной ответственный Команда инфраструктуры · Сетевая инфраструктура · Совместно Внешние стороны · Внешние стороны
Команда инфраструктуры: задачи
Подключиться к нескольким провайдерам (мультихоминг), отслеживать пинг по провайдерам и находить тех, чей трафик идёт в обход, договариваться с провайдерами о корректировке маршрутов.
Внешние стороны: задачи
Попросить провайдера скорректировать маршрут.
Цифры для ориентира
Даже внутри одной страны пинг в зависимости от маршрута может отличаться в два-три раза.
На графике
Высоко с самого начала · RTT (по провайдерам и ASN)
Где смотреть
Сравнить RTT по провайдерам (ASN). По traceroute и mtr с зондов RIPE Atlas медленного провайдера или от игроков посмотреть, через какие страны и города идёт маршрут. IPv4 и IPv6 измерять отдельно (mtr -4, -6)
Подтверждает
В одном и том же регионе RTT всегда высокий только у определённого провайдера, и маршрут проходит через другую страну или далёкий город. Либо высокий только у одного семейства адресов (IPv4 или IPv6)
Опровергает
Если у всех провайдеров одинаково высокий, это «Задержка распространения (физическое расстояние)», если высокий только по вечерам, это «Перегрузка пиринга в часы пик»
Чем проверить
Инструменты инфраструктуры (игровой код не нужен)
Подробнее
Маршруты для IPv4 и IPv6 выбираются независимо, поэтому даже до одного и того же сервера один из протоколов может идти далёким обходом и работать медленнее (замеры APNIC 2016 года: внутри одного провайдера нашлись отдельные группы пользователей, у которых IPv6 медленнее IPv4 на 15 ms, 25 ms и 75 ms). Приложения с Happy Eyeballs (RFC 8305), которые из IPv6 и IPv4 выбирают тот, что подключится первым, сначала пробуют IPv6, и если IPv6 подключается в пределах рекомендованных 250 ms, IPv4 уже не пробуют. Поэтому соединение легко устанавливается по IPv6, даже если этот путь немного медленнее. Если пинг высокий только у одного провайдера, IPv4 и IPv6 измеряют по отдельности.
The Internet at the Speed of Light (HotNets 2014)ACM Реальный путь через маршрутизаторы по медиане примерно в 1,5 раза длиннее прямого оптоволоконного пути, бывают случаи, когда пакет между двумя близкими точками идёт через другую сторону земного шара (hairpinning)
Probe Selection (RIPE Atlas REST API)RIPE NCC Зонды для измерений RIPE Atlas выбирают по стране, региону, ASN или диапазону адресов и запускают с них ping и traceroute
IPv6 Performance – RevisitedAPNIC Сравнение времени туда и обратно по IPv6 и IPv4 у одних и тех же пользователей с двойным стеком: сети доступа иногда обрабатывают пакеты IPv6 совсем иначе, и внутри одного провайдера появляются группы, где IPv6 медленнее на 15 ms, 25 ms и 75 ms
ID isp-peak · Основной ответственный Команда инфраструктуры · Сетевая инфраструктура · Совместно Внешние стороны · Внешние стороны
Примерно с 21:00 до 23:00 резко растёт видеотрафик, и стыки между провайдерами (пиринг) легко перегружаются.
Почему По вечерам массово смотрят стримы и скачивают файлы → Следствие На пиринговых стыках появляются очереди и потери → На экране Только по вечерам у абонентов определённого провайдера микрофризы и телепортация
Основной ответственный Команда инфраструктуры · Сетевая инфраструктура · Совместно Внешние стороны · Внешние стороны
Команда инфраструктуры: задачи
Расширять прямые подключения к этому провайдеру, обходить перегруженные маршруты, отслеживать потери и пинг по провайдерам в вечерние часы.
Внешние стороны: задачи
Попросить провайдера расширить пиринговые стыки.
На графике
Высоко только в определённые часы · RTT и потери (по провайдерам)
Где смотреть
Построить RTT и потери по провайдерам (ASN) по часам, снять mtr вечером и днём с зондов RIPE Atlas этого провайдера или у игроков и найти участок, с которого начинаются потери
Подтверждает
Только у определённого провайдера каждый вечер примерно с 21:00 до 23:00 растут RTT и потери, а в mtr потери и задержка тянутся от стыка между провайдерами до самой цели
Опровергает
Если растёт у всех провайдеров сразу, проблема в наших линиях или серверах. Если по вечерам плохо только в одном доме, это «Перегруженный радиоканал Wi-Fi»
Probe Selection (RIPE Atlas REST API)RIPE NCC Зонды для измерений RIPE Atlas выбирают по стране, региону, ASN или диапазону адресов и запускают с них ping и traceroute
ID isp-cable · Основной ответственный Внешние стороны · Внешние стороны · Совместно Команда инфраструктуры · Сетевая инфраструктура
После обрыва подводного кабеля трафик несколько недель (иногда месяцев), пока идёт ремонт, ходит дальними обходными маршрутами, а оставшиеся линии перегружены.
Почему Обрыв кабеля или отказ оборудования → Следствие Трафик уходит на дальние обходные маршруты и оставшиеся линии → На экране У зарубежных игроков резко растёт пинг и появляются потери, это длится от нескольких дней до нескольких недель
Основной ответственный Внешние стороны · Внешние стороны · Совместно Команда инфраструктуры · Сетевая инфраструктура
Команда инфраструктуры: задачи
Иметь линии по другим маршрутам и при аварии переводить трафик на них.
Внешние стороны: задачи
Сообщить зарубежным игрокам причину и ожидаемый срок восстановления, запросить у оператора линии график ремонта.
На графике
Ступенька вверх с определённого момента · RTT (по зарубежным странам)
Где смотреть
Найти на графиках RTT и потерь по странам момент роста, сверить его со сводками интернет-сбоев Cloudflare Radar и объявлениями операторов подводных кабелей, по traceroute проверить, не идёт ли маршрут через другой континент
Подтверждает
С какого-то момента RTT для определённого зарубежного региона поднимается ступенькой и держится от нескольких дней до нескольких недель, на то же время приходятся сообщения об аварии на кабеле. Маршрут меняется на непривычно дальний обход
Опровергает
Если всё возвращается за несколько дней и сообщений об авариях нет, это «Смена маршрута BGP и сходимость» или участок сети провайдера
Чем проверить
Инструменты инфраструктуры (игровой код не нужен)
Источников: 3
AAE-1 & SMW5 cable cuts impact millions of users across multiple countriesCloudflare Для ремонта подводного кабеля нужно отправить ремонтное судно, поэтому он обычно занимает от нескольких дней до нескольких недель (в случае Тонги 38 дней), при обрыве растут задержка и потери на участке Европа–Азия
Q2 2024 Internet disruption summaryCloudflare Кабели в Красном море, повреждённые в феврале 2024 года, в июле всё ещё ремонтировались (зона конфликта), обрыв EASSy и Seacom в мае устранили за 19 дней
Q1 2024 Internet disruption summaryCloudflare Обрыв кабелей у Западной Африки (14 марта) устранили через 3–6 недель, всё это время трафик переводили на другие кабели
ID isp-bgp · Основной ответственный Команда инфраструктуры · Сетевая инфраструктура · Совместно Команда разработки · Разработка сервера, Внешние стороны · Внешние стороны
Когда в интернете меняется маршрутная информация, пакеты теряются, пока маршруты снова не сойдутся: от нескольких секунд до нескольких десятков секунд (изредка несколько минут).
Почему Меняется маршрутная информация на участке какого-то провайдера → Следствие От нескольких секунд до нескольких десятков секунд пакеты пропадают или переходят на новый маршрут → На экране Внезапный фриз на несколько секунд, после которого меняется пинг (например, 40 → 70 ms)
Основной ответственный Команда инфраструктуры · Сетевая инфраструктура · Совместно Команда разработки · Разработка сервера, Внешние стороны · Внешние стороны
Команда разработки: задачи
Таймауты, которые переживают короткие обрывы (не разрывать сразу соединение, замершее на несколько секунд).
Команда инфраструктуры: задачи
Мониторить маршруты (следить за изменениями маршрутов и пинга для наших диапазонов IP), отказы наших линий обнаруживать через BFD меньше чем за 1 с и переключаться (стандартный hold time в BGP 90–180 с), если маршрут сменился на дальний и не возвращается, переводить трафик на другую линию.
Внешние стороны: задачи
Если маршрут часто меняется на участке какого-то провайдера, попросить его выяснить причину.
На графике
Ступенька вверх с определённого момента · RTT, маршрут traceroute
Где смотреть
Сравнить маршруты traceroute и mtr до и после момента, когда изменился RTT, и посмотреть в RIPEstat BGPlay историю изменений маршрутов BGP для нашего диапазона адресов (префикса)
Подтверждает
Вместе с фризом на несколько секунд RTT переходит на другое значение, и в тот же момент есть обновления BGP и смена AS-пути
Опровергает
Если изменений маршрута не было, а RTT растёт только по вечерам, это «Перегрузка пиринга в часы пик», если плохо только части соединений, это «Неисправность одного из путей ECMP»
BGPlay (RIPEstat Data API)RIPE NCC Показывает маршруты BGP для диапазона адресов (префикса) на начало периода, обновления BGP, замеченные за этот период, и сведения об AS на пути
ID isp-ecmp · Основной ответственный Команда инфраструктуры · Сетевая инфраструктура · Совместно Команда разработки · Разработка сервера, Внешние стороны · Внешние стороны
Провайдеры и ЦОД держат несколько путей к одной цели и для каждого соединения выбирают один из них. Если неисправен только один путь, лаги постоянно бывают только у тех, кому достался этот путь.
Почему На участке из нескольких объединённых линий одна линия или одно устройство неисправно или перегружено → Следствие Путь выбирается по сочетанию адресов и портов (хешу), поэтому потери и задержка только у соединений, попавших на этот путь → На экране В одном регионе и у одного провайдера телепортация постоянно бывает только у части игроков. После переподключения иногда всё проходит
Основной ответственный Команда инфраструктуры · Сетевая инфраструктура · Совместно Команда разработки · Разработка сервера, Внешние стороны · Внешние стороны
Команда разработки: задачи
Вести статистику потерь и повторных передач по соединениям, чтобы можно было выгрузить IP, порты и время у пострадавших игроков (для TCP число повторных передач из TCP_INFO, для UDP расчёт по пропущенным номерам пакетов).
Команда инфраструктуры: задачи
Собрать IP, порты и время у пострадавших игроков и передать провайдеру или ЦОД, отслеживать потери по путям, измерять маршрут тем же протоколом и портом, что и игра (mtr --tcp или --udp с --port), если путь проходит через наше оборудование, вывести неисправную линию или устройство из группы.
Внешние стороны: задачи
Попросить провайдера проверить и заменить неисправный путь, посоветовать игрокам временно обходить проблему переподключением (если при переподключении меняется порт).
Цифры для ориентира
Если путей 4, проблема бывает примерно у четверти пользователей. Замер пинга может пойти по другому пути, чем игровой трафик, и показать норму.
На графике
Высоко только у некоторых · потери и повторные передачи по соединениям (по IP и портам)
Где смотреть
Разбить потери и повторные передачи по соединениям по IP и порту источника. Запускать mtr по UDP (-u) на игровой порт (-P) с фиксированным портом источника (-L) и повторить несколько раз с разными портами источника. Если задать только -P без -L, порт источника меняется с каждым запросом, и пути смешиваются
Подтверждает
В пределах одного региона и провайдера потери стабильно бывают только у определённых сочетаний портов (или адресов) источника, а после переподключения со сменой порта всё нормально
Опровергает
Если плохо при любом порте, это перегрузка или авария на всём участке
Чем проверить
Инструменты инфраструктуры (игровой код не нужен)
Подробнее
Чтобы пакеты одного соединения не перемешивались, оборудование (ECMP, LAG) закрепляет за каждым соединением путь по значению, вычисленному из адресов и портов, а при некоторых настройках только из адресов. Там, где учитываются только адреса, переподключение не помогает: путь остаётся тем же. Поэтому если одновременно приходят жалобы «пинг нормальный, а игра лагает» и «после перезахода стало лучше», стоит заподозрить эту причину.
mtr(8) manual page sourcemtr Опции -u (UDP), -P (порт назначения), -L (порт источника UDP), если задан только -P, в порт источника подставляется номер запроса, и он меняется с каждым запросом
ID isp-shaping · Основной ответственный Внешние стороны · Внешние стороны · Совместно Команда разработки · Разработка сервера, Команда инфраструктуры · Сетевая инфраструктура
Если превышен лимит трафика или тариф предусматривает управление определённым трафиком, пакеты задерживаются или отбрасываются.
Почему После исчерпания пакета трафика по тарифу скорость ограничена, либо ограничен определённый трафик → Следствие Пакеты ждут в очереди или отбрасываются → На экране Лаги после определённого объёма трафика, особенно в мобильной сети
Основной ответственный Внешние стороны · Внешние стороны · Совместно Команда разработки · Разработка сервера, Команда инфраструктуры · Сетевая инфраструктура
Команда разработки: задачи
Сократить игровой трафик (сжатие, отправка только нужного).
Команда инфраструктуры: задачи
Если игровой трафик задерживается или отбрасывается только у определённого провайдера, собрать данные и эскалировать провайдеру.
Внешние стороны: задачи
Попросить игроков проверить, не исчерпан ли трафик по тарифу и не ограничена ли скорость, а также не расходуют ли трафик другие приложения на том же телефоне, запросить у провайдера, не ограничивает ли он игровой трафик.
Цифры для ориентира
На корейских мобильных тарифах после исчерпания трафика скорость обычно ограничивают до 1–5 Mbps, на дешёвых тарифах до сотен kbps. Самой игре трафика нужно немного, но если на том же телефоне его тратят другие приложения, перед оборудованием, ограничивающим скорость, выстраивается очередь.
На графике
Упор в лимит (плато) · пропускная способность, RTT
Где смотреть
Попросить игрока проверить в приложении провайдера остаток трафика и наличие ограничения скорости и замерить максимальную скорость спидтестом. На стороне сервера сравнить потери и RTT по провайдерам
Подтверждает
Скорость упирается в одно значение, например 1–5 Mbps или сотни kbps, и с этого момента RTT и потери растут, когда трафик тратят другие приложения на том же телефоне. После докупки трафика или перехода на Wi-Fi проблема пропадает
Опровергает
Если ограничения скорости нет, а плохо только у определённого провайдера, это «Перегрузка пиринга в часы пик» или «Неоптимальная маршрутизация»
Чем проверить
Проверка на стороне игрока
Источников: 2
SKT, 고객 선택권과 혜택 강화한 신규 5G 요금제 출시SK텔레콤 Примеры ограничения скорости на тарифах 5G после исчерпания базового трафика: до 400 kbps, 1 Mbps, 3 Mbps
SKT, 요금제 개편SK텔레콤 После исчерпания включённого трафика интернет продолжает работать на скорости до 400 kbps (услуга «Спокойный интернет для всех»)
ID isp-udp-block · Основной ответственный Внешние стороны · Внешние стороны · Совместно Команда разработки · Разработка клиента, Команда разработки · Разработка сервера, Команда инфраструктуры · Сетевая инфраструктура
Некоторые сети блокируют отдельные UDP-адреса и порты или ограничивают скорость UDP, а оборудование инспекции пакетов (DPI) отсеивает протоколы, которые не может распознать. Игры, работающие по UDP, в таких сетях не подключаются или часто теряют соединение.
Почему Подключение из сети провайдера, который ограничивает скорость UDP, или из сети с оборудованием проверки трафика (цензуры) на уровне страны или провайдера → Следствие Блокируются отдельные UDP-адреса и порты, в часы нагрузки ограничивается скорость UDP, отсеиваются порты и протоколы не из белого списка, или пропускаются только первые несколько пакетов, а дальше включается блокировка → На экране Только у игроков из определённой страны или у определённого провайдера ошибка входа или бесконечная загрузка, дисконнект вскоре после входа, телепортация из-за потерь в часы нагрузки
Сразу после входа или техработ, Всегда, Вечерний пик
Ответственные
Основной ответственный Внешние стороны · Внешние стороны · Совместно Команда разработки · Разработка клиента, Команда разработки · Разработка сервера, Команда инфраструктуры · Сетевая инфраструктура
Команда разработки: задачи
Клиент: если по UDP не удаётся подключиться за несколько секунд, автоматически переходить на запасной путь через TCP/TLS 443, распознавать и случаи, когда соединение сначала устанавливается, но вскоре рвётся, и повторять попытку по запасному пути, писать в лог, по какому пути прошло подключение. Сервер: принимать тот же игровой протокол и по TCP 443 (TLS), подстроить таймауты, потому что на запасном пути задержка может вырасти.
Команда инфраструктуры: задачи
Перед запуском в новой стране измерить в сетях местных провайдеров, доходит ли UDP и какие потери в часы пик, разместить ближе к этой стране relay-серверы или шлюзы, принимающие запасной путь через TCP 443, отслеживать долю успешных подключений по UDP и TCP по странам и ASN, если у провайдера подтверждено ограничение скорости UDP, собрать данные и эскалировать.
Внешние стороны: задачи
Запросить у провайдера или ведомства критерии ограничения UDP и возможность их смягчить, посоветовать игрокам подключиться из другой сети и сравнить.
Цифры для ориентира
По замерам, на которые ссылается документ IETF, 3–5% сетей полностью блокируют UDP. По данным Google о QUIC (работает поверх UDP) за 2016 год, 4,4% клиентов не могли им пользоваться: UDP или QUIC был заблокирован либо MTU пути был слишком мал. В основном это были клиенты за корпоративными файрволами, а блокировки на уровне целого провайдера не встречались. Ещё 0,3% клиентов находились в сетях, которые, судя по резкому росту потерь в часы пик, ограничивали скорость UDP. После обращений к провайдерам эту долю удалось снизить с 1% в 2015 году.
На графике
Высоко только у некоторых · доля успешных подключений по UDP (по странам и ASN)
Где смотреть
Отдельно смотреть долю успешных подключений по UDP и по запасному пути TCP 443 в разрезе стран и ASN. С облачной VM в сети этого провайдера или с ПК игрока проверить подключение отдельно на игровой UDP-порт и на TCP 443 и сравнить через mtr -u -P (игровой порт) и mtr -T -P 443, с какого участка пропадают ответы
Подтверждает
Только из определённой страны или ASN по UDP нет первого ответа или соединение рвётся через несколько секунд, а TCP 443 оттуда же работает нормально. При ограничении скорости потери UDP заметно растут только в часы пик, а TCP страдает меньше
Опровергает
Если вместе с UDP не работает и TCP, смотреть аварии на маршруте, блокировку IP и «Сбои и задержки DNS». Если во всех странах одинаково, проверить настройки наших серверов и файрвола, если потери и у UDP, и у TCP только в моменты большого объёма передачи, это «Отбрасывание избытка полисером»
Чем проверить
Инструменты инфраструктуры (игровой код не нужен)
Подробнее
Оборудование DPI выбирает UDP-потоки по адресам, портам и протоколу и блокирует их, а иногда работает по белому списку и блокирует всё, кроме разрешённых протоколов (по обзору IRTF). Если оборудование судит лишь по некоторым полям пакета, блокировка может сработать даже из-за небольшого изменения протокола. На раннем этапе QUIC один файрвол после изменения одного бита в заголовке пропускал первые несколько пакетов, а следующие блокировал, и логика клиента, переключающаяся на TCP, не срабатывала. При запуске в новой стране это может проявиться в жалобах вида «в Корее всё работает, а в этой стране у части провайдеров не подключается». Если блокировка только в сети одного места, например в кафе или офисе, см. причину «Ограничения публичного Wi-Fi и корпоративной сети».
Источников: 4
RFC 9308: Applicability of the QUIC Transport ProtocolIETF По замерам 3–5% сетей полностью блокируют UDP, поэтому приложения на UDP должны либо смириться с отказом подключения, либо иметь запасной путь через TCP (TLS), порты, не связанные с зарегистрированными сервисами, файрвол может блокировать
The QUIC Transport Protocol: Design and Internet-Scale Deployment (SIGCOMM 2017)ACM 2016 год: 4,4% клиентов не могли использовать QUIC поверх UDP (блокировка UDP или QUIC либо малый MTU пути, в основном за корпоративными файрволами, блокировка целым провайдером не наблюдалась), 0,3% находились в сетях, похожих на ограничение скорости UDP (рост потерь в часы пик, после обращений к провайдерам доля снизилась с 1% в 2015 году), случай с файрволом, который после изменения 1 бита заголовка пропускал только первые несколько пакетов и блокировал остальные, из-за чего не срабатывала логика перехода на TCP
RFC 9505: A Survey of Worldwide Censorship TechniquesIRTF Оборудование инспекции в сети может выбирать потоки TCP и UDP по адресам, портам и протоколу и блокировать их (для QUIC наблюдалась блокировка UDP-эндпоинтов), блокировка всего, кроме разрешённых протоколов, ведёт к избыточной блокировке, применяется и ограничение скорости для определённого трафика
mtr(8) manual page sourcemtr -u отправляет UDP, -T отправляет TCP SYN, -P задаёт порт назначения, так маршрут измеряется тем же протоколом и портом, что и у игры
ID isp-line · Основной ответственный Внешние стороны · Внешние стороны
Плохой контакт в разъёмах, старый кабель или неисправный модем дают постоянные потери и периодические обрывы связи.
Почему Повреждённый кабель, плохой контакт, неисправность модема или оптического терминала → Следствие Пакеты отбрасываются из-за битовых ошибок, иногда связь пропадает на время от нескольких секунд до минуты, пока линия переподключается → На экране Постоянные небольшие потери, иногда фриз на несколько секунд или дисконнект
Основной ответственный Внешние стороны · Внешние стороны
Внешние стороны: задачи
Попросить игрока проверить, обрываются ли другие игры и видеозвонки, и если да, посоветовать вызвать провайдера для проверки линии.
На графике
Случайные всплески · доля потерь, журнал переподключений линии
Где смотреть
Несколько минут измерять pathping (или mtr) потери до первого участка провайдера и посмотреть время переподключений в журнале интернет-подключения (WAN) в интерфейсе роутера
Подтверждает
Даже когда линия свободна, потери стабильно начинаются с первого участка провайдера, а время переподключений в журнале роутера совпадает с моментами фризов и дисконнектов. Другие игры и видеозвонки тоже обрываются
Опровергает
Если потери начинаются на беспроводном участке до роутера, это «Помехи и слабый сигнал Wi-Fi», если на дальних участках провайдера, проблема в маршруте провайдера
pathpingMicrosoft Некоторое время пингует каждый участок, считает долю потерь по маршрутизаторам и линкам и показывает, на каком участке возникают потери
ID isp-dns · Основной ответственный Внешние стороны · Внешние стороны · Совместно Команда разработки · Разработка клиента
DNS превращает имя сервера в адрес. Если DNS отвечает медленно или с ошибкой, клиент не может найти сервер авторизации и сервер патчей.
Почему Сбой DNS провайдера или ошибка настройки → Следствие Не находятся адреса сервера авторизации и сервера патчей → На экране После нажатия кнопки входа долгое ожидание или ошибка входа. У тех, кто уже в игре, всё нормально
Основной ответственный Внешние стороны · Внешние стороны · Совместно Команда разработки · Разработка клиента
Команда разработки: задачи
Кэшировать адреса (запоминать адрес сервера, к которому последний раз удалось подключиться), держать несколько DNS (если один не ответил, повторить запрос через другой).
Внешние стороны: задачи
Посоветовать игрокам попробовать другой DNS, например публичный.
На графике
Высоко только у некоторых · число неудачных входов (по провайдерам), время DNS-запроса
Где смотреть
Через Resolve-DnsName -Server (или nslookup) запросить имя сервера авторизации у DNS провайдера и у публичного DNS и сравнить время ответа и результат
Подтверждает
Только DNS провайдера не отвечает или отвечает долго, а с публичным DNS вход проходит сразу. У игроков, которые уже в игре, всё нормально
Опровергает
Если любой DNS сразу выдаёт адрес, а войти не получается, проблема в маршруте, файрволе или сервере
Cloudflare 1.1.1.1 Incident on July 14, 2025Cloudflare Публичный DNS-резолвер не работал 62 минуты, и для пользователей, которые не могли разрешать имена, практически все интернет-сервисы стали недоступны
ID isp-ddos-path · Основной ответственный Команда инфраструктуры · Сетевая инфраструктура · Совместно Внешние стороны · Внешние стороны
Массированная атака на игровую компанию или на другого клиента в той же сети забивает общие линии связи.
Почему Появляется огромный объём атакующего трафика → Следствие Задерживается и отбрасывается даже нормальный трафик на тех же линиях → На экране У многих игроков одновременно телепортация, дисконнекты, ошибки входа
Основной ответственный Команда инфраструктуры · Сетевая инфраструктура · Совместно Внешние стороны · Внешние стороны
Команда инфраструктуры: задачи
Подключить сервис защиты от DDoS, при атаке уводить трафик в обход, скрывать адреса серверов (ставить их за защитным оборудованием, чтобы реальные адреса не были видны).
Внешние стороны: задачи
Если атака направлена на другого клиента той же сети, попросить провайдера заблокировать её на вышестоящем участке.
На графике
Упор в лимит (плато) · входящий трафик линии (bps, pps), дропы на интерфейсе
Где смотреть
Посмотреть входящий трафик и число отброшенных пакетов на интерфейсах наших линий и оборудования, а также журнал обнаружения атак сервиса защиты от DDoS рядом с моментами массовых обрывов
Подтверждает
Входящий трафик упирается в ёмкость линии и выходит на плато, растут дропы, и в то же время игроки из разных регионов и у разных провайдеров разом получают телепортацию и дисконнекты
Опровергает
Если у линии есть запас, а плохо только у части провайдеров, проблема в перегрузке или маршрутах на участках провайдеров
Чем проверить
Инструменты инфраструктуры (игровой код не нужен)
Источников: 3
Infrastructure layer attacksAWS Массированные атаки вроде UDP-отражения или SYN-флуда переполняют ёмкость сети или занимают ресурсы файрволов и балансировщиков нагрузки
Obfuscating AWS resources (BP1, BP4, BP5)AWS Ставить перед origin-серверами edge-сервисы вроде CloudFront и балансировщиков нагрузки, чтобы серверы не были видны напрямую
RFC 7999: BLACKHOLE CommunityIETF BGP-сообщество BLACKHOLE, которым соседнему провайдеру сообщают, что трафик на определённый адрес нужно отбрасывать
ID isp-cgnat · Основной ответственный Команда разработки · Разработка клиента · Совместно Команда разработки · Разработка сервера, Команда инфраструктуры · Сетевая инфраструктура
В мобильных сетях и у некоторых провайдеров один IP делят много абонентов, а записи NAT для неактивных соединений быстро удаляются.
Почему Оборудование провайдера ведёт таблицу сессий для огромного числа абонентов → Следствие Лимит таблицы сессий, короткий таймаут простоя → На экране Дисконнект после бездействия, ложные срабатывания, при которых блокируются сразу все игроки с одним IP
Основной ответственный Команда разработки · Разработка клиента · Совместно Команда разработки · Разработка сервера, Команда инфраструктуры · Сетевая инфраструктура
Команда разработки: задачи
Клиент: слать хартбиты с интервалом не больше половины самого короткого таймаута простоя (в мобильных сетях он бывает около 30 с), причём слать должен именно клиент, потому что запись CGNAT у провайдера надёжно обновляется только исходящими изнутри пакетами, при обрыве автоматически переподключаться. Сервер: отвечать на хартбиты и первым закрывать соединение, если их нет определённое время, подхватывать игрока по токену сессии, даже если после смены записи NAT изменились адрес и порт, осторожно применять блокировки по IP, потому что один IP могут делить много людей (решать вместе с признаками аккаунта и устройства).
Команда инфраструктуры: задачи
Подстроить лимиты файрвола и защиты от DDoS на число соединений с одного IP и число новых соединений в секунду под общие IP провайдеров (для диапазонов мобильных операторов поднять пороги или сделать исключение).
Цифры для ориентира
В мобильных сетях таймаут простоя для UDP бывает около 30 с.
На графике
Массовый обрыв соединений · число обрывов (таймаут хартбита), время бездействия перед обрывом (по провайдерам)
Где смотреть
Посмотреть в логах подключений, сколько аккаунтов одновременно подключено с одного IP и какой это провайдер (ASN), собрать по провайдерам время бездействия у соединений, оборвавшихся после простоя. На стороне игрока проверить адрес интернет-подключения (WAN) в интерфейсе роутера
Подтверждает
В диапазонах мобильных операторов с одного IP подключено несколько аккаунтов, а время бездействия перед обрывом короткое, в основном около 30–60 с. WAN-адрес роутера из 100.64.0.0/10 (общие адреса для NAT провайдера) или отличается от адреса, который видит сервер
Опровергает
Если обрывы скапливаются у пользователей домашних роутеров независимо от провайдера, это «Истечение записи в таблице NAT»
ID isp-vpn · Основной ответственный Внешние стороны · Внешние стороны · Совместно Команда инфраструктуры · Сетевая инфраструктура, Команда разработки · Разработка сервера
С включённым VPN или игровым ускорителем пакеты идут через промежуточные серверы этого сервиса. Если такой сервер далеко или перегружен, соединение становится даже медленнее, чем без него.
Почему VPN или ускоритель направляет все игровые пакеты через промежуточный сервер → Следствие Добавляются расстояние до промежуточного сервера и его перегрузка, а из-за заголовков туннеля уменьшается MTU (максимальный размер пакета за одну передачу) → На экране Рост пинга и потери, ошибка входа из-за блокировки вместе с другими пользователями того же промежуточного адреса
Основной ответственный Внешние стороны · Внешние стороны · Совместно Команда инфраструктуры · Сетевая инфраструктура, Команда разработки · Разработка сервера
Команда разработки: задачи
Держать UDP-пакеты не больше 1 200 байт (чтобы не было фрагментации, даже когда заголовки туннеля уменьшают MTU), решения о блокировке по IP принимать с учётом общих промежуточных адресов VPN и ускорителей, вместе с признаками аккаунта и устройства.
Команда инфраструктуры: задачи
Если много зарубежных игроков, ставить свои точки подключения ближе к ним, проверять маршруты провайдеров, от абонентов которых массово приходят жалобы вида «с ускорителем стало лучше».
Внешние стороны: задачи
Посоветовать игрокам выключить VPN или ускоритель и сравнить.
Цифры для ориентира
Близкий промежуточный сервер добавляет единицы ms, обход через другую страну добавляет от десятков до более чем 100 ms.
На графике
Высоко только у некоторых · RTT (по игрокам), владелец IP подключения
Где смотреть
Проверить, принадлежит ли ASN адреса подключения VPN-сервису, ускорителю или хостинг-провайдеру, попросить игрока выключить VPN или ускоритель и сравнить пинг и traceroute
Подтверждает
RTT и потери растут или вход блокируется только с включённым VPN или ускорителем, а в traceroute виден участок через промежуточный сервер
Опровергает
Если с VPN или ускорителем и без них одинаково, дело в линии или участке провайдера. Если с ними лучше, проблема в обычном маршруте провайдера («Неоптимальная маршрутизация», «Перегрузка пиринга в часы пик»)
Чем проверить
Проверка на стороне игрока
Подробнее
И наоборот, если маршрут провайдера плохой, ускоритель может пустить трафик лучшим путём, и пинг снизится. Жалобы «с ускорителем стало лучше» указывают на проблемы маршрутов провайдера, например неоптимальную маршрутизацию или вечернюю перегрузку.
Azure network round-trip latency statisticsMicrosoft Azure Сколько добавляет к времени туда и обратно узел в другой стране: Сеул–Токио 30 ms, Сеул–Гонконг 39 ms, Сеул–Сингапур 68 ms
ID dc-firewall · Основной ответственный Команда инфраструктуры · Сетевая инфраструктура · Совместно Команда разработки · Разработка сервера, Команда разработки · Разработка клиента
Файрвол записывает каждое пропущенное соединение в таблицу сессий и отслеживает его. Когда таблица заполнена, новые соединения принять нельзя.
Почему Из-за наплыва подключений или атаки число сессий достигает лимита → Следствие Для нового соединения нет свободной записи, и оно отклоняется → На экране У тех, кто пытается войти, ошибка входа или бесконечная загрузка, у части уже установленных соединений тоже дисконнект
Сразу после входа или техработ, При наплыве игроков
Ответственные
Основной ответственный Команда инфраструктуры · Сетевая инфраструктура · Совместно Команда разработки · Разработка сервера, Команда разработки · Разработка клиента
Команда разработки: задачи
Сервер: сдерживать наплыв подключений очередью на вход, переиспользовать соединения вместо повторяющихся коротких, первым закрывать соединения без хартбитов (чтобы мёртвые соединения не занимали таблицу сессий надолго). Клиент: слать хартбиты с интервалом не больше половины самого короткого таймаута простоя, при обрыве автоматически переподключаться, увеличивая интервал между попытками и добавляя случайный разброс (чтобы игроки не возвращались все разом).
Команда инфраструктуры: задачи
Увеличить таблицу сессий, быстрее удалять завершившиеся короткие соединения (сократить таймаут для закрытых сессий), при сокращении таймаута простоя сообщать новое значение команде разработки, чтобы подстроить интервал хартбитов, блокировать атаки, поставить алерт на заполнение таблицы сессий.
На графике
Упор в лимит (плато) · число сессий файрвола, число неудачных новых подключений
Где смотреть
Вывести на график число одновременных сессий файрвола вместе с лимитом и найти в логах устройства записи об отброшенных пакетах, для которых не удалось создать сессию. На файрволе Linux сравнить nf_conntrack_count с nf_conntrack_max и поискать в dmesg «nf_conntrack: table full, dropping packet», на инстансе AWS смотреть conntrack_allowance_exceeded в ethtool -S
Подтверждает
С момента, когда число сессий упирается в лимит и выходит на плато, растёт число неудачных новых подключений, а вместе с ним записи об ошибках создания сессий или счётчик отброшенных пакетов
Опровергает
Если сессий намного меньше лимита, а войти нельзя, это «Переполнение очереди подключений (backlog)» или сервер авторизации. Если рвутся только неактивные соединения, это «Истечение отслеживания соединений в облачной группе безопасности»
Чем проверить
Инструменты инфраструктуры (игровой код не нужен)
Источников: 5
Netfilter Conntrack Sysfs variablesLinux kernel Максимальное число записей в таблице conntrack (nf_conntrack_max), время хранения закрывающихся соединений (TIME_WAIT и FIN_WAIT по умолчанию 120 с), установленных TCP-соединений по умолчанию 5 дней, текущее число записей (nf_conntrack_count)
Amazon EC2 security group connection trackingAWS При превышении числа соединений, которые инстанс может отслеживать, пакеты новых соединений отбрасываются, неактивные соединения могут исчерпать таблицу отслеживания
Infrastructure layer attacksAWS Атаки вроде SYN-флуда занимают ресурсы серверов, файрволов и балансировщиков нагрузки
ID dc-ddos · Основной ответственный Команда инфраструктуры · Сетевая инфраструктура · Совместно Команда разработки · Разработка сервера
Когда для отражения атаки трафик заворачивают через центр очистки, маршрут удлиняется, а нормальных пользователей защита иногда принимает за атаку и блокирует.
Почему После обнаружения атаки (или постоянно) входящий трафик идёт в обход через центр очистки → Следствие Маршрут удлиняется, часть нормальных пакетов признаётся атакой → На экране Пинг растёт у всех, ошибка входа только в отдельных регионах или у отдельных провайдеров
Основной ответственный Команда инфраструктуры · Сетевая инфраструктура · Совместно Команда разработки · Разработка сервера
Команда разработки: задачи
Описать профиль игрового трафика (порты, размер пакетов, пакеты в секунду) и передать команде инфраструктуры, держать UDP-пакеты не больше 1 200 байт.
Команда инфраструктуры: задачи
Настроить правила защиты под профиль игрового трафика, использовать региональные узлы очистки, уменьшить размер TCP-пакетов на участке туннеля (MSS clamping), проверять ложные срабатывания по доле неудачных подключений в разрезе регионов и провайдеров.
Цифры для ориентира
Если узел очистки в той же стране, добавляются единицы ms, если в другой, от 30 до более чем 100 ms. Обычно в обход идёт только входящий трафик, а ответы сервера уходят напрямую. Если очищенный трафик возвращается через туннель, уменьшается и максимальный размер пакета (MTU), и это может привести к тому, что пропадают только большие пакеты.
На графике
Ступенька вверх с определённого момента · RTT (пинг), доля неудачных подключений по регионам и провайдерам
Где смотреть
Наложить на одну временную шкалу записи о включении и выключении перенаправления (очистки) в оборудовании или сервисе защиты, логи блокировок, график RTT и долю неудачных подключений по регионам и провайдерам. Из проблемного региона проверить через mtr и traceroute, не появился ли на маршруте узел очистки
Подтверждает
В момент включения перенаправления RTT поднимается ступенькой и держится, а после выключения возвращается. Либо в логе блокировок есть адреса нормальных игроков, и доля неудачных подключений растёт только в этом регионе или у этого провайдера
Опровергает
Если RTT растёт, когда записей о перенаправлении и блокировках нет, это «Неоптимальная маршрутизация» или «Смена маршрута BGP и сходимость». Если пропадают только большие пакеты, это «Несовпадение MTU (пропадают только большие пакеты)»
Чем проверить
Инструменты инфраструктуры (игровой код не нужен)
Источников: 2
Maximum transmission unit and maximum segment sizeCloudflare Входящий трафик после очистки доставляется через GRE-туннель (MTU 1 476), исходящие ответы идут сразу в интернет (DSR), TCP MSS рекомендуется ограничить до 1 436, иначе большие пакеты отбрасываются или фрагментируются
Azure network round-trip latency statisticsMicrosoft Azure Время туда и обратно в зависимости от расположения узла: Сеул–регион Пусан 8 ms, Сеул–Токио 30 ms, Сеул–Сингапур 68 ms
ID dc-lb-idle · Основной ответственный Команда инфраструктуры · Сетевая инфраструктура · Совместно Команда разработки · Разработка клиента, Команда разработки · Разработка сервера
Балансировщик нагрузки удаляет неактивное соединение через определённое время. Игра считает, что соединение живо, и в итоге получает дисконнект.
Почему Игрок какое-то время не отправляет ни одного пакета (окно чата, отошёл от компьютера) → Следствие Балансировщик удаляет неактивное соединение (типичные значения по умолчанию 60–350 с) → На экране Дисконнект в момент, когда игрок снова начинает двигаться
Основной ответственный Команда инфраструктуры · Сетевая инфраструктура · Совместно Команда разработки · Разработка клиента, Команда разработки · Разработка сервера
Команда разработки: задачи
Клиент: слать хартбиты с интервалом не больше половины самого короткого таймаута простоя (за ALB с 60 с не реже раза в 30 с), при обрыве автоматически переподключаться. Сервер: отвечать на хартбиты и первым закрывать соединение, если их нет определённое время, подхватывать игрока по токену сессии.
Команда инфраструктуры: задачи
Проверить таймаут простоя балансировщиков на пути, сообщить значение команде разработки и при необходимости увеличить.
Цифры для ориентира
Значения по умолчанию: AWS ALB 60 с, NLB 350 с для TCP и 120 с для UDP, Azure Load Balancer 4 мин для TCP. Значения TCP у ALB и NLB можно изменить, а 120 с для UDP у NLB изменить нельзя. По истечении таймаута ALB закрывает и соединение со стороны сервера, а NLB удаляет его молча, и сервер часто об этом не знает.
На графике
Массовый обрыв соединений · число обрывов, время бездействия перед обрывом
Где смотреть
Проверить настройку таймаута простоя у балансировщиков на пути и собрать для каждого оборвавшегося соединения время от последнего пакета до обрыва. Для AWS NLB смотреть также TCP_ELB_Reset_Count в CloudWatch (число RST, отправленных балансировщиком)
Подтверждает
Время бездействия у оборвавшихся соединений скапливается сразу после настроенного значения (ALB 60 с, NLB 350 с для TCP и т. д.), и проблема воспроизводится, если простоять без действий дольше этого времени и затем двинуться. У NLB в этот момент растёт TCP_ELB_Reset_Count
Опровергает
Если обрывы не зависят от времени бездействия, причина в другом. Если на серверах без балансировщика обрывы скапливаются около 350 с, это «Истечение отслеживания соединений в облачной группе безопасности», если дело в домашнем роутере игрока, это «Истечение записи в таблице NAT»
Чем проверить
Инструменты инфраструктуры (игровой код не нужен)
Источников: 4
Edit attributes for your Application Load BalancerAWS Таймаут простоя ALB по умолчанию 60 с (1–4 000 с), если соединения с клиентом и с целевым сервером всё это время молчат, балансировщик закрывает соединение
Network Load BalancersAWS Таймаут простоя NLB для TCP по умолчанию 350 с (60–6 000 с), по его истечении NLB просто перестаёт отслеживать соединение и на последующие данные отвечает RST, 120 с для UDP-потоков изменить нельзя
Configure load balancer TCP reset and idle timeoutMicrosoft Azure Таймаут простоя Azure Load Balancer по умолчанию 4 мин (4–100 мин), после него сохранение сессии не гарантируется, отправка TCP reset включается отдельно
ID dc-cloud-conntrack · Основной ответственный Команда инфраструктуры · Серверная инфраструктура · Совместно Команда разработки · Разработка клиента, Команда разработки · Разработка сервера
Файрвол облачного сервера (группа безопасности) тоже отслеживает соединения, и запись о неактивном соединении истекает через заданное время. Поэтому даже на сервере, к которому подключаются напрямую без балансировщика, игрок после бездействия может получить дисконнект.
Почему Группа безопасности настроена так, что отслеживает игровые соединения (разрешены только определённые адреса, ограничены исходящие правила, трафик идёт через NLB и т. п.) → Следствие Запись о соединении, которое какое-то время неактивно, истекает, и последующие пакеты группа безопасности молча отбрасывает → На экране После отлучки игрок двигается, но ответа нет, затем дисконнект. Серверная программа долго ничего не замечает
Основной ответственный Команда инфраструктуры · Серверная инфраструктура · Совместно Команда разработки · Разработка клиента, Команда разработки · Разработка сервера
Команда разработки: задачи
Клиент: слать хартбиты с интервалом не больше половины самого короткого таймаута простоя (при 350 с для TCP не реже раза в 175 с, при 180 с для UDP-потока не реже раза в 90 с), при обрыве автоматически переподключаться. Сервер: отвечать на хартбиты и первым закрывать соединение, если их нет определённое время, подхватывать игрока по токену сессии.
Команда инфраструктуры: задачи
Проверить время отслеживания соединений на инстансе (TcpEstablishedTimeout) и при необходимости увеличить (для UDP максимум 180 с, больше нельзя), рассмотреть конфигурацию группы безопасности без отслеживания (игровой порт открыт для всех адресов, исходящие правила разрешают всё. Соединения через NLB всё равно отслеживаются), при переходе на новое поколение инстансов проводить тест с бездействием.
Цифры для ориентира
В AWS типы инстансов Nitro v6 по умолчанию удаляют запись о неактивном TCP-соединении через 350 с (остальные типы через 5 дней). Для UDP по умолчанию 180 с для потоков с многократным обменом запросами и ответами (stream) и 30 с для потоков в одну сторону или с единственной парой запрос–ответ.
На графике
Массовый обрыв соединений · число обрывов, время бездействия перед обрывом
Где смотреть
Проверить настройку времени отслеживания соединений на инстансе и правила группы безопасности (создают ли они отслеживание), собрать время бездействия у оборвавшихся соединений. Сразу после обрыва посмотреть на сервере через ss -tnoi, остаётся ли соединение в ESTABLISHED с работающим таймером повторной передачи (timer:(on,…)) и растущим backoff
Подтверждает
Время бездействия у оборвавшихся соединений скапливается сразу после 350 с для TCP, 180 с для UDP-потока, 30 с для UDP в одну сторону, а сокет на стороне сервера, не заметив обрыва, остаётся в ESTABLISHED (если серверу есть что отправить, он только повторяет передачу)
Опровергает
Если группа безопасности настроена без отслеживания (игровой порт открыт для всех адресов, исходящие правила разрешают всё, NLB на пути нет), причина в другом. Если трафик идёт через NLB, сравнить значения с таймаутом из причины «Таймаут простоя балансировщика»
Чем проверить
Инструменты инфраструктуры (игровой код не нужен)
Источников: 3
Amazon EC2 security group connection trackingAWS Отслеживание неактивных TCP-соединений по умолчанию 350 с (Nitro v6, у остальных 432 000 с = 5 дней), UDP в одну сторону 30 с, stream 180 с (максимум 180), при правилах «разрешить все адреса» отслеживания нет, соединения через NLB отслеживаются всегда
ss(8) — Linux manual pageiproute2 timer:(on,…) в выводе -o означает таймер повторной передачи, backoff в выводе -i показывает, сколько раз ожидание перед повтором удваивалось
ID dc-nat-gateway · Основной ответственный Команда инфраструктуры · Сетевая инфраструктура · Совместно Команда разработки · Разработка сервера
Исходящие соединения серверов из частной подсети во внешний мир (авторизация на платформе, платежи, внешние API) проходят через NAT-шлюз, который подменяет адрес и порт. Если одновременных соединений к одной цели больше, чем позволяет лимит портов шлюза, новые соединения не устанавливаются.
Почему Серверы открывают много коротких соединений к одному внешнему адресу, например к авторизации на платформе или платёжному сервису, или долго держат соединения открытыми → Следствие NAT-шлюз не может выделить для этой цели ещё один исходный порт, и новое соединение не устанавливается → На экране В самой игре всё нормально, но функции, которые обращаются наружу (вход, платежи, выдача наград), не работают или тормозят (ошибка входа / бесконечная загрузка, съеденные действия / роллбэк)
Сразу после входа или техработ, Вечерний пик, При наплыве игроков
Ответственные
Основной ответственный Команда инфраструктуры · Сетевая инфраструктура · Совместно Команда разработки · Разработка сервера
Команда разработки: задачи
Переиспользовать соединения к внешним API (HTTP keep-alive, пул соединений) и не открывать новое соединение на каждый запрос, для неактивных соединений в пуле слать keepalive чаще таймаута простоя NAT (350 с у AWS) или закрывать их первыми, при ошибках повторять с растущим интервалом и случайным разбросом, записывать долю ошибок и задержку по каждому внешнему вызову.
Команда инфраструктуры: задачи
Добавить IP-адреса на NAT-шлюз (к публичному NAT-шлюзу AWS по умолчанию можно привязать только 2 Elastic IP, для большего нужно запросить повышение квоты), разделить шлюзы по зонам доступности и подсетям, поставить алерты на метрики ошибок выделения портов (AWS ErrorPortAllocation, Failed в Azure SNAT Connection Count, OUT_OF_RESOURCES в Google Cloud dropped_sent_packets_count), в Google Cloud NAT увеличить минимум портов на VM или включить динамическое выделение портов.
Цифры для ориентира
AWS NAT Gateway с одного IP-адреса открывает до 55 000 одновременных соединений к одной цели (IP, порт, протокол), а добавляя IP (до 8), этот предел можно поднять. Соединение, молчавшее 350 с, удаляется, и на последующие пакеты по нему возвращается RST. У Azure NAT Gateway на один публичный IP приходится 64 512 портов SNAT (не больше 16 IP). Google Cloud NAT делит 64 512 портов одного NAT IP между VM, а минимум портов на VM по умолчанию 64 (статическое выделение), поэтому при настройках по умолчанию одна VM обычно может держать к одной цели не больше 64 одновременных соединений.
На графике
Упор в лимит (плато) · число одновременных соединений NAT-шлюза, число ошибок выделения портов
Где смотреть
Сопоставить с моментами ошибок внешних вызовов на игровых серверах метрики NAT-шлюза в CloudWatch для AWS: ErrorPortAllocation, ActiveConnectionCount, PacketsDropCount (в Azure SNAT Connection Count с фильтром по состоянию Failed и Dropped Packets, в Google Cloud dropped_sent_packets_count с reason OUT_OF_RESOURCES)
Подтверждает
В моменты ошибок внешних вызовов ErrorPortAllocation (в Azure SNAT Connection Count в состоянии Failed, в Google Cloud отбрасывания OUT_OF_RESOURCES) больше 0, а ошибки сосредоточены на вызовах к одной-двум целям с большим числом соединений, например к серверам авторизации или платежей
Опровергает
Если ошибок выделения портов 0, а connect на игровом сервере завершается с EADDRNOTAVAIL и число TIME_WAIT близко к размеру диапазона эфемерных портов, это «Исчерпание эфемерных портов в межсерверных соединениях». Если соединение устанавливается, но ответ медленный, это «Зависимость от внешних сервисов»
Чем проверить
Инструменты инфраструктуры (игровой код не нужен)
Подробнее
Причина «Исчерпание эфемерных портов в межсерверных соединениях» описывает нехватку портов на одном сервере, а здесь лимит действует на NAT-шлюзе и делится между всеми серверами за ним (Google Cloud NAT распределяет порты по VM). Если на серверах TIME_WAIT и диапазон эфемерных портов в порядке, а сбоят только внешние вызовы, причина здесь. Порт закрытого соединения тоже не сразу снова используется для той же цели (у Azure период охлаждения, у Google Cloud порт недоступен на время TIME_WAIT), поэтому чем чаще открываются короткие соединения, тем быстрее достигается лимит.
Источников: 7
NAT gateway basicsAWS 55 000 одновременных соединений к одной цели (IP, порт и протокол назначения) на один IPv4-адрес, предел поднимается добавлением IP до 8 (у публичного NAT-шлюза по умолчанию 2 Elastic IP, больше по запросу на повышение квоты); полоса автоматически растёт с 5 до 100 Gbps, а производительность с 1 до 10 млн пакетов в секунду, сверх этого предела пакеты отбрасываются
NAT gateway metrics and dimensionsAWS ErrorPortAllocation: сколько раз не удалось выделить исходный порт (больше 0 означает слишком много одновременных соединений), ActiveConnectionCount, IdleTimeoutCount (соединения, закрытые после 350 с простоя), PacketsDropCount
Troubleshoot NAT gatewaysAWS После 350 с простоя соединение истекает, и на последующую отправку возвращается RST, рекомендуется keepalive чаще 350 с, при достижении лимита соединений добавить шлюзы по зонам доступности и IP или сократить число соединений
Source Network Address Translation (SNAT) with Azure NAT GatewayMicrosoft Azure 64 512 портов SNAT на один публичный IP (не больше 16 IP), каждому соединению к одной цели нужен отдельный порт, закрытый порт проходит период охлаждения перед повторным использованием для той же цели
Metrics and alerts for Azure NAT GatewayMicrosoft Azure Если SNAT Connection Count с фильтром по состоянию Failed больше 0, вероятно исчерпание портов SNAT, Dropped Packets
IP addresses and portsGoogle Cloud На один NAT IP по 64 512 портов для TCP и для UDP, минимум портов на VM по умолчанию 64 (статическое выделение) и 32 (динамическое), число зарезервированных за VM портов ограничивает число одновременных соединений к одной цели, порт закрытого соединения нельзя использовать на время TIME_WAIT
Logs and metricsGoogle Cloud dropped_sent_packets_count с reason OUT_OF_RESOURCES: пакеты, отброшенные из-за нехватки NAT IP или портов
ID dc-lb-imbalance · Основной ответственный Команда инфраструктуры · Сетевая инфраструктура · Совместно Команда разработки · Разработка сервера
Соединения скапливаются на одном сервере, или балансировщик продолжает отправлять игроков на уже упавший сервер.
Почему Правило распределения не подходит, или health check (проверка работоспособности) не видит реального состояния → Следствие Перегружен только один сервер, или подключения идут на упавший сервер → На экране Только в части каналов или у части игроков слоумо, ошибка входа или бесконечная загрузка
Сразу после входа или техработ, При наплыве игроков
Ответственные
Основной ответственный Команда инфраструктуры · Сетевая инфраструктура · Совместно Команда разработки · Разработка сервера
Команда разработки: задачи
Реализовать health check, который отвечает на запрос балансировщика по реальному состоянию игры (идут ли тики, есть ли соединение с БД), и сообщать заодно нагрузку сервера.
Команда инфраструктуры: задачи
Перевести health check на проверку реального ответа игры, распределять по нагрузке серверов, отслеживать разницу в числе соединений между серверами.
На графике
Высоко только у некоторых · число соединений и загрузка CPU по серверам
Где смотреть
Наложить на один график число соединений (ss -s) и загрузку CPU каждого сервера за балансировщиком и сравнить статус health check целей на балансировщике (в AWS HealthyHostCount и UnHealthyHostCount в CloudWatch) с реальным состоянием игровых серверов
Подтверждает
У одного-двух серверов число соединений и CPU намного выше, чем у остальных, или сервер с остановившимися тиками числится «исправным» и продолжает принимать новые подключения
Опровергает
Если соединения распределены по серверам ровно, а тормозит только один канал, дело в нагрузке внутри этого канала («Перегрузка однопоточной локации (хотспот)»)
Load Balancing in the DatacenterGoogle При простом round robin загрузка CPU между задачами расходится до 2 раз, взвешенное распределение, при котором бэкенд передаёт свою нагрузку в ответах и health check, состояние lame duck, в котором бэкенд просит больше не присылать ему запросы
Health checks for Network Load Balancer target groupsAWS Health check по умолчанию раз в 30 с, после 2 неудач цель исключается, UDP-сервисы проверяются через TCP или HTTP health check, поэтому рекомендуется настроить проверку так, чтобы она отражала реальное состояние сервиса
ID dc-microburst · Основной ответственный Команда разработки · Разработка сервера · Совместно Команда инфраструктуры · Сетевая инфраструктура, Команда инфраструктуры · Серверная инфраструктура
Когда несколько серверов в один и тот же момент разом отправляют пакеты тысячам игроков, маленький буфер порта коммутатора, где сходится этот трафик, переполняется меньше чем за 1 ms.
Почему Появление мирового босса, массовое умение или совпавшие во времени тики нескольких серверов, и всё отправляется разом → Следствие Буфер (от сотен KB до нескольких MB на порт) там, где несколько портов сходятся в один или быстрый порт переходит в медленный, мгновенно заполняется → На экране Часть пакетов отбрасывается, у многих игроков одновременно телепортация и съеденные умения
Основной ответственный Команда разработки · Разработка сервера · Совместно Команда инфраструктуры · Сетевая инфраструктура, Команда инфраструктуры · Серверная инфраструктура
Команда разработки: задачи
Распределять отправку равномерно внутри тика (пейсинг), немного сдвигать начало тика на разных серверах.
Команда инфраструктуры: задачи
Сеть: коммутаторы с большими буферами, распределение трафика (разносить серверы по разным коммутаторам и портам), мониторинг счётчиков отбрасывания по портам коммутаторов. Серверы и ОС: ограничить общую скорость отправки сервера (шейпер tc в Linux).
Цифры для ориентира
Порт 10 Gbps за 1 ms может отправить около 1,25 MB. Если трафик двух портов одновременно сходится в один, каждую миллисекунду в очереди прибавляется 1,25 MB. Даже при средней загрузке 10% за секунду на интервале 1 ms порт может переполняться.
На графике
Растёт вслед за онлайном и нагрузкой · выходные отбрасывания на портах коммутатора
Где смотреть
Собирать с минимально возможным интервалом счётчики выходных отбрасываний (ifOutDiscards, на некоторых устройствах output drops) на портах коммутатора, к которым подключены серверы, и на портах, где сходится их трафик, и сопоставлять с моментами появления босса и массовых боёв. На графиках средней загрузки за 1 с или 1 мин этого не видно
Подтверждает
Средняя загрузка низкая, но каждый раз, когда игроки собираются в одном месте, растут выходные отбрасывания, и в эти же моменты многие игроки одновременно жалуются на телепортацию и съеденные умения
Опровергает
Если отбрасывания стабильно растут в часы высокой средней загрузки, это «Перегрузка линии связи ЦОД». Если растут ошибки приёма (CRC), это «Неисправный кабель и ошибки порта»
Data Center TCP (DCTCP) (SIGCOMM 2010)ACM У типовых коммутаторов неглубокие буферы (48 портов делят 4 MB, один порт может занять около 700 KB), если несколько потоков на короткое время сходятся в один порт, возникают потери
RFC 2863: The Interfaces Group MIBIETF ifOutDiscards: число пакетов, которые не были отправлены и отброшены без ошибок, например чтобы освободить место в буфере
Основной ответственный Команда инфраструктуры · Сетевая инфраструктура · Совместно Команда инфраструктуры · Серверная инфраструктура
Команда инфраструктуры: задачи
Сеть: приоритет игровому трафику (QoS), отдельная линия для крупных передач, алерт на загрузку линии. Серверы и ОС: ограничить скорость бэкапов, отправки логов и деплоя и запускать их в часы низкой нагрузки.
На графике
Упор в лимит (плато) · загрузка линии, RTT (пинг)
Где смотреть
Наложить на одну временную шкалу загрузку интерфейса внешней линии ЦОД (аплинка), рассчитанную по SNMP ifHCInOctets и ifHCOutOctets, выходные отбрасывания (ifOutDiscards) и расписание бэкапов, деплоя и отправки логов
Подтверждает
Загрузка линии упирается в предел пропускной способности и выходит на плато, в это время растут RTT и отбрасывания на всём сервере, и это время совпадает с крупными передачами данных
Опровергает
Если поминутная загрузка намного ниже предела, а отбрасывания есть, это «Микробёрсты на коммутаторе»
RFC 2863: The Interfaces Group MIBIETF ifHCInOctets и ifHCOutOctets: число байт, принятых и отправленных через интерфейс (64-битные счётчики), ifOutDiscards: число пакетов, отброшенных без отправки
ID dc-failover · Основной ответственный Команда инфраструктуры · Сетевая инфраструктура · Совместно Команда разработки · Разработка сервера, Команда разработки · Разработка клиента
Когда маршрутизатор или файрвол выходит из строя и трафик переключается на резервное устройство (failover), на эти несколько секунд у всех фриз.
Почему Из-за отказа или обслуживания трафик переключается на резервное устройство → Следствие Переключение занимает несколько секунд, а если состояние сессий не синхронизировано, соединения сбрасываются → На экране Одновременный фриз у всех игроков сервера, массовые дисконнекты
Основной ответственный Команда инфраструктуры · Сетевая инфраструктура · Совместно Команда разработки · Разработка сервера, Команда разработки · Разработка клиента
Команда разработки: задачи
Сервер: таймауты, которые переживают короткие обрывы (несколько секунд), при переподключении после обрыва подхватывать сессию по токену. Клиент: при обрыве автоматически переподключаться (со случайным разбросом интервала между попытками, чтобы игроки не возвращались все разом).
Команда инфраструктуры: задачи
Резервирование с общим состоянием соединений, обнаружение отказов через BFD меньше чем за 1 с, регулярные тесты переключения.
Цифры для ориентира
Если устройство сразу замечает отказ, примерно 1–3 с. Если быстрого обнаружения отказов (BFD) нет и всё держится на стандартных таймерах BGP, маршрут может быть разорван 90–180 с, пока соседнее устройство не заметит отказ.
На графике
Массовый обрыв соединений · число подключений, общий входящий и исходящий трафик сервера
Где смотреть
Посмотреть журналы событий маршрутизаторов и файрволов (смена роли VRRP, падение сессий BFD и BGP, записи о переключении на резерв) и в то же время число подключений и общий трафик серверов
Подтверждает
В момент переключения по журналу устройства трафик всех серверов за ним на несколько секунд падает до 0 или число подключений падает одновременно
Опровергает
Если подключения упали только на одном сервере, это «Падение сервера» или «Проблемы драйвера и прошивки NIC». Если журнал устройства чист, а остановилась одна облачная виртуальная машина, это «Обслуживание облачного хоста и живая миграция»
RFC 7938: Use of BGP for Routing in Large-Scale Data CentersIETF Если полагаться только на keepalive в BGP, сходимость медленная, если сразу реагировать на падение линка и разрывать сессию, отказ обнаруживается за миллисекунды и маршруты быстро сходятся заново
ID dc-bad-cable · Основной ответственный Команда инфраструктуры · Сетевая инфраструктура
Если оптический модуль или кабель неисправен, определённая доля пакетов на этом пути повреждается.
Почему Битовые ошибки из-за неисправного оптического модуля или кабеля → Следствие Повреждённые пакеты устройство молча отбрасывает → На экране Только у части серверов и игроков на этом пути постоянные потери, телепортация и откидывание назад
Основной ответственный Команда инфраструктуры · Сетевая инфраструктура
Команда инфраструктуры: задачи
Мониторить счётчики ошибок портов (CRC) и ставить алерты, менять оптические модули, кабели и другие компоненты, до замены выводить проблемный линк и пускать трафик в обход.
На графике
Высоко только у некоторых · число ошибок CRC по портам, доля потерь по серверам и путям
Где смотреть
Посмотреть счётчики CRC на обоих концах линка. На коммутаторе ошибки FCS порта (dot3StatsFCSErrors) и ошибки приёма (ifInErrors), на сервере crc в RX errors из ip -s -s link (статистика ядра rx_crc_errors)
Подтверждает
Ошибки CRC на одном порту стабильно растут независимо от объёма трафика и времени суток, и потери есть только у серверов и игроков, чей трафик идёт через этот порт
Опровергает
Если ошибок CRC нет, а растут только выходные отбрасывания, это перегрузка («Микробёрсты на коммутаторе», «Перегрузка линии связи ЦОД»)
Чем проверить
Инструменты инфраструктуры (игровой код не нужен)
Источников: 3
Understanding and Mitigating Packet Corruption in Data Center Networks (SIGCOMM 2017)ACM Анализ 350 000 линков в ЦОД: повреждения пакетов вызывают неисправные оптические модули, повреждённое волокно и грязные коннекторы, доля повреждений постоянна и не зависит от загрузки, проблемные линки выводят и ремонтируют, сохраняя нужное число путей
ID dc-mtu · Основной ответственный Команда инфраструктуры · Сетевая инфраструктура · Совместно Команда инфраструктуры · Серверная инфраструктура, Команда разработки · Разработка сервера
Если на промежуточном участке MTU (максимальный размер пакета за одну передачу) меньше, а уведомления о превышении размера блокируются, постоянно пропадают только большие пакеты.
Почему На участке туннеля или VPN MTU уменьшается → Следствие Уведомление о превышении размера (ICMP) блокирует файрвол, и отправитель о нём не знает → На экране Фриз и затем дисконнект только при открытии больших экранов вроде инвентаря или списка персонажей
При определённом действии, Сразу после входа или техработ
Ответственные
Основной ответственный Команда инфраструктуры · Сетевая инфраструктура · Совместно Команда инфраструктуры · Серверная инфраструктура, Команда разработки · Разработка сервера
Команда разработки: задачи
Чтобы снизить размер на стороне сервера, задать в сокете максимальный размер сегмента TCP_MAXSEG (одного дробления сообщений в игровом коде недостаточно), держать UDP-пакеты не больше 1 200 байт.
Команда инфраструктуры: задачи
Сеть: уменьшить размер TCP-пакетов на участке туннеля (MSS clamping), разрешить уведомления о превышении размера (ICMP) на файрволах и в сетевых ACL облака. Серверы и ОС: разрешить уведомления о превышении размера (ICMP) и в файрволе сервера, и в облачной группе безопасности, включить в ядре сервера определение MTU через tcp_mtu_probing=1 (последняя страховка, которая срабатывает, только когда соединение уже простояло несколько секунд).
Цифры для ориентира
Обычно 1 500 байт, после туннеля около 1 400.
На графике
Высоко только у некоторых · дисконнекты по регионам и провайдерам, ошибки больших ответов
Где смотреть
С ПК игрока с проблемой пинговать сервер с флагом запрета фрагментации (DF), меняя размер. В Windows ping /f /l 1472 SERVER_IP, в Linux ping -M do -s 1472 SERVER_IP (1 472 = MTU 1 500 минус 20 байт заголовка IP и 8 байт заголовка ICMP). Уменьшая размер, найти максимальный, который проходит, и проверить, разрешают ли группа безопасности и файрвол на стороне сервера ICMP-уведомления о превышении размера (Fragmentation Needed)
Подтверждает
Маленький пинг проходит, а пинг с DF размером 1 472 байта нет (ответа нет или приходит ошибка о необходимости фрагментации), и максимальный проходящий размер мал, около 1 400. У игроков из одного региона фриз только при открытии больших экранов
Опровергает
Если и пинг с DF размером 1 472 байта проходит, проблема с MTU пути исключается. Если не проходит даже маленький пинг, заблокирован сам ICMP, и этим способом ничего определить нельзя
Чем проверить
Проверка на стороне игрока
Источников: 5
RFC 2923: TCP Problems with Path MTU DiscoveryIETF Если файрвол блокирует ICMP (Fragmentation Needed), определение MTU пути не срабатывает и постоянно пропадают только большие пакеты (чёрная дыра), а пинг и мелкий обмен работают, поэтому диагностировать трудно
IP SysctlLinux kernel При tcp_mtu_probing=1 определение MTU пути для TCP обычно выключено и включается, когда обнаружена чёрная дыра ICMP
ping(8) — Linux manual pageiputils -M do ставит флаг DF и не отправляет пакеты больше MTU пути, -s задаёт размер данных (по умолчанию 56 байт плюс 8 байт заголовка ICMP)
pingMicrosoft /f ставит флаг DF и помогает найти проблемы с MTU пути, /l задаёт размер данных
ID nic-irq · Основной ответственный Команда инфраструктуры · Серверная инфраструктура
Если NIC отправляет прерывания о приходе пакетов только на одно ядро CPU, это ядро становится узким местом.
Почему Одна очередь приёма, или выключен RSS, который распределяет пакеты по нескольким ядрам → Следствие Одно ядро загружено на 100% и не успевает забирать пакеты → На экране При наплыве игроков потери и задержка на всём сервере (телепортация, задержка ввода)
Основной ответственный Команда инфраструктуры · Серверная инфраструктура
Команда инфраструктуры: задачи
Настроить RSS (распределяет NIC) и RPS (распределяет ядро ОС), распределить прерывания по нескольким ядрам, для UDP включить распределение по очередям с учётом портов (rx-flow-hash udp4 sdfn в ethtool -N), разнести ядра обработки прерываний и ядра потоков игрового тика, следить за %soft по ядрам.
Цифры для ориентира
Через сетевой стек ядра ОС одно процессорное ядро успевает обработать примерно сотни тысяч пакетов в секунду, в зависимости от размера пакетов и настроек. Если в загрузке по ядрам доля обработки приёма (%soft в mpstat) сосредоточена на одном ядре, причина именно в этом.
На графике
Упор в лимит (плато) · %soft по ядрам, входящие пакеты в секунду
Где смотреть
Посмотреть через mpstat -P ALL 1 %soft (долю времени на обработку программных прерываний) по ядрам, через /proc/interrupts, на какие ядра идут прерывания каждой очереди NIC, через ethtool -l число очередей, через ethtool -S число пакетов по очередям (названия счётчиков зависят от драйвера)
Подтверждает
У одного ядра %soft держится около 100%, остальные простаивают, прерывания и пакеты скапливаются в одной очереди. С этого момента число входящих пакетов в секунду перестаёт расти
Опровергает
Если %soft ровно распределён по ядрам, причина в другом. Если CPU простаивает, а потери есть, это «Превышен лимит PPS в облаке» или «Слишком маленький кольцевой буфер»
Чем проверить
Инструменты инфраструктуры (игровой код не нужен)
Подробнее
Даже при нескольких очередях трафик скапливается в одной, если почти весь он приходит с немногих адресов, например от шлюзов или прокси. Для UDP NIC по умолчанию иногда распределяет пакеты по очередям только по адресам, и чтобы нагрузка распределилась равномерно, нужно включить учёт портов.
Источников: 4
Scaling in the Linux Networking StackLinux kernel RSS (NIC распределяет пакеты по нескольким очередям приёма) и RPS (распределяет ядро ОС), настройка с отдельным прерыванием на каждую очередь и распределением по ядрам, если узкое место в обработке прерываний приёма, рекомендуется RSS
How to receive a million packets per secondCloudflare Замеры, в которых при одной очереди приёма на одно ядро это ядро упиралось примерно в 350–430 тыс. пакетов в секунду, случай, когда NIC хешировал UDP только по IP-адресам и весь трафик шёл в одну очередь
ID nic-ring · Основной ответственный Команда инфраструктуры · Серверная инфраструктура
Если кольцевой буфер, где NIC ненадолго держит пакеты, маленький, при резком наплыве пакетов он переполняется, и пакеты отбрасываются.
Почему Кольцевой буфер оставлен маленьким, со значением по умолчанию (256–2 048 слотов в зависимости от драйвера) → Следствие Во время всплеска трафика буфер переполняется раньше, чем CPU успевает забрать пакеты → На экране Потери только в моменты всплесков (телепортация, съеденные умения). В логах игрового сервера следов нет
Основной ответственный Команда инфраструктуры · Серверная инфраструктура
Команда инфраструктуры: задачи
Увеличить кольцевой буфер (ethtool -G), следить за счётчиками отбрасываний (rx_missed_errors и другие в ethtool -S, названия зависят от драйвера).
Цифры для ориентира
При потоке 1 млн пакетов в секунду 1 024 слота заполняются примерно за 1 ms. Достаточно CPU один раз опоздать за это время, и буфер переполнится. У большинства NIC буфер можно увеличить до нескольких тысяч слотов.
На графике
Случайные всплески · счётчик отбрасываний при приёме в NIC
Где смотреть
Собирать с коротким интервалом счётчики отбрасываний при приёме из ethtool -S (rx_missed_errors, rx_fifo_errors и т. п., названия зависят от драйвера) и missed из ip -s -s link, через ethtool -g проверить текущий и максимальный размер кольцевого буфера
Подтверждает
В моменты всплесков счётчики отбрасываний растут, а текущий размер буфера намного меньше максимального. После увеличения буфера отбрасываний становится меньше
Опровергает
Если счётчики отбрасываний не меняются, а потери есть, дело на следующем этапе в ядре ОС («Нехватка буферов сокетов в ядре») или на сетевом участке. Если %soft одного ядра 100%, это «Все прерывания NIC на одном ядре»
ID nic-coalesce · Основной ответственный Команда инфраструктуры · Серверная инфраструктура
Если ради разгрузки CPU NIC копит пакеты и сообщает о них разом, пакеты задерживаются на время накопления.
Почему NIC копит пакеты определённое время или до определённого числа и только потом сообщает о них → Следствие Пока идёт накопление, пакеты ждут → На экране Небольшой рост задержки. Обычно он мал, но при чрезмерных настройках доходит до миллисекунд
Основной ответственный Команда инфраструктуры · Серверная инфраструктура
Команда инфраструктуры: задачи
Включить адаптивное объединение, подобрать значения под игровой сервер (ethtool -C).
Цифры для ориентира
Обычно от десятков до сотен µs. Для игр это, как правило, пренебрежимо мало, но при чрезмерных настройках вырастает до миллисекунд.
На графике
Высоко с самого начала · время туда и обратно внутри одного ЦОД
Где смотреть
Посмотреть текущие настройки объединения через ethtool -c (adaptive-rx, rx-usecs, rx-frames) и сравнить время ping туда и обратно до другого сервера в том же ЦОД до и после изменения настроек
Подтверждает
rx-usecs задан большим, сотни µs и больше, и при его уменьшении время туда и обратно внутри ЦОД сокращается на ту же величину
Опровергает
Если после уменьшения время туда и обратно не меняется, причина в другом
ID nic-cloud-pps · Основной ответственный Команда инфраструктуры · Серверная инфраструктура · Совместно Команда разработки · Разработка сервера, Внешние стороны · Внешние стороны
У каждого типа облачного сервера есть лимиты пакетов в секунду и пропускной способности, и всё сверх лимита молча отбрасывается.
Почему Онлайн растёт, и число пакетов в секунду превышает лимит инстанса → Следствие Облачная сеть отбрасывает превышение → На экране Потери непонятного происхождения, телепортация, съеденные умения. При этом у CPU сервера есть запас
Основной ответственный Команда инфраструктуры · Серверная инфраструктура · Совместно Команда разработки · Разработка сервера, Внешние стороны · Внешние стороны
Команда разработки: задачи
Объединять пакеты (сообщения одного тика в одном пакете), не отправлять часто совсем мелкие пакеты.
Команда инфраструктуры: задачи
Проверять счётчики превышения лимитов (в AWS pps_allowance_exceeded, conntrack_allowance_exceeded и др.) и ставить на них алерты, переходить на более крупный инстанс, лимит отслеживания соединений обходить конфигурацией группы безопасности без отслеживания.
Внешние стороны: задачи
Запросить у облачного провайдера лимиты пакетов в секунду и отслеживания соединений для каждого типа инстансов.
Цифры для ориентира
Лимиты зависят от размера инстанса, а лимит пакетов в секунду часто не раскрывают. «До 10 Gbps» у небольших инстансов означает скорость в режиме burst, доступную только пока есть кредиты (обычно 5–60 мин), а базовая скорость намного ниже.
На графике
Упор в лимит (плато) · пакеты в секунду, счётчики превышения allowance
Где смотреть
Собирать с коротким интервалом счётчики ENA из ethtool -S: pps_allowance_exceeded, bw_in_allowance_exceeded, bw_out_allowance_exceeded, conntrack_allowance_exceeded и смотреть их вместе с числом пакетов в секунду. Можно также отправлять эти счётчики в CloudWatch через агент и ставить на них алерты
Подтверждает
В момент потерь растут счётчики превышения allowance, а число пакетов в секунду упирается в одно значение. У CPU сервера есть запас
Опровергает
Если счётчики превышения не меняются, причина в другом. Если %soft одного ядра 100%, это «Все прерывания NIC на одном ядре»
Чем проверить
Инструменты инфраструктуры (игровой код не нужен)
Подробнее
conntrack_allowance_exceeded растёт, когда таблица отслеживания соединений заполнена и новые соединения отбрасываются. Если место в таблице есть, а рвутся только неактивные соединения, у которых истекло отслеживание, смотрите причину «Истечение отслеживания соединений в облачной группе безопасности».
Источников: 2
Monitor network performance for ENA settings on your EC2 instanceAWS У каждого инстанса есть лимиты пропускной способности, PPS и отслеживания соединений, превышение сначала копится в очереди, потом отбрасывается, счётчики pps_allowance_exceeded и conntrack_allowance_exceeded
Amazon EC2 instance network bandwidthAWS «До N Gbps» у инстансов с 16 vCPU и меньше означает burst за счёт кредитов сетевого ввода-вывода (обычно 5–60 мин), когда кредиты заканчиваются, полоса возвращается к базовой
ID nic-saturate · Основной ответственный Команда разработки · Разработка сервера · Совместно Команда инфраструктуры · Серверная инфраструктура
Если карта на 1 Gbps или 10 Gbps загружена до предела, очередь отправки растёт, и в итоге пакеты отбрасываются.
Почему Из-за роста рассылки объём отправки доходит до предела карты → Следствие Очередь отправки растёт, а при переполнении пакеты отбрасываются → На экране Задержка и потери на всём сервере (задержка ввода, телепортация)
Основной ответственный Команда разработки · Разработка сервера · Совместно Команда инфраструктуры · Серверная инфраструктура
Команда разработки: задачи
Сократить объём отправки (фильтрация по зоне интереса AOI, сжатие, отправка только изменений).
Команда инфраструктуры: задачи
Нарастить сетевые карты (более быстрая NIC, в облаке более крупный инстанс), поставить алерт на загрузку NIC.
На графике
Упор в лимит (плато) · объём отправки NIC, отбрасывания при отправке
Где смотреть
Сравнить txkB/s и %ifutil (загрузку относительно скорости интерфейса) из sar -n DEV 1 со скоростью NIC и полосой инстанса и заодно посмотреть TX dropped в ip -s link
Подтверждает
Объём отправки выходит на плато около предела NIC или полосы инстанса, и с этого момента растут отбрасывания при отправке и задержка на всём сервере
Опровергает
Если запас по полосе есть, причина в другом. Если много мелких пакетов и есть потери, это «Превышен лимит PPS в облаке»
Чем проверить
Инструменты инфраструктуры (игровой код не нужен)
Источников: 3
Interface statisticsLinux kernel tx_dropped: число пакетов, отброшенных при отправке из-за нехватки ресурсов
ID nic-noisy · Основной ответственный Команда инфраструктуры · Серверная инфраструктура · Совместно Внешние стороны · Внешние стороны
Если другие виртуальные машины на том же физическом сервере активно используют сеть и CPU, обработка на нашем сервере нерегулярно запаздывает.
Почему Другие виртуальные машины на том же физическом сервере потребляют много ресурсов → Следствие Обработка пакетов на нашей виртуальной машине нерегулярно запаздывает → На экране Без явной причины время от времени появляется джиттер (неравномерность интервалов между пакетами) и микрофризы
Основной ответственный Команда инфраструктуры · Серверная инфраструктура · Совместно Внешние стороны · Внешние стороны
Команда инфраструктуры: задачи
Выделенные хосты, инстансы с гарантированной производительностью, инстанс с постоянным джиттером остановить и запустить снова, чтобы он переехал на другой хост.
Внешние стороны: задачи
Сообщить облачному провайдеру о проблемном хосте.
На графике
Случайные всплески · джиттер времени туда и обратно внутри ЦОД, %steal
Где смотреть
Непрерывно пинговать другой сервер в том же ЦОД и записывать джиттер времени туда и обратно, сравнить его вместе с %steal из mpstat с другими инстансами той же конфигурации
Подтверждает
Только у этого инстанса джиттер времени туда и обратно или %steal нерегулярно скачут, а у других инстансов той же конфигурации всё спокойно. После остановки и запуска с переездом на другой хост проблема пропадает
Опровергает
Если у всех инстансов той же конфигурации одинаковые скачки, хост ни при чём. Смотреть нагрузку на стороне игрового сервера или сетевой участок
Чем проверить
Инструменты инфраструктуры (игровой код не нужен)
Источников: 2
How EC2 instance stop and start worksAWS Если инстанс остановить и снова запустить, в большинстве случаев он переезжает на новый хост (кроме выделенных хостов)
mpstat(1) — Linux manual pagesysstat %steal: доля времени, в течение которого этот виртуальный CPU вынужденно ждал, пока гипервизор выполнял другой виртуальный CPU
ID nic-host-maintenance · Основной ответственный Команда инфраструктуры · Серверная инфраструктура · Совместно Команда разработки · Разработка сервера, Внешние стороны · Внешние стороны
Во время обслуживания физического сервера (хоста) облачный провайдер переносит виртуальную машину на другой хост (живая миграция) или ненадолго её приостанавливает. На это время замирает весь сервер, а если пауза долгая, соединения рвутся.
Почему Из-за обслуживания хоста или прогноза отказа провайдер переносит виртуальную машину на другой хост или ненадолго приостанавливает её → Следствие Во время переноса CPU, память и сеть работают медленнее, а в конце виртуальная машина ненадолго полностью останавливается (в зависимости от провайдера и способа от меньше 1 с до примерно 30 с) → На экране Фриз у всех на сервере одновременно, затем перемотка и телепортация, а если остановка дольше таймаута, массовые дисконнекты
Основной ответственный Команда инфраструктуры · Серверная инфраструктура · Совместно Команда разработки · Разработка сервера, Внешние стороны · Внешние стороны
Команда разработки: задачи
Таймауты, которые переживают остановку на несколько секунд, ограничение числа догоняющих тиков после остановки, расчёт прошедшего времени по монотонным часам (monotonic clock), процедура, которая по уведомлению об обслуживании сохраняет прогресс и переводит игроков на другой сервер.
Команда инфраструктуры: задачи
Подписаться на уведомления об обслуживании и поставить алерты (Google Cloud maintenance-event, запланированные события AWS и AWS Health, Azure Scheduled Events), получив уведомление, заранее заменить сервер в часы с малым онлайном, если провайдер позволяет, сдвинуть время обслуживания (Azure Maintenance Configuration, для некоторых типов запланированные события AWS), сверять журнал обслуживания с журналом инцидентов.
Внешние стороны: задачи
Уточнить у облачного провайдера график обслуживания и масштаб влияния, если на одном инстансе остановки повторяются, сообщить провайдеру.
Цифры для ориентира
По словам Google Compute Engine, остановка при живой миграции обычно намного короче 1 с, а системные часы за время остановки могут прыгнуть вперёд до 5 с. Значение maintenance-event в метаданных меняется за 60 с до переноса (если до этого его хотя бы раз запрашивали). У Azure при обслуживании без перезагрузки остановка почти всегда короче 10 с, изредка (для обычных размеров не чаще раза в 18 месяцев) около 30 с, а живая миграция обычно не дольше 5 с. Azure Scheduled Events предупреждает о такой остановке (Freeze) минимум за 15 мин. Но если оборудование хоста внезапно отказывает, восстановление начинается сразу, без предупреждения.
На графике
Провал, затем пачка · пакеты сервера на приём и отправку, интервал тика
Где смотреть
Сверить момент остановки с записями провайдера. В Google Cloud это compute.instances.migrateOnHostMaintenance в журнале аудита, в AWS запланированные события в describe-instance-status и AWS Health, в Azure Microsoft.Compute/virtualMachines/liveMigration/action в журнале действий (Activity Log) и момент, когда метрика доступности VM (VmAvailabilityMetric) упала до 0. Внутри сервера посмотреть, есть ли пробел в метриках и логах на время остановки и прыгнули ли часы сразу после неё (журнал синхронизации времени)
Подтверждает
Момент остановки всего сервера совпадает с записанным у провайдера временем обслуживания или миграции, и на эти несколько секунд все метрики и логи внутри сервера пустые
Опровергает
Если в записях провайдера ничего нет, а короткие остановки часто повторяются, это «CPU steal (виртуальная машина)». Если в логе ядра есть записи о сбросе NIC, это «Проблемы драйвера и прошивки NIC»
Чем проверить
Инструменты инфраструктуры (игровой код не нужен)
Подробнее
AWS предупреждает об обслуживании через запланированные события (scheduled events). system-reboot означает перезагрузку с переносом на новый хост, system-maintenance означает, что обслуживание сети или питания может ненадолго повлиять на инстанс. Даже если остановка длится несколько секунд, клиенты, не получившие за это время ACK на отправленные серверу пакеты, удваивают ожидание перед каждым повтором, поэтому TCP-соединение может оставаться замершим и после того, как сервер оживёт (см. причину «TCP RTO и экспоненциальный backoff»). После пробуждения часы прыгают (см. причину «Скачок системных часов (шаговая коррекция NTP)»), а health check балансировщика может не пройти, и сервер ненадолго исключат из балансировки. Инстансы, которые нельзя перенести (например, bare metal в Google Cloud), при обслуживании останавливаются или перезапускаются.
Источников: 6
Live migration process during maintenance eventsGoogle Cloud Остановка при живой миграции обычно намного короче 1 с, за время остановки системные часы прыгают вперёд до 5 с, во время переноса ненадолго падает производительность диска, CPU, памяти и сети, VM без живой миграции при обслуживании выключаются (bare metal её не поддерживает)
Query metadata server for maintenance event noticesGoogle Cloud Значение метаданных maintenance-event меняется за 60 с до живой миграции (если VM настроена на живую миграцию и после прошлого обслуживания это значение хотя бы раз запрашивали)
Scheduled events for Amazon EC2 instancesAWS Типы запланированных событий (system-reboot: перезагрузка с переносом на новый хост, system-maintenance: кратковременное влияние из-за обслуживания сети или питания), уведомления по почте и через AWS Health, проверка через describe-instance-status, для некоторых типов время можно сдвинуть
Maintenance and updatesMicrosoft Azure Обслуживание без перезагрузки почти всегда останавливает VM меньше чем на 10 с, изредка (для обычных размеров не чаще раза в 18 месяцев) примерно на 30 с, живая миграция обычно не дольше 5 с, после остановки часы синхронизируются автоматически, долгие TCP-соединения могут рваться, а данные, отправленные остановленной VM, другая сторона повторяет с экспоненциальным backoff, и восстановление затягивается, health check балансировщика примерно за 10 с признаёт VM неисправной, проверка по Microsoft.Compute/virtualMachines/liveMigration/action в журнале действий и по VmAvailabilityMetric, которая на время остановки падает до 0, время применения выбирается через Maintenance Configuration
Scheduled Events for Linux VMs in AzureMicrosoft Azure О Freeze (остановка на несколько секунд, CPU и сеть могут замереть) предупреждают минимум за 15 мин, при отказе оборудования хоста восстановление начинается сразу, без периода уведомления
ID nic-reset · Основной ответственный Команда инфраструктуры · Серверная инфраструктура
Из-за ошибки драйвера или сбоя какой-то функции карта зависает и перезапускается, и на это время весь приём и отправка прекращаются.
Почему Ошибка драйвера, сбой функций offload → Следствие NIC зависает и перезапускается (несколько секунд) → На экране У всех на этом сервере одновременно фриз, затем телепортация или дисконнект
Основной ответственный Команда инфраструктуры · Серверная инфраструктура
Команда инфраструктуры: задачи
Отслеживать в логе ядра записи «transmit queue … timed out» и «Link is Down» и ставить на них алерты, обновить драйвер и прошивку, отключить проблемную функцию (offload и т. п.).
На графике
Провал, затем пачка · пакеты сервера на приём и отправку
Где смотреть
Найти в логе ядра через dmesg записи «NETDEV WATCHDOG … transmit queue N timed out», сброс драйвера, «Link is Down» и «Link is Up» и посмотреть число пакетов сервера на приём и отправку в это время
Подтверждает
В момент остановки в логе ядра есть таймаут очереди отправки или падение и подъём линка, и на эти несколько секунд число принятых и отправленных пакетов падает до 0
Опровергает
Если лог ядра чист и порт на коммутаторе в порядке, это остановка процесса игрового сервера («Полная пауза GC на сервере», «Дедлок») или «Переключение сетевого оборудования на резерв (failover)»
Чем проверить
Инструменты инфраструктуры (игровой код не нужен)
Источников: 3
net/sched/sch_generic.c (Linux v6.12)Linux kernel Если очередь отправки зависла, watchdog ядра пишет «NETDEV WATCHDOG … transmit queue N timed out» и вызывает функцию сброса драйвера
ID nic-offload · Основной ответственный Команда инфраструктуры · Серверная инфраструктура
GRO и LRO объединяют несколько пакетов в один, чтобы снизить нагрузку на CPU. При некоторых настройках маленький игровой пакет ненадолго ждёт следующий, чтобы объединиться с ним.
Почему NIC или ядро ОС объединяет пришедшие пакеты и обрабатывает их вместе → Следствие Если включено аппаратное объединение (LRO) или задано время ожидания объединения, пакет ненадолго ждёт следующий → На экране Небольшой рост задержки (обычно не больше нескольких десятков µs)
Основной ответственный Команда инфраструктуры · Серверная инфраструктура
Команда инфраструктуры: задачи
Подстроить под игровой трафик (выключить LRO, проверить настройку времени ожидания объединения), эффект обычно мал, поэтому проверять после других причин.
На графике
Высоко с самого начала · время туда и обратно внутри одного ЦОД
Где смотреть
Проверить состояние lro и gro через ethtool -k и значение gro_flush_timeout в настройках устройства в sysfs, сравнить время туда и обратно для маленьких пакетов внутри ЦОД до и после изменения
Подтверждает
LRO включён или gro_flush_timeout больше 0, и если выключить LRO или поставить 0, время туда и обратно для маленьких пакетов сокращается
Опровергает
Если разница после изменения в пределах единиц µs, причина в другом
Чем проверить
Инструменты инфраструктуры (игровой код не нужен)
Источников: 3
NAPILinux kernel Большой gro_flush_timeout даёт пакетную обработку, но при низкой нагрузке добавляет задержку
ID so-backlog · Основной ответственный Команда разработки · Разработка сервера · Совместно Команда инфраструктуры · Серверная инфраструктура, Команда разработки · Разработка клиента
Когда сразу после техработ одновременно подключаются десятки тысяч игроков, очередь подключений ядра (backlog) переполняется и попытки подключения отбрасываются.
Почему С окончанием техработ подключения приходят быстрее, чем игровой сервер успевает принимать их через accept → Следствие Очередь подключений ядра (backlog: меньшее из значения, которое код сервера передал в listen, и предела ядра) заполнена → На экране Попытки подключения отбрасываются, повторы идут один за другим: ошибка входа / бесконечная загрузка
Основной ответственный Команда разработки · Разработка сервера · Совместно Команда инфраструктуры · Серверная инфраструктура, Команда разработки · Разработка клиента
Команда разработки: задачи
Сервер: увеличить значение, которое код передаёт в listen, не давать потоку, принимающему подключения, останавливаться на другой работе, сделать очередь на вход. Клиент: увеличивать интервал между повторами (со случайным разбросом).
Команда инфраструктуры: задачи
Увеличить somaxconn в ядре (эффект будет, только если поднять и его, и значение listen в коде сервера), держать SYN cookies включёнными, следить за числом переполнений (TcpExtListenOverflows в nstat).
Цифры для ориентира
Предел ядра Linux (somaxconn) начиная с версии 5.4 по умолчанию равен 4 096 (до этого 128), но если код сервера передаёт в listen меньшее значение, лимитом становится оно. Когда очередь заполнена, Linux молча, без ошибки, отбрасывает запросы на подключение. ОС клиента повторяет запрос несколько раз, начиная через 1 секунду, поэтому для игрока это выглядит как долгая загрузка без сообщения «Ошибка подключения». Сервер на Windows возвращает отказ, и клиент сразу видит «Ошибка подключения».
На графике
Всплеск сразу после входа или техработ · число переполнений очереди подключений (ListenOverflows), число попыток подключения
Где смотреть
Посмотреть прирост TcpExtListenOverflows и TcpExtListenDrops в nstat -az и сравнить через ss -ltn у слушающего сокета Recv-Q (число подключений, ждущих accept) и Send-Q (лимит backlog)
Подтверждает
В момент наплыва подключений растёт ListenOverflows, а Recv-Q слушающего сокета держится на уровне Send-Q
Опровергает
Если ListenOverflows не меняется, причина в другом. Если соединение установлено, а загрузка не заканчивается, это «Наплыв входов и запросы N+1». Если вход упирается ровно в определённое число игроков, это «Лимит файловых дескрипторов»
Чем проверить
Инструменты инфраструктуры (игровой код не нужен)
Источников: 5
listen(2) — Linux manual pageLinux man-pages Backlog в listen, превышающий somaxconn, молча урезается. somaxconn по умолчанию 4 096 (с версии 5.4, раньше 128). При заполненной очереди запрос можно проигнорировать и положиться на повтор со стороны клиента
IP SysctlLinux kernel tcp_syn_retries: запрос на подключение (SYN) отправляется повторно несколько раз, первое ожидание перед повтором 1 секунда. tcp_abort_on_overflow по умолчанию выключен (при переполнении отказ не отправляется), tcp_syncookies по умолчанию включён
SNMP counterLinux kernel TcpExtListenOverflows: сколько раз запрос на подключение (SYN) был отброшен из-за заполненной очереди accept. Вместе с ним растёт и TcpExtListenDrops
net/ipv4/tcp_diag.c (Linux v6.12)Linux kernel Значения Recv-Q и Send-Q в ss: у слушающего сокета это число подключений, ждущих accept, и лимит backlog, у подключённого сокета это байты, ещё не прочитанные приложением, и отправленные байты без ACK
ID so-fd · Основной ответственный Команда инфраструктуры · Серверная инфраструктура · Совместно Команда разработки · Разработка сервера
Каждому соединению нужен файловый дескриптор (fd, номер, который ОС присваивает открытому файлу или сокету), а число fd, которые может открыть один процесс, ограничено.
Почему Онлайн достигает лимита файловых дескрипторов процесса → Следствие Сервер не может принять новые соединения (Too many open files). Заодно не открываются файлы логов и соединения с БД → На экране Начиная с определённого числа игроков больше никто не может войти: ошибка входа / бесконечная загрузка
Сразу после входа или техработ, При наплыве игроков
Ответственные
Основной ответственный Команда инфраструктуры · Серверная инфраструктура · Совместно Команда разработки · Разработка сервера
Команда разработки: задачи
Надёжно закрывать сокет при завершении соединения (чтобы не было утечки fd). Если accept завершается с EMFILE (не хватает fd), ненадолго перестать принимать подключения или принять подключение на заранее отложенный резервный fd и сразу закрыть (чтобы не тратить CPU на повторную обработку одного и того же уведомления о подключении).
Команда инфраструктуры: задачи
Проверить ulimit и настройки сервиса (LimitNOFILE в systemd), настроить алерт при приближении к лимиту.
Цифры для ориентира
В Linux, если отдельно не настроить сервис, лимит всё ещё часто равен 1 024. Для игровых серверов его обычно поднимают до десятков или сотен тысяч. В Windows такого низкого лимита по умолчанию нет.
На графике
Упор в лимит (плато) · число открытых fd процесса, онлайн
Где смотреть
Посмотреть fd-nr (число открытых файловых дескрипторов) процесса игрового сервера через pidstat -v и лимит открытых файлов в /proc/PID/limits, найти в логах сервера ошибки accept (EMFILE, Too many open files)
Подтверждает
Число fd выходит на плато на значении лимита, и с этого момента accept завершается с EMFILE
Опровергает
Если число fd далеко от лимита, причина в другом. Если запросы на подключение отбрасывает ядро, это «Переполнение очереди подключений (backlog)», если дело в отслеживании соединений, это «Переполнение таблицы conntrack на сервере»
Чем проверить
Инструменты инфраструктуры (игровой код не нужен)
Подробнее
Непринятые подключения так и остаются в очереди подключений ядра (backlog), поэтому, в зависимости от кода, сервер может раз за разом получать уведомление «есть новое подключение» и впустую тратить CPU.
ID so-sockbuf · Основной ответственный Команда инфраструктуры · Серверная инфраструктура · Совместно Команда разработки · Разработка сервера
Если буферы приёма и отправки маленькие, то при всплеске трафика принятые по UDP пакеты отбрасываются, а отправка по TCP встаёт, потому что в буфере нет места.
Почему SO_SNDBUF и SO_RCVBUF оставлены по умолчанию или слишком малы → Следствие При всплеске трафика или короткой остановке принимающего потока буфер приёма UDP переполняется и пакеты выбрасываются, а TCP ждёт, пока в буфере отправки освободится место → На экране Телепортация (потери UDP) или перемотка (ожидание TCP)
Основной ответственный Команда инфраструктуры · Серверная инфраструктура · Совместно Команда разработки · Разработка сервера
Команда разработки: задачи
Задавать в коде размер буферов под трафик (SO_SNDBUF, SO_RCVBUF). Для TCP учитывать, что явная установка размера отключает автонастройку буферов в Linux. Не делать буферы слишком большими: в них копятся устаревшие данные и растёт задержка. Не допускать остановок принимающего потока.
Команда инфраструктуры: задачи
Настроить пределы ядра (rmem_max, wmem_max: размер буфера, заданный в коде, тоже не может их превысить) и значение по умолчанию (rmem_default), следить за счётчиком переполнений буфера (RcvbufErrors).
Цифры для ориентира
Буфер приёма UDP в Linux по умолчанию около 208 KB. Даже маленький пакет занимает в памяти ядра намного больше своего реального размера, поэтому буфер заполняют уже десятки или сотни пакетов. На сервере, который принимает 100 000 пакетов в секунду, буфер переполняется, если принимающий поток остановится всего на несколько ms.
Посмотреть прирост UdpRcvbufErrors в nstat -az и skmem в ss -uamn (rb: размер буфера приёма, d: число пакетов, отброшенных до попадания в сокет). Для TCP проверить в skmem из ss -tm, не дошла ли память очереди отправки (w) до размера буфера отправки (tb)
Подтверждает
В моменты всплесков трафика или остановок принимающего потока растёт UdpRcvbufErrors (или d у сокета), а rb около значения по умолчанию (примерно 208 KB). В TCP w упирается в tb, и send блокируется
Опровергает
Если счётчик не растёт, а потери есть, дело на уровне NIC («Слишком маленький кольцевой буфер») или на участке сети
Чем проверить
Инструменты инфраструктуры (игровой код не нужен)
Источников: 6
socket(7) — Linux manual pageLinux man-pages Значения SO_RCVBUF и SO_SNDBUF по умолчанию берутся из rmem_default и wmem_default, пределы из rmem_max и wmem_max. Ядро удваивает заданное значение
include/net/sock.h (Linux v6.18)Linux kernel Буфер сокета по умолчанию определён как 256 пакетов по 256 байт с учётом накладных расходов sk_buff (SKB_TRUESIZE(256)×256). Даже маленький кадр учитывается как sk_buff+MTU (около 208 KB: расчётное значение для x86-64)
IP SysctlLinux kernel tcp_rmem, tcp_wmem: если явно задать SO_RCVBUF или SO_SNDBUF, автонастройка размера буфера для этого сокета отключается
net/ipv4/udp.c (Linux v6.12)Linux kernel Если очередь приёма UDP превышает размер буфера сокета, пакет сразу отбрасывается и растёт RcvbufErrors
net/ipv4/proc.c (Linux v6.12)Linux kernel Имена счётчиков, которые показывает nstat: RcvbufErrors и SndbufErrors в группе Udp
ss(8) — Linux manual pageiproute2 skmem в выводе -m: rb (размер буфера приёма), tb (размер буфера отправки), w (память очереди отправки), d (число пакетов, отброшенных до попадания в сокет)
ID so-context · Основной ответственный Команда разработки · Разработка сервера · Совместно Команда инфраструктуры · Серверная инфраструктура
Если потоков намного больше, чем ядер, заметная часть CPU уходит только на то, чтобы ОС запускала их по очереди.
Почему Потоков сотни или тысячи (например, свой поток на каждое соединение) → Следствие Растут затраты на переключение контекста (смену выполняемого потока) и число промахов кэша → На экране CPU занят, но производительность низкая, тики неравномерные: микрофризы, слоумо
Основной ответственный Команда разработки · Разработка сервера · Совместно Команда инфраструктуры · Серверная инфраструктура
Команда разработки: задачи
Держать число потоков по числу ядер, перейти на асинхронный ввод-вывод (epoll, IOCP).
Команда инфраструктуры: задачи
Мониторить число переключений контекста и число потоков в очереди на выполнение (cs и r в vmstat).
Цифры для ориентира
Одно переключение контекста стоит несколько µs, а вместе с последующими промахами кэша ещё больше.
На графике
Растёт вслед за онлайном и нагрузкой · переключения контекста в секунду, число потоков в очереди на выполнение
Где смотреть
Сравнить cs (переключения контекста в секунду) и r (число выполняемых или ждущих CPU) из vmstat 1 с числом ядер и посмотреть через pidstat -w -t добровольные (cswch/s) и принудительные (nvcswch/s) переключения контекста по потокам игрового сервера
Подтверждает
С ростом онлайна r поднимается намного выше числа ядер, cs тоже взлетает, а потоков с большим числом принудительных переключений контекста сотни
Опровергает
Если r не превышает числа ядер, причина в другом. Если много только добровольных переключений, потоки ждут блокировок или ввода-вывода («Конкуренция за блокировки», «Архитектура с блокирующим вводом-выводом»)
vmstat(8) — Linux manual pageprocps-ng Поля cs (число переключений контекста в секунду) и r (число выполняемых или ожидающих выполнения процессов)
I/O Completion PortsMicrosoft Множество асинхронных операций ввода-вывода обрабатывает заранее созданный пул потоков через IOCP, а число одновременно работающих потоков ограничивается по числу процессоров
pidstat(1) — Linux manual pagesysstat cswch/s в выводе -w: добровольные переключения контекста, когда поток сам останавливается в ожидании ресурса. nvcswch/s: принудительные переключения, когда поток израсходовал квант времени. -t выводит данные по потокам
ID so-steal · Основной ответственный Команда инфраструктуры · Серверная инфраструктура · Совместно Внешние стороны · Внешние стороны
Пока физический сервер (гипервизор) временно отдаёт процессорное время виртуальной машины другим виртуальным машинам (CPU steal), игровой сервер стоит.
Почему Другие виртуальные машины на том же хосте активно используют CPU → Следствие Виртуальная машина игрового сервера то и дело не получает CPU на время от единиц до десятков ms → На экране Необъяснимые всплески времени тика: микрофризы, фризы
Основной ответственный Команда инфраструктуры · Серверная инфраструктура · Совместно Внешние стороны · Внешние стороны
Команда инфраструктуры: задачи
Мониторить steal (st в top и vmstat), использовать выделенные ядра или хосты, избегать burst-инстансов, которые замедляются, когда кончаются CPU-кредиты. Инстанс с постоянно высоким steal остановить и запустить заново, чтобы он переехал на другой хост.
Внешние стороны: задачи
Сообщить облачному провайдеру о хосте с постоянно высоким steal.
На графике
Случайные всплески · %steal, время тика сервера
Где смотреть
Наложить %steal из mpstat -P ALL 1 на время тика сервера на одной временной оси
Подтверждает
В моменты всплесков времени тика скачет и %steal, а после остановки, запуска и переезда на другой хост он снижается
Опровергает
Если %steal близок к 0, а время тика скачет, причина внутри игрового сервера («Полная пауза GC на сервере», «Конкуренция за блокировки»). Если сервер в контейнере, это «Троттлинг CPU в контейнере (квота CFS)»
Чем проверить
Инструменты инфраструктуры (игровой код не нужен)
Источников: 4
proc_stat(5) — Linux manual pageLinux man-pages steal: время, отнятое в виртуализированной среде на выполнение других операционных систем
Standard mode for burstable performance instancesAWS Burst-инстансы тратят кредиты, чтобы работать выше базовой производительности, а когда кредиты заканчиваются, загрузка CPU снижается до базового уровня
mpstat(1) — Linux manual pagesysstat %steal: доля времени, в течение которого этот виртуальный CPU вынужденно ждал, пока гипервизор выполнял другой виртуальный CPU
ID so-cpu-quota · Основной ответственный Команда инфраструктуры · Серверная инфраструктура · Совместно Команда разработки · Разработка сервера
Если у контейнера задан лимит CPU, то, израсходовав квоту в пределах периода (обычно 100 ms), он принудительно останавливается до конца периода (троттлинг).
Почему В Kubernetes или похожей системе контейнеру игрового сервера задан лимит CPU (limit) → Следствие В момент пиковых расчётов тика квота кончается, и контейнер стоит десятки ms до следующего периода → На экране Средняя загрузка CPU низкая, но время тика периодически скачет: микрофризы, слоумо
Основной ответственный Команда инфраструктуры · Серверная инфраструктура · Совместно Команда разработки · Разработка сервера
Команда разработки: задачи
Подогнать число рабочих потоков под лимит CPU (чтобы рантайм не создавал потоки по числу всех ядер хоста).
Команда инфраструктуры: задачи
Задать лимит CPU с запасом или убрать его и выделить ядра, следить за числом троттлингов (nr_throttled).
Цифры для ориентира
Если на сервере с лимитом в 2 ядра одновременно работают 8 потоков, квота периода 100 ms расходуется за 25 ms, и следующие 75 ms сервер стоит.
На графике
Растёт вслед за онлайном и нагрузкой · число троттлингов (nr_throttled), время тика сервера
Где смотреть
Смотреть прирост nr_throttled и throttled_usec (в cgroup v1 nr_throttled и throttled_time) в cpu.stat cgroup контейнера вместе со временем тика сервера
Подтверждает
Средняя загрузка CPU ниже лимита, но nr_throttled и throttled_usec постоянно растут, и их рост совпадает со всплесками времени тика
Опровергает
Если nr_throttled не растёт, причина в другом. Если CPU недодают самой виртуальной машине, это «CPU steal (виртуальная машина)»
Чем проверить
Инструменты инфраструктуры (игровой код не нужен)
Источников: 3
CFS Bandwidth ControlLinux kernel Если квота на период израсходована, потоки стоят до следующего периода (троттлинг). Период по умолчанию 100 ms, статистика nr_throttled
Control Group v2Linux kernel cpu.max имеет формат «$MAX $PERIOD» (квота, период), значение по умолчанию «max 100000» (период 100 ms)
ID so-cstate · Основной ответственный Команда инфраструктуры · Серверная инфраструктура
Простаивающее ядро CPU ради экономии энергии переходит в глубокое состояние сна (C-state) и снижает частоту. Когда приходит пакет или срабатывает таймер, на пробуждение и подъём частоты уходит время, и к обработке даже маленьких пакетов добавляется задержка.
Почему Политика управления частотой в ОС (governor) или настройки питания в BIOS разрешают глубокие C-state и низкие частоты → Следствие Каждое пробуждение ядра из глубокого сна добавляет до сотен µs, а если частота зафиксирована на низком уровне, медленнее идёт сам расчёт тика → На экране Обычно это почти незаметно, но при большом числе межсерверных вызовов задержки складываются, и в часы затишья ответ, как ни странно, приходит позже: задержка ввода. Если частота зафиксирована на низком уровне, при наплыве игроков тики отстают: слоумо
Основной ответственный Команда инфраструктуры · Серверная инфраструктура
Команда инфраструктуры: задачи
Перевести настройки питания в BIOS в режим производительности, а governor в ОС в performance (scaling_governor в cpufreq). На серверах, чувствительных к задержке, ограничить глубокие C-state (профиль tuned latency-performance, /dev/cpu_dma_latency в PM QoS, параметр ядра intel_idle.max_cstate). После изменений сравнить RTT внутри ЦОД, джиттер времени тика и энергопотребление.
Цифры для ориентира
По таблице драйвера intel_idle в Linux 6.12 неглубокое состояние C1 у серверных CPU Intel требует для пробуждения 1–2 µs, а глубокое C6 от 133 µs (Skylake-SP) до 290 µs (Sapphire Rapids). Один раз это немного, но если запрос проходит через несколько серверов, задержки складываются. Чем дольше ожидаемый простой, тем более глубокое состояние выбирает ядро ОС, поэтому чаще это проявляется на ненагруженных серверах, куда пакеты приходят изредка. Универсальный governor powersave в cpufreq фиксирует самую низкую частоту из допустимого диапазона (одноимённый алгоритм intel_pstate регулирует частоту по нагрузке).
На графике
Высоко с самого начала · RTT внутри ЦОД, частота ядер
Где смотреть
Посмотреть через cpupower monitor долю времени в каждом C-state и фактическую частоту по ядрам, проверить для каждого state в /sys/devices/system/cpu/cpu0/cpuidle/ поля name, latency (время пробуждения в µs) и usage, а также scaling_governor в cpufreq и текущий профиль через tuned-adm active
Подтверждает
Простаивающие ядра подолгу находятся в самом глубоком C-state или их частота держится около минимальной, а после перехода на governor performance и неглубокие C-state RTT и джиттер мелких запросов снижаются
Опровергает
Если после изменений разница не больше десятков µs, этой причиной можно пренебречь. Если всплески измеряются в ms, это «CPU steal (виртуальная машина)» или другой слой
Чем проверить
Инструменты инфраструктуры (игровой код не нужен)
Подробнее
На bare-metal-серверах в ЦОД смотрят и настройки питания в BIOS (прошивке), и настройки ОС. В облаке менять C-state и частоту из ОС можно только на некоторых типах инстансов, а в AWS настройки по умолчанию ориентированы на максимальную производительность, так что обычно их можно не трогать. Профиль tuned latency-performance в дистрибутивах семейства Red Hat ставит governor performance и через PM QoS разрешает только неглубокие C-state. Отключение энергосбережения увеличивает энергопотребление, поэтому его применяют только на серверах, чувствительных к задержке.
Источников: 7
CPU Idle Time ManagementLinux kernel У каждого состояния сна есть время выхода (exit latency) и минимальное время пребывания (target residency), а глубину выбирают по ожидаемому времени простоя. В sysfs для каждого state есть latency, usage и time. Глубокие состояния ограничивают через PM QoS (/dev/cpu_dma_latency) и intel_idle.max_cstate
drivers/idle/intel_idle.c (Linux v6.12)Linux kernel Время пробуждения серверных CPU Intel по C-state: Skylake-SP C1 2 µs, C1E 10 µs, C6 133 µs; Ice Lake C6 170 µs; Sapphire Rapids C1 1 µs, C6 290 µs
CPU Performance ScalingLinux kernel Через scaling_governor можно посмотреть и сменить governor. performance запрашивает самую высокую частоту из допустимого диапазона, powersave самую низкую
intel_pstate CPU Performance Scaling DriverLinux kernel Алгоритм powersave в intel_pstate, в отличие от универсального governor powersave, регулирует частоту по нагрузке (похоже на schedutil и ondemand)
Chapter 2. Getting started with TuneDRed Hat Профиль latency-performance отключает энергосбережение, ставит governor performance и через PM QoS разрешает только неглубокие C-state. Текущий профиль показывает tuned-adm active
Processor state control for Amazon EC2 Linux instancesAWS Управлять C-state и P-state из ОС можно только на некоторых типах инстансов, и их можно менять, чтобы снизить задержку. Настройки по умолчанию дают максимальную производительность и подходят для большинства задач. У Graviton частота фиксированная, и ОС ею не управляет
ID so-oom · Основной ответственный Команда разработки · Разработка сервера · Совместно Команда инфраструктуры · Серверная инфраструктура
Когда память заканчивается, Linux выбирает процесс, который занимает больше всего памяти, и принудительно его завершает. Обычно это игровой сервер.
Почему Память исчерпана из-за утечки или резкого роста потребления, либо контейнер упёрся в лимит памяти → Следствие Ядро принудительно завершает процесс игрового сервера → На экране Дисконнект у всех на этом сервере одновременно, возможен роллбэк недавнего прогресса
Основной ответственный Команда разработки · Разработка сервера · Совместно Команда инфраструктуры · Серверная инфраструктура
Команда разработки: задачи
Исправить утечки, задать верхнюю границу потребления памяти и при приближении к ней сохранять данные и штатно завершать работу.
Команда инфраструктуры: задачи
Настроить алерты по памяти, задать лимит памяти контейнера по фактическому потреблению, настроить очерёдность завершения процессов (oom_score_adj).
Цифры для ориентира
В журнале ядра (dmesg) остаётся запись «Out of memory: Killed process», а в Kubernetes виден статус OOMKilled. В Windows OOM killer нет, и там сервер чаще падает с ошибкой, когда не удаётся выделить память.
На графике
Массовый обрыв соединений · число подключений, расход памяти
Где смотреть
Сопоставить с моментом обрыва подключений запись «Out of memory: Killed process» в dmesg, статус пода OOMKilled в Kubernetes или прирост oom_kill в memory.events в cgroup v2
Подтверждает
В момент массового обрыва подключений есть запись о завершении процесса игрового сервера, а перед этим расход памяти дорос до лимита
Опровергает
Если записи OOM нет, а процесс завершился, смотреть лог падения и core dump, как в причине «Падение сервера»
Чем проверить
Инструменты инфраструктуры (игровой код не нужен)
Источников: 4
mm/oom_kill.c (Linux v6.12)Linux kernel Оценка рассчитывается так, чтобы самый высокий балл получал процесс, занимающий больше всего памяти (с учётом oom_score_adj). При завершении записывается «Out of memory: Killed process …»
Pushing the Limits of Windows: Virtual MemoryMicrosoft В Windows при достижении предела выделения (commit limit) выделение памяти с фиксацией (commit) завершается ошибкой, что может привести к сбою приложения или системы
Control Group v2Linux kernel oom_kill в memory.events: число процессов в этой cgroup, завершённых OOM killer
ID so-reclaim · Основной ответственный Команда инфраструктуры · Серверная инфраструктура · Совместно Команда разработки · Разработка сервера
Процесс останавливается, пока ОС уплотняет память (compaction), чтобы собрать большие страницы (huge pages), или освобождает память, чтобы пополнить запас свободной (reclaim).
Почему Свободной памяти становится мало, или механизм больших страниц (THP) запускает уплотнение памяти → Следствие Поток, запросивший память, ждёт, пока закончится освобождение или уплотнение → На экране Нерегулярные остановки сервера (от единиц до сотен ms)
Основной ответственный Команда инфраструктуры · Серверная инфраструктура · Совместно Команда разработки · Разработка сервера
Команда разработки: задачи
Сократить крупные выделения памяти во время работы (выделять заранее при запуске и переиспользовать).
Команда инфраструктуры: задачи
Разрешить большие страницы (THP) только там, где они нужны (madvise), поднять порог свободной памяти (vm.min_free_kbytes и др.).
На графике
Случайные всплески · время тика сервера, PSI памяти
Где смотреть
Смотреть some и full в /proc/pressure/memory (доля времени, проведённого в ожидании памяти) и прирост compact_stall в /proc/vmstat вместе со временем тика сервера, проверить настройку /sys/kernel/mm/transparent_hugepage/defrag
Подтверждает
В моменты всплесков времени тика растут PSI памяти и compact_stall. defrag стоит в always
Опровергает
Если PSI и compact_stall не меняются, причина в другом. Если растёт использование свопа, это «Своп»
Чем проверить
Инструменты инфраструктуры (игровой код не нужен)
Источников: 3
Transparent Hugepage SupportLinux kernel При defrag=always, если выделить THP не удалось, процесс останавливается и тут же выполняет освобождение и уплотнение памяти. При madvise так происходит только в областях, для которых это запрошено
Documentation for /proc/sys/vm/Linux kernel min_free_kbytes: минимальный объём свободной памяти, который ядро держит в резерве (порог watermark)
PSI - Pressure Stall InformationLinux kernel some в /proc/pressure/memory (доля времени, когда часть задач стояла в ожидании памяти) и full (доля времени, когда стояли все задачи)
ID so-timejump · Основной ответственный Команда разработки · Разработка сервера · Совместно Команда инфраструктуры · Серверная инфраструктура
Если часы сервера разом переводятся на несколько секунд вперёд или назад, таймеры, завязанные на системные часы, срабатывают пачкой или замирают.
Почему Синхронизация времени резко переводит часы → Следствие Таймеры срабатывают пачкой или замирают, таймауты определяются неверно → На экране Сбои баффов и кулдаунов, массовый дисконнект, перемотка
Основной ответственный Команда разработки · Разработка сервера · Совместно Команда инфраструктуры · Серверная инфраструктура
Команда разработки: задачи
Считать прошедшее время, таймауты и кулдауны по монотонным часам (monotonic clock), которые не скачут и не идут назад, а wall clock использовать только для отображения и записи в логи.
Команда инфраструктуры: задачи
Корректировать часы плавно (makestep в chrony только сразу после запуска), мониторить состояние синхронизации времени (расхождение часов).
Цифры для ориентира
ntpd переводит часы разом, если расхождение больше 0,128 с, а меньшее расхождение устраняет плавно, со скоростью, при которой на 1 секунду уходит чуть больше 30 минут. Популярный сейчас chrony с рекомендуемой настройкой (makestep) переводит часы разом лишь несколько раз сразу после запуска, а дальше корректирует плавно. Часы скачут и тогда, когда виртуальная машина ненадолго останавливается и снова возобновляет работу.
На графике
Случайные всплески · число срабатываний таймеров и обрывов, журнал коррекций часов
Где смотреть
Найти в логе службы синхронизации времени записи о резкой коррекции часов и сопоставить их со временем сбоев. chrony пишет в syslog, если коррекция больше значения logchange (по умолчанию 1 с)
Подтверждает
В моменты сбоев баффов и кулдаунов, массовых дисконнектов и перемотки есть записи о коррекции часов, и величина коррекции близка к масштабу сбоя
Опровергает
Если записей о коррекции часов нет, причина в другом. Для виртуальной машины проверить и случаи остановки с последующим возобновлением («Обслуживание облачного хоста и живая миграция»)
Чем проверить
Инструменты инфраструктуры (игровой код не нужен)
Источников: 4
ntpd - Network Time Protocol (NTP) daemonNetwork Time Foundation Если расхождение превышает порог шага 128 ms, часы переводятся разом, если меньше, корректируются плавно. Скорость 0,5 ms в секунду, поэтому на 1 секунду уходит 2 000 с (около 33 минут)
chrony – Frequently Asked Questionschrony Рекомендуется разрешать шаговую коррекцию лишь несколько раз сразу после запуска, например makestep 1 3. Виртуальная машина, которую остановили и возобновили, может проснуться с неверным временем
ID so-cron · Основной ответственный Команда инфраструктуры · Серверная инфраструктура
Сжатие логов, бэкапы и проверки безопасности, которые запускаются каждый день в одно и то же время, занимают CPU и диск.
Почему В заданное время запускаются задания ОС → Следствие Они делят CPU и диск с игровым сервером → На экране В определённое время, например каждый день в 4:00, микрофризы и слоумо
Основной ответственный Команда инфраструктуры · Серверная инфраструктура
Команда инфраструктуры: задачи
Разнести задания по времени, понизить им приоритет (nice, ionice), отделить от игрового сервера (запускать на отдельном сервере).
На графике
Всплески с постоянным периодом · загрузка CPU, очередь диска, время тика сервера
Где смотреть
Собрать время запуска плановых заданий из crontab и systemctl list-timers и в моменты всплесков времени тика посмотреть через pidstat -u -d, какие процессы используют CPU и диск
Подтверждает
Время тика скачет каждый день (или каждый час) в одно и то же время, и в этот момент CPU и диск занимают процессы плановых заданий
Опровергает
Если всплески не привязаны к одному и тому же времени суток, причина в другом. Если всплески идут каждые несколько секунд или минут, это «Полная пауза GC на сервере» или «Одновременное срабатывание таймеров»
Чем проверить
Инструменты инфраструктуры (игровой код не нужен)
Источников: 4
ionice(1) — Linux manual pageutil-linux Задания класса idle получают доступ к диску, только когда им не пользуются другие программы
systemd.timer(5) — Linux manual pagesystemd RandomizedDelaySec сдвигает запуск планового задания на случайное время и уменьшает скопление нагрузки
ID so-os-update · Основной ответственный Команда инфраструктуры · Серверная инфраструктура
Игровой код не менялся, но после обновления ОС, ядра, драйверов или прошивки сервер стал работать медленнее. Обновление может поменять значения по умолчанию, планировщик, защиту от уязвимостей CPU (mitigations) и поведение драйверов.
Почему Регулярный патч безопасности или новый образ сервера меняет ядро, драйверы или прошивку → Следствие Меняются значения по умолчанию или планировщик, включается новая защита от уязвимостей: на ту же работу уходит больше процессорного времени, а потоки получают CPU в другом порядке → На экране Сервер, который работал нормально, со дня обновления постоянно чуть медленнее: задержка ввода, а при наплыве игроков микрофризы и слоумо
Основной ответственный Команда инфраструктуры · Серверная инфраструктура
Команда инфраструктуры: задачи
Сначала обновлять часть серверов, сравнивать время тика, задержку и загрузку CPU с прежней версией и только потом раскатывать дальше. Не выкатывать в один день с игровым патчем. Записывать версии ядра, драйверов и прошивки и ключевые значения sysctl до и после обновления. При проблемах загрузиться со старым ядром и проверить. Отключение защиты (mitigations=off) решать, взвесив риски безопасности.
Цифры для ориентира
С новой версией ядра меняется и поведение по умолчанию. Например, начиная с 6.6 Linux стал переходить с планировщика CFS на EEVDF, а значение предела очереди подключений (somaxconn) по умолчанию с версии 5.4 выросло со 128 до 4 096. Защита от уязвимостей CPU добавляет работу: при возврате из ядра в программу (после каждого системного вызова), при переключении контекста и переключении виртуальных машин очищаются внутренние буферы CPU и т. п. Поэтому сильнее страдают сетевые серверы, которые делают системный вызов на каждый пакет. Для полной защиты от некоторых уязвимостей нужно выключить SMT (технологию, при которой одно ядро работает как два потока), а без SMT производительность в зависимости от нагрузки может сильно упасть. Параметр ядра mitigations=off отключает всю эту защиту и возвращает производительность, но оставляет систему уязвимой.
На графике
Ступенька вверх с определённого момента · время тика сервера, загрузка CPU, задержка при той же нагрузке
Где смотреть
Сопоставить с моментом роста задержки историю обновлений в пакетном менеджере и время перезагрузки, версию ядра из uname -r и сведения о драйвере NIC из ethtool -i. Сравнить обновлённые и необновлённые серверы под одинаковой нагрузкой через mpstat и pidstat, а также состояние защиты в /sys/devices/system/cpu/vulnerabilities/
Подтверждает
Задержка и загрузка CPU ступенькой поднимаются с момента перезагрузки после обновления и так и остаются, причём под одинаковой нагрузкой они выше только у обновлённых серверов. После загрузки со старым ядром или драйвером всё возвращается
Опровергает
Если обновлённые и необновлённые серверы под одинаковой нагрузкой одинаково медленные, причина в другом. Если в тот же день выкатили и игровой патч, а число или размер пакетов на игрока изменились, это «Патч изменил характер трафика»
Чем проверить
Инструменты инфраструктуры (игровой код не нужен)
Подробнее
Состояние защиты смотрят в файлах в /sys/devices/system/cpu/vulnerabilities/. По умолчанию (mitigations=auto) защита работает с включённым SMT, а с auto,nosmt на уязвимых CPU SMT выключается, и после обновления ядра число логических ядер может сократиться вдвое. Если обновить ОС в один день с игровым патчем, будет трудно понять, что стало причиной, поэтому их выкатывают отдельно.
Источников: 6
The kernel’s command-line parametersLinux kernel mitigations=: off отключает всю защиту от уязвимостей CPU и повышает производительность, но оставляет систему уязвимой. По умолчанию auto защищает с включённым SMT, auto,nosmt при необходимости выключает SMT
MDS - Microarchitectural Data SamplingLinux kernel Защита очищает буферы CPU при возврате из ядра в пространство пользователя и при входе в виртуальную машину. Состояние уязвимостей и защиты показывают файлы в /sys/devices/system/cpu/vulnerabilities/. На многих CPU для полной защиты нужно выключить SMT, а это в зависимости от нагрузки сильно бьёт по производительности
Spectre Side ChannelsLinux kernel Для защиты буферы предсказания переходов очищаются при переключении контекста и переключении виртуальных машин, а строгие варианты защиты добавляют накладные расходы всем программам
EEVDF SchedulerLinux kernel Начиная с 6.6 Linux переходит с CFS на планировщик EEVDF
ID so-conntrack · Основной ответственный Команда инфраструктуры · Серверная инфраструктура · Совместно Команда разработки · Разработка сервера, Команда разработки · Разработка клиента
Когда таблица отслеживания соединений (conntrack), в которую файрвол Linux записывает все соединения, достигает лимита, новые пакеты отбрасываются.
Почему Из-за наплыва подключений и множества коротких соединений растёт число записей → Следствие Таблица заполнена, новые соединения и часть пакетов отбрасываются → На экране Ошибка входа, телепортация из-за необъяснимых потерь
Сразу после входа или техработ, При наплыве игроков
Ответственные
Основной ответственный Команда инфраструктуры · Серверная инфраструктура · Совместно Команда разработки · Разработка сервера, Команда разработки · Разработка клиента
Команда разработки: задачи
Сервер: сократить короткие соединения (для межсерверных вызовов переиспользовать соединения). Клиент: при неудачном подключении или обрыве увеличивать интервал между повторами и добавлять случайный разброс.
Команда инфраструктуры: задачи
Увеличить размер таблицы (nf_conntrack_max), исключить игровые порты из отслеживания (NOTRACK в таблице raw), настроить алерт по заполненности.
Цифры для ориентира
Лимит по умолчанию в зависимости от памяти сервера составляет примерно от 60 000 до 260 000 записей. При переполнении в журнале ядра появляется «nf_conntrack: table full, dropping packet».
На графике
Упор в лимит (плато) · число записей conntrack (nf_conntrack_count)
Где смотреть
Вывести net.netfilter.nf_conntrack_count из sysctl (текущее число записей) на один график с nf_conntrack_max и найти в dmesg «nf_conntrack: table full, dropping packet»
Подтверждает
nf_conntrack_count выходит на плато на уровне max, и с этого момента в журнале ядра появляется table full
Опровергает
Если число записей далеко от max, причина в другом. Лимит отслеживания соединений самого инстанса AWS проверяют по conntrack_allowance_exceeded (см. «Превышен лимит PPS в облаке»)
Чем проверить
Инструменты инфраструктуры (игровой код не нужен)
Источников: 3
Netfilter Conntrack Sysfs variablesLinux kernel nf_conntrack_max по умолчанию равен числу бакетов хеш-таблицы (nf_conntrack_buckets), а число бакетов зависит от объёма памяти
net/netfilter/nf_conntrack_core.c (Linux v6.12)Linux kernel Размер по умолчанию 65 536 при памяти больше 1 GB и 262 144 при памяти больше 4 GB (на 64-битных системах). При заполнении пакет отбрасывается с записью «nf_conntrack: table full, dropping packet»
ID so-ports · Основной ответственный Команда разработки · Разработка сервера · Совместно Команда инфраструктуры · Серверная инфраструктура
Если игровой сервер часто открывает и закрывает короткие соединения с БД или другими серверами, закрытые соединения ещё какое-то время занимают порты, и новые соединения открыть не удаётся.
Почему На каждый запрос открывается и закрывается новое соединение → Следствие Сторона, закрывшая соединение первой, держит порт около 60 секунд (в Linux) в состоянии TIME_WAIT, и свободные порты заканчиваются → На экране Внутренние запросы не проходят: сбои сохранения и ошибки функций
Основной ответственный Команда разработки · Разработка сервера · Совместно Команда инфраструктуры · Серверная инфраструктура
Команда разработки: задачи
Переиспользовать соединения (пул соединений), не открывать и не закрывать соединение на каждый запрос.
Команда инфраструктуры: задачи
Расширить диапазон портов (ip_local_port_range), рассмотреть повторное использование TIME_WAIT для исходящих соединений (tcp_tw_reuse в Linux), следить за числом TIME_WAIT.
Цифры для ориентира
Диапазон портов в Linux по умолчанию (32768–60999) даёт около 28 000 портов. Если открывать к одному и тому же адресу больше 470 новых соединений в секунду, порты заканчиваются. В Windows портов по умолчанию около 16 000 (49152–65535), а TIME_WAIT длиннее, поэтому порты заканчиваются ещё быстрее.
На графике
Упор в лимит (плато) · число сокетов в TIME_WAIT, число неудачных внутренних соединений
Где смотреть
Подсчитать сокеты в TIME_WAIT по адресам назначения через ss -tan state time-wait и найти в логах игрового сервера ошибки connect (EADDRNOTAVAIL)
Подтверждает
Число TIME_WAIT к одному адресату (БД и т. п.) выходит на плато около размера диапазона эфемерных портов (по умолчанию около 28 000), а connect завершается с EADDRNOTAVAIL
Опровергает
Если TIME_WAIT мало, но сбоят только исходящие соединения во внешнюю сеть, это «Лимиты соединений и портов облачного NAT-шлюза»
Чем проверить
Инструменты инфраструктуры (игровой код не нужен)
Подробнее
60 секунд TIME_WAIT в Linux зашиты в ядро. Если уменьшить похожий по названию tcp_fin_timeout, TIME_WAIT короче не станет.
Источников: 5
IP SysctlLinux kernel ip_local_port_range по умолчанию 32768–60999, параметр tcp_tw_reuse, tcp_fin_timeout: время пребывания в состоянии FIN_WAIT_2
TCP/IP port exhaustion troubleshootingMicrosoft Динамические порты Windows по умолчанию 49152–65535, закрытое соединение по умолчанию держит порт в TIME_WAIT 4 минуты
ss(8) — Linux manual pageiproute2 Фильтр состояния state time-wait отбирает только сокеты в TIME_WAIT
connect(2) — Linux manual pageLinux man-pages EADDRNOTAVAIL: соединение не открыть, потому что заняты все порты из диапазона эфемерных портов
ID sk-hol · Основной ответственный Команда разработки · Разработка сервера · Совместно Команда разработки · Разработка клиента
Чтобы сохранить порядок, TCP не передаёт игре пакеты, пришедшие позже, пока заново не получит один потерянный пакет.
Почему Один пакет теряется → Следствие Следующие пакеты уже пришли, но ждут в буфере приёма → На экране Всё замирает, а потом разом прорывается: перемотка
Основной ответственный Команда разработки · Разработка сервера · Совместно Команда разработки · Разработка клиента
Команда разработки: задачи
Сервер: передавать позиции в реальном времени по UDP, гарантированную доставку оставить только для того, без чего нельзя, разделить данные на несколько потоков (streams). Клиент: перевести сетевую часть на ту же схему, что и сервер (UDP, раздельные каналы доставки).
Цифры для ориентира
Потеря одного пакета даёт остановку минимум на время пути туда и обратно плюс ещё немного, а если потеряется и повторная передача, остановка длится от сотен ms до нескольких секунд.
На графике
Провал, затем пачка · объём приёма по соединениям, число повторных передач
Где смотреть
В захвате пакетов на стороне сервера (tcpdump, Wireshark) найти в соединении этого игрока повторно переданные пакеты и паузы вокруг них, а по серверу в целом смотреть прирост TcpRetransSegs в nstat -az
Подтверждает
Остановка начинается с повторной передачи одного пакета, а сразу после его прихода накопившиеся данные обрабатываются разом (приём держится на 0, а потом идёт пачкой)
Опровергает
К играм на UDP неприменимо. Если повторных передач нет, а остановки есть, смотреть тики сервера («Превышение бюджета тика»)
RFC 5681: TCP Congestion ControlIETF Потеря обнаруживается по 3 дублирующим ACK и запускается быстрая повторная передача, иначе приходится ждать таймер повторной передачи
ID sk-rto · Основной ответственный Команда разработки · Разработка сервера · Совместно Команда разработки · Разработка клиента
С каждой новой неудачной повторной передачей ожидание удваивается, и короткий обрыв связи превращается в долгую остановку.
Почему Связь ненадолго обрывается, и повторные передачи тоже одна за другой не доходят → Следствие Ожидание до следующей попытки каждый раз удваивается: 0,3 → 0,6 → 1,2 → 2,4 с (при пинге 100 ms) → На экране Связь пропала на 1 с, а фриз в игре длится больше 2 с. Если обрыв дольше, в итоге дисконнект
Основной ответственный Команда разработки · Разработка сервера · Совместно Команда разработки · Разработка клиента
Команда разработки: задачи
Сервер: отвечать на хартбиты, а если их долго нет, первым закрывать соединение (сократить время до отказа через TCP_USER_TIMEOUT), восстанавливать сессию по токену, рассмотреть надёжный UDP. Клиент: часто отправлять хартбиты, а если ответы пропали, сразу переподключаться, не дожидаясь повторных передач TCP.
Цифры для ориентира
Минимальный RTO (время ожидания перед повторной передачей) в Linux равен «пинг + 200 ms», а при установке соединения он начинается с 1 секунды. С настройкой по умолчанию (tcp_retries2=15) повторные передачи могут раз за разом не проходить, но TCP отказывается от соединения только примерно через 15 минут.
На графике
Провал, затем пачка · RTO и backoff по соединениям, число срабатываний RTO
Где смотреть
Посмотреть через ss -ti у зависшего соединения rto (ожидание перед повторной передачей в ms) и backoff (число срабатываний подряд), а по серверу в целом прирост TcpExtTCPTimeouts (число срабатываний таймера повторной передачи) в nstat -az
Подтверждает
У зависшего соединения backoff 1 и больше, rto вырос до секунд, и в этот момент растёт TCPTimeouts
Опровергает
Если всё решается быстрой повторной передачей и RTO не срабатывает, остановка короткая. Тогда это «HOL-блокировка в TCP»
net/ipv4/tcp_input.c (Linux v6.12)Linux kernel В Linux RTO = сглаженный RTT + разброс RTT, а нижняя граница разброса равна tcp_rto_min (200 ms), поэтому RTO не меньше RTT+200 ms
IP SysctlLinux kernel tcp_rto_min_us по умолчанию 200 ms, начальный RTO для запроса на подключение 1 секунда, при tcp_retries2=15 до отказа проходит минимум 924,6 с (около 15 минут)
ss(8) — Linux manual pageiproute2 rto (таймер повторной передачи, ms) и backoff (число экспоненциальных удвоений) в выводе -i
net/ipv4/tcp_timer.c (Linux v6.12)Linux kernel При каждом срабатывании таймера повторной передачи увеличивается TCPTimeouts, backoff растёт на единицу, а RTO удваивается (до максимального значения)
ID sk-nagle · Основной ответственный Команда разработки · Разработка сервера · Совместно Команда разработки · Разработка клиента
Алгоритм Нейгла, который копит мелкие пакеты перед отправкой, и отложенный ACK, который придерживает подтверждения, мешают друг другу, и каждое сообщение, записанное по частям, задерживается на 40–200 ms.
Почему Мелкие сообщения пишутся по частям без включённого TCP_NODELAY → Следствие Отправитель ждёт ACK, а получатель отправляет ACK с задержкой → На экране Пинг низкий, но все действия одинаково запаздывают: задержка ввода
Основной ответственный Команда разработки · Разработка сервера · Совместно Команда разработки · Разработка клиента
Команда разработки: задачи
Сервер: включить TCP_NODELAY, собирать сообщения за тик и записывать их за один раз. На отключение отложенного ACK у получателя не полагаться (TCP_QUICKACK в Linux действует недолго, в Windows нужно править реестр на каждом ПК): игра не может надёжно этим управлять. Клиент: включить TCP_NODELAY, собирать сообщения за кадр и записывать их за один раз.
Цифры для ориентира
Отложенный ACK в Linux обычно 40 ms (в зависимости от ситуации до 200 ms). В старых версиях Windows было 200 ms, в современных 40 ms (в стандартном шаблоне Windows Server 2019 тоже 40 ms). Задержку ACK определяет ОС получателя, поэтому, если сервер с включённым Nagle отправляет сообщения по частям, задержка в зависимости от ПК игрока может составлять 40–200 ms.
На графике
Высоко с самого начала · время отклика на действие (RTT внутри игры)
Где смотреть
Посмотреть в захвате пакетов на стороне сервера (tcpdump, Wireshark) интервалы между запросами и ответами и проверить, включает ли код сервера и клиента TCP_NODELAY
Подтверждает
Пинг низкий, но между мелкими пакетами повторяются паузы около 40 ms (в старых версиях Windows 200 ms), и каждая пауза заканчивается сразу после прихода ACK от другой стороны. С TCP_NODELAY паузы исчезают
Опровергает
Если интервал ответа близок к пингу, причина в другом. Если игровой сервер сам поздно формирует ответ, дело в обработке на сервере («Затор в очереди сообщений»)
Чем проверить
Инструменты инфраструктуры (игровой код не нужен)
Источников: 5
RFC 9293: Transmission Control Protocol (TCP)IETF Пока есть данные без ACK, алгоритм Нейгла копит мелкие порции. Должна быть возможность отключить его для каждого соединения. Отложенный ACK меньше 0,5 с. Описана проблема их взаимодействия
include/net/tcp.h (Linux v6.12)Linux kernel Отложенный ACK в Linux: минимум TCP_DELACK_MIN (HZ/25 = 40 ms), максимум TCP_DELACK_MAX (HZ/5 = 200 ms)
ID sk-block-send · Основной ответственный Команда разработки · Разработка сервера
Если у одного игрока с медленным подключением заполнился буфер отправки, а сервер отправляет данные блокирующим способом (вызов не возвращается, пока в буфере не освободится место), поток сервера ждёт этого одного игрока.
Почему Буфер отправки медленного клиента заполнен → Следствие Отправка блокирующая, и поток сервера ждёт, пока в буфере освободится место → На экране У всех, кого обслуживает этот поток, фриз или слоумо
Основной ответственный Команда разработки · Разработка сервера
Команда разработки: задачи
Перейти на неблокирующую отправку, ограничить очередь отправки для каждого клиента, выбрасывать устаревшие обновления.
На графике
Случайные всплески · время тика сервера, Send-Q по соединениям
Где смотреть
Найти через ss -tn соединения, у которых Send-Q (байты без ACK или ещё не отправленные) заполнен на весь буфер отправки, и в момент всплеска времени тика посмотреть в дампе потоков (стеках) игрового сервера, нет ли потоков, застрявших в вызове send
Подтверждает
Когда есть медленное соединение с заполненным Send-Q, обслуживающий его поток стоит в send, и вместе с ним замирают только игроки, которых обслуживает тот же поток
Опровергает
Если остановившийся поток ждёт вне send (на блокировке, в вызове БД), это «Конкуренция за блокировки» или «Синхронные вызовы в игровом потоке»
Чем проверить
Инструменты инфраструктуры (игровой код не нужен)
Источников: 3
send(2) — Linux manual pageLinux man-pages Если в буфере отправки нет места, send() блокируется, а в неблокирующем режиме сразу возвращает EAGAIN
send function (winsock2.h)Microsoft В Winsock send тоже блокируется при нехватке места в буфере, если сокет не в неблокирующем режиме
net/ipv4/tcp_diag.c (Linux v6.12)Linux kernel Значения Recv-Q и Send-Q в ss: у слушающего сокета это число подключений, ждущих accept, и лимит backlog, у подключённого сокета это байты, ещё не прочитанные приложением, и отправленные байты без ACK
ID sk-slow-client · Основной ответственный Команда разработки · Разработка сервера
Если для клиента постоянно копятся неотправленные данные, сервер выбрасывает устаревшие обновления или разрывает соединение.
Почему Подключение клиента не справляется с объёмом, который отправляет сервер → Следствие Сервер выбрасывает устаревшие обновления или при превышении лимита разрывает соединение → На экране Только у этого игрока телепортация или дисконнект
Основной ответственный Команда разработки · Разработка сервера
Команда разработки: задачи
Сократить объём отправки (частота обновлений в зависимости от расстояния), продолжать отправку в пониженном качестве, уменьшить объём данных, который копится в ядре (TCP_NOTSENT_LOWAT в Linux).
Цифры для ориентира
При буфере отправки 256 KB и подключении 30 KB/s в буфере копится отставание больше чем на 8 секунд. К тому же Linux может автоматически увеличивать этот буфер до нескольких MB.
На графике
Высоко только у некоторых · Send-Q по соединениям, число выброшенных обновлений по клиентам
Где смотреть
Посмотреть, что игровой сервер пишет по каждому клиенту: длину очереди отправки, число выброшенных обновлений, причины обрывов. Заодно проверить на сервере через ss -tni Send-Q и cwnd этого соединения
Подтверждает
Send-Q постоянно заполнен только у соединений игроков, которых телепортирует или выкидывает из игры, а в игровом логе записаны выброшенные обновления этого игрока или обрыв из-за переполнения очереди отправки
Опровергает
Если Send-Q пуст, а телепортация есть, отправка на сервере ни при чём. Дело в потерях на подключении этого игрока («Потери на беспроводном участке») или в интерполяции на экране
Чем проверить
Нужны логи и метрики игрового сервера или клиента
Источников: 2
IP SysctlLinux kernel tcp_wmem: максимум автоматически настраиваемого буфера отправки по умолчанию от 64 KB до 4 MB (в зависимости от памяти). tcp_notsent_lowat и TCP_NOTSENT_LOWAT ограничивают объём ещё не отправленных данных
net/ipv4/tcp_diag.c (Linux v6.12)Linux kernel Значения Recv-Q и Send-Q в ss: у слушающего сокета это число подключений, ждущих accept, и лимит backlog, у подключённого сокета это байты, ещё не прочитанные приложением, и отправленные байты без ACK
ID sk-keepalive · Основной ответственный Команда разработки · Разработка сервера · Совместно Команда разработки · Разработка клиента, Команда инфраструктуры · Серверная инфраструктура
Если другая сторона пропадает без сигнала о закрытии, TCP замечает это очень нескоро. Keepalive (механизм TCP, который проверяет, живо ли неактивное соединение) по умолчанию выключен, а если его включить, проверка начинается только после 2 часов простоя.
Почему Клиент пропадает без сигнала о закрытии: выключилось питание или оборвалась связь → Следствие Сервер считает соединение живым (keepalive по умолчанию 7 200 с, а если оставались неотправленные данные, до отказа от повторных передач около 15 минут) → На экране В мире остаётся персонаж-фантом, а при перезаходе ошибка «Аккаунт уже в игре»
Основной ответственный Команда разработки · Разработка сервера · Совместно Команда разработки · Разработка клиента, Команда инфраструктуры · Серверная инфраструктура
Команда разработки: задачи
Сервер: отвечать на хартбиты, а если их долго нет, первым закрывать соединение (настроить TCP_KEEPIDLE и TCP_USER_TIMEOUT). При переподключении заменять старую сессию по токену сессии и продолжать игру. Клиент: отправлять хартбиты на уровне игры с интервалом от нескольких до десятков секунд (не больше половины самого короткого таймаута простоя), при обрыве автоматически переподключаться.
Команда инфраструктуры: задачи
Для сокетов, которым код не задаёт свои значения, снизить значения ядра по умолчанию (tcp_keepalive_time и др.; они действуют только на сокеты с включённым SO_KEEPALIVE).
Цифры для ориентира
По умолчанию Linux начинает проверку после 7 200 с простоя, отправляет 9 проб с интервалом 75 с и, если ответа так и нет, разрывает соединение. Всего выходит около 2 ч 11 мин. Windows по умолчанию тоже начинает проверку только после 2 часов простоя.
На графике
Высоко только у некоторых · время с последнего приёма по соединениям
Где смотреть
Посмотреть через ss -tnoi lastrcv (сколько ms прошло с последнего приёма) и таймер keepalive (timer:(keepalive,…)) по соединениям и сопоставить с записями игрового сервера об отказах «Аккаунт уже в игре»
Подтверждает
Остаются соединения ESTABLISHED с lastrcv от нескольких минут до нескольких часов, а перезаход с этого аккаунта отклоняется с ошибкой «Аккаунт уже в игре»
Опровергает
Если давно молчащих соединений нет, а «Аккаунт уже в игре» всё равно появляется, дело в коде очистки сессий на игровом сервере
Чем проверить
Инструменты инфраструктуры (игровой код не нужен)
Источников: 4
tcp(7) — Linux manual pageLinux man-pages После 7 200 с простоя 9 проб с интервалом 75 с (ещё около 11 минут). Действует только на сокеты с включённым SO_KEEPALIVE. Опции TCP_KEEPIDLE и TCP_USER_TIMEOUT
ID sk-fragment · Основной ответственный Команда разработки · Разработка сервера
UDP-пакет больше MTU (размера, который можно отправить за один раз) фрагментируется на уровне IP, и при потере всего одного фрагмента выбрасывается весь пакет.
Почему Снапшот людного места больше 1 500 байт → Следствие Пакет уходит несколькими фрагментами, и при потере любого из них выбрасывается целиком → На экране Чем больше пакет, тем в разы выше доля потерь. Телепортация только в людных местах
Основной ответственный Команда разработки · Разработка сервера
Команда разработки: задачи
Самим разбивать данные на пакеты не больше 1 200 байт, отправлять только изменения.
Цифры для ориентира
На линии с потерями 2% пакет из 4 фрагментов теряется примерно в 8% случаев. Некоторые файрволы и провайдеры вообще отбрасывают фрагментированные пакеты, и тогда игрок не получает ни одного большого пакета.
На графике
Растёт вслед за онлайном и нагрузкой · число IP-фрагментов (IpFragCreates), размер снапшота
Где смотреть
Посмотреть на сервере прирост IpFragCreates (число фрагментов, созданных при отправке) в nstat -az, а на принимающей стороне IpReasmFails (число неудачных сборок). Проверить распределение размеров UDP-пакетов по логам игрового сервера или захвату пакетов
Подтверждает
В людных местах растёт IpFragCreates, встречаются UDP-пакеты больше 1 500 байт, и в это же время растёт число жалоб на телепортацию
Опровергает
Если IpFragCreates не растёт, при отправке с сервера фрагментации нет
Чем проверить
Инструменты инфраструктуры (игровой код не нужен)
Источников: 3
RFC 8085: UDP Usage GuidelinesIETF Если потерян один фрагмент, пакет не собрать, и он теряется целиком. UDP-приложениям следует избегать IP-фрагментации
net/ipv4/proc.c (Linux v6.12)Linux kernel Имена счётчиков, которые показывает nstat: FragCreates (число созданных фрагментов) и ReasmFails (число неудачных сборок) в группе Ip
ID sk-reliable-udp · Основной ответственный Команда разработки · Разработка сервера · Совместно Команда разработки · Разработка клиента
Если собственные правила повторной передачи поверх UDP слишком осторожные, потери восстанавливаются поздно, а если слишком агрессивные, они ещё сильнее забивают линию.
Почему Интервал повторов, их число и размер окна не соответствуют качеству подключения → Следствие Восстановление запаздывает, либо дублирующие передачи усиливают перегрузку → На экране Умения «съедаются», перемотка, при перегрузке лаги сильнее
Основной ответственный Команда разработки · Разработка сервера · Совместно Команда разработки · Разработка клиента
Команда разработки: задачи
Сервер: повторно передавать по измеренному RTT, разделить каналы доставки по важности данных. Клиент: применить те же настройки повторной передачи и каналов, что и на сервере.
На графике
Случайные всплески · доля повторных передач надёжного UDP, RTT внутри игры
Где смотреть
Логировать на сервере и клиенте статистику, которую используемая библиотека ведёт по каждому соединению (число повторных передач, оценка RTT, ожидание перед повтором), и сравнить с реальной долей потерь на подключении того же игрока (измеренной mtr)
Подтверждает
Если доля повторных передач в разы выше реальной доли потерь, настройки слишком агрессивные. Если ожидание перед повтором в разы больше измеренного RTT, слишком осторожные
Опровергает
Если доля повторных передач близка к доле потерь, а ожидание соответствует RTT, с настройками всё в порядке. Смотреть сами потери на подключении
Чем проверить
Нужны логи и метрики игрового сервера или клиента
Источников: 1
RFC 8085: UDP Usage GuidelinesIETF Повторные передачи могут усиливать перегрузку, поэтому на них распространяется управление перегрузкой. RTT оценивают как среднее по нескольким измерениям (EWMA), начальное значение 1 секунда, при срабатывании таймера скорость передачи снижают
ID sk-slowstart · Основной ответственный Команда инфраструктуры · Серверная инфраструктура · Совместно Команда разработки · Разработка сервера
Если соединение какое-то время простаивало, TCP снова уменьшает окно перегрузки (объём, который можно отправить за раз), и внезапно понадобившийся большой объём данных уходит в несколько заходов.
Почему По простаивавшему соединению отправляется большой объём данных, например при входе в город → Следствие Окно перегрузки уменьшено, и передача растягивается на несколько RTT → На экране Сразу после входа окружающие персонажи и NPC появляются с опозданием на несколько RTT (тем заметнее, чем дальше сервер)
Основной ответственный Команда инфраструктуры · Серверная инфраструктура · Совместно Команда разработки · Разработка сервера
Команда разработки: задачи
Уменьшить объём данных при входе (сначала отправлять самое необходимое).
Команда инфраструктуры: задачи
Выключить tcp_slow_start_after_idle (Linux, настройка на весь сервер).
Цифры для ориентира
Если простой дольше RTO, окно перегрузки начинает уменьшаться и после долгого простоя опускается примерно до 14 KB (10 пакетов). Тогда 100 KB не уйдут за один раз и будут переданы за 3 RTT.
На графике
Высоко только у некоторых · время передачи сразу после входа (у игроков с большим RTT)
Где смотреть
Проверить значение sysctl net.ipv4.tcp_slow_start_after_idle и в момент входа в локацию после простоя посмотреть в ss -ti, не уменьшился ли cwnd (окно перегрузки) этого соединения
Подтверждает
Параметр равен 1 (по умолчанию), в момент входа после простоя cwnd падает примерно до 10, и передача растягивается на несколько RTT. Чем больше RTT у игрока, тем позже всё появляется, а при значении 0 эффект пропадает
Опровергает
Если cwnd остаётся большим, а объекты всё равно появляются поздно, дело в обработке входа на сервере («Лавина спавна при входе в людное место»)
Чем проверить
Инструменты инфраструктуры (игровой код не нужен)
Источников: 4
IP SysctlLinux kernel tcp_slow_start_after_idle по умолчанию включён: после простоя длиной в RTO окно перегрузки уменьшается (по схеме RFC 2861)
RFC 5681: TCP Congestion ControlIETF Если данные не отправлялись дольше RTO, окно перегрузки уменьшается до окна перезапуска min(IW, cwnd) или меньше и начинается медленный старт
ID sk-congestion · Основной ответственный Команда инфраструктуры · Серверная инфраструктура · Совместно Команда разработки · Разработка сервера
TCP считает потери признаком перегрузки и снижает скорость передачи на 30–50%. Точно так же он реагирует и на потери в Wi-Fi.
Почему Когда отправлять нужно много, в Wi-Fi или на линии случаются небольшие потери → Следствие TCP резко снижает скорость передачи и восстанавливает её медленно (CUBIC, алгоритм по умолчанию в Linux и Windows, снижает на 30%) → На экране В людных местах обновления отстают: перемотка, задержка ввода
Основной ответственный Команда инфраструктуры · Серверная инфраструктура · Совместно Команда разработки · Разработка сервера
Команда разработки: задачи
Сократить объём отправки (зона интереса, только изменения), отправлять порциями, не всё разом.
Команда инфраструктуры: задачи
Перейти на другой алгоритм управления перегрузкой, например BBR (tcp_congestion_control).
На графике
Пила: плавный рост и резкий сброс · окно перегрузки (cwnd) и скорость передачи по соединениям
Где смотреть
Несколько раз снять ss -ti для соединения игрока с отстающими обновлениями и посмотреть, как меняются cwnd и ssthresh, какой алгоритм управления перегрузкой используется (cubic, bbr) и копится ли Send-Q
Подтверждает
После потерь cwnd раз за разом резко падает и медленно растёт снова, а пока он мал, копится Send-Q, и это совпадает по времени с жалобами на перемотку и задержку ввода
Опровергает
Если cwnd достаточный, а обновления всё равно отстают, дело в окне приёма («Нулевое окно (остановка, похожая на повторную передачу)») или в отправке на сервере
IP SysctlLinux kernel tcp_congestion_control выбирает алгоритм управления перегрузкой для новых соединений
ss(8) — Linux manual pageiproute2 cwnd, ssthresh и название алгоритма управления перегрузкой в выводе -i
net/ipv4/tcp_diag.c (Linux v6.12)Linux kernel Значения Recv-Q и Send-Q в ss: у слушающего сокета это число подключений, ждущих accept, и лимит backlog, у подключённого сокета это байты, ещё не прочитанные приложением, и отправленные байты без ACK
ID sk-linger · Основной ответственный Команда разработки · Разработка сервера
Если сервер резко рвёт соединение, последнее отправленное сообщение или подтверждение сохранения пропадает.
Почему Сервер закрывает соединение принудительно (RST). Так бывает, если SO_LINGER выставлен в 0 с или сокет закрыт, когда полученные данные ещё не дочитаны → Следствие Причина кика и последние данные, которые ещё передавались, выбрасываются → На экране Сообщение «Соединение закрыто из-за неизвестной ошибки» без видимой причины
Основной ответственный Команда разработки · Разработка сервера
Команда разработки: задачи
Отправив причину, сначала закрыть только направление отправки (shutdown), дочитать полученные данные, пока другая сторона не закроет соединение, и только потом закрыть сокет. Не использовать SO_LINGER с 0 с.
На графике
Случайные всплески · число соединений, завершённых через RST
Где смотреть
Посмотреть прирост TcpExtTCPAbortOnData (закрыто через RST с неотправленными данными, SO_LINGER 0 с) и TcpExtTCPAbortOnClose (закрыто с непрочитанными данными) в nstat -az, а в захвате пакетов на стороне сервера проверить, уходит ли в момент обрыва RST вместо FIN
Подтверждает
В моменты жалоб на «Соединение закрыто из-за неизвестной ошибки» сервер отправляет RST, а AbortOnData и AbortOnClose растут
Опровергает
Если сервер штатно закрыл соединение через FIN, а причина не показана, дело в обработке закрытия на клиенте
Чем проверить
Инструменты инфраструктуры (игровой код не нужен)
Источников: 4
closesocket function (winsock.h)Microsoft Если включить SO_LINGER со временем 0, закрытие становится принудительным: соединение сразу сбрасывается, а неотправленные данные теряются
SNMP counterLinux kernel TcpExtTCPAbortOnData: соединение закрыто через RST с неотправленными данными (например, при SO_LINGER 0 с). TcpExtTCPAbortOnClose: сокет закрыт с непрочитанными данными, и отправлен RST
ID sk-blocking-io · Основной ответственный Команда разработки · Разработка сервера
Если поток, ожидая один сокет, не может делать ничего другого, то с ростом числа игроков тормозит всё.
Почему Поток ждёт чтения и записи по каждому соединению → Следствие Задержка одного соединения распространяется на другие соединения того же потока → На экране Чем выше онлайн, тем сильнее у всех слоумо и задержка ввода
Основной ответственный Команда разработки · Разработка сервера
Команда разработки: задачи
Перейти на асинхронный ввод-вывод на базе epoll, IOCP или io_uring.
На графике
Растёт вслед за онлайном и нагрузкой · время ответа, число потоков
Где смотреть
Посмотреть через pidstat -w -t число потоков игрового сервера и добровольные переключения контекста по потокам (cswch/s, сколько раз поток останавливался в ожидании ресурса) и сравнить с временем ответа в зависимости от онлайна
Подтверждает
С ростом онлайна время ответа круто растёт, потоков становится столько же, сколько соединений, и большинство из них почти не используют CPU, зато часто добровольно переключаются (ждут сокет)
Опровергает
Если потоки не ждут и постоянно загружают CPU, это перегрузка расчётами («Превышение бюджета тика»)
Чем проверить
Инструменты инфраструктуры (игровой код не нужен)
Источников: 3
epoll(7) — Linux manual pageLinux man-pages Механизм уведомлений о событиях ввода-вывода, который масштабируется на одновременное наблюдение за множеством fd
I/O Completion PortsMicrosoft Способ Windows обрабатывать множество асинхронных операций ввода-вывода заранее созданным пулом потоков
pidstat(1) — Linux manual pagesysstat cswch/s в выводе -w: добровольные переключения контекста, когда поток сам останавливается в ожидании ресурса. -t выводит данные по потокам
ID sk-reuseport · Основной ответственный Команда разработки · Разработка сервера · Совместно Команда инфраструктуры · Серверная инфраструктура
Когда несколько процессов принимают трафик на одном порту, ядро закрепляет каждое подключение за процессом по хешу адреса и больше его не меняет. Если один процесс зависает, ждут только игроки, закреплённые за ним.
Почему Шлюз или сервер авторизации запускает несколько процессов с SO_REUSEPORT → Следствие Если один процесс останавливается из-за GC или перегрузки, закреплённые за ним новые подключения и UDP-пакеты к другим процессам не переходят → На экране Только у части игроков ошибка входа или фриз. При перезапуске со сменой числа процессов часть UDP-сессий обрывается
Основной ответственный Команда разработки · Разработка сервера · Совместно Команда инфраструктуры · Серверная инфраструктура
Команда разработки: задачи
Не допускать остановок принимающего потока, реализовать передачу сессий при перезапуске.
Команда инфраструктуры: задачи
Следить за очередью подключений каждого процесса (Recv-Q в ss), а если при деплое меняется число процессов, следовать процедуре передачи сессий.
На графике
Высоко только у некоторых · очередь подключений (Recv-Q) по слушающим сокетам
Где смотреть
Посмотреть через ss -ltnp для каждого слушающего сокета на этом порту Recv-Q (число подключений, ждущих accept) и процесс-владелец, сравнить пропускную способность процессов
Подтверждает
Из нескольких сокетов на одном порту Recv-Q постоянно растёт только у одного, а процесс этого сокета стоит или его пропускная способность близка к 0
Опровергает
Если Recv-Q растёт равномерно у всех сокетов, это общая перегрузка («Переполнение очереди подключений (backlog)»)
Чем проверить
Инструменты инфраструктуры (игровой код не нужен)
Источников: 4
socket(7) — Linux manual pageLinux man-pages С SO_REUSEPORT несколько сокетов делают bind на один адрес и делят между собой TCP-подключения и UDP-пакеты
Why does one NGINX worker take all the load?Cloudflare SO_REUSEPORT делит подключения по очередям воркеров простым хешем, поэтому если один воркер застрял, встают все подключения в его очереди
net/ipv4/tcp_diag.c (Linux v6.12)Linux kernel Значения Recv-Q и Send-Q в ss: у слушающего сокета это число подключений, ждущих accept, и лимит backlog, у подключённого сокета это байты, ещё не прочитанные приложением, и отправленные байты без ACK
ID sk-udp-connreset · Основной ответственный Команда разработки · Разработка сервера
Когда сервер на Windows отправляет UDP уже ушедшему клиенту, обратно приходит уведомление «порт недоступен» (ICMP). Из-за него следующий вызов приёма завершается ошибкой, и если код сервера считает её поломкой самого сокета, страдают все, кто работает через этот сокет.
Почему Сервер продолжает слать UDP на адрес только что вышедшего клиента, и обратно приходит «порт недоступен» (ICMP) → Следствие Windows завершает следующий вызов приёма ошибкой WSAECONNRESET (10054), а код сервера прекращает приём или закрывает сокет → На экране У всех, кто работал через этот сокет, разом фриз или дисконнект
Основной ответственный Команда разработки · Разработка сервера
Команда разработки: задачи
Отключить SIO_UDP_CONNRESET через WSAIoctl, чтобы не получать это уведомление, а при ошибке приёма только писать в лог и продолжать приём.
На графике
Массовый обрыв соединений · число подключений, лог ошибок приёма
Где смотреть
Найти в логах игрового сервера коды ошибок приёма UDP (WSAECONNRESET, 10054) и записи об остановке цикла приёма или закрытии сокета, а по захвату пакетов на стороне сервера проверить, приходил ли перед этим ICMP Port Unreachable
Подтверждает
Прямо перед массовым обрывом подключений записана ошибка приёма WSAECONNRESET, а перед ней с адреса только что вышедшего клиента пришёл ICMP Port Unreachable
Опровергает
Неприменимо, если сервер на Linux или код уже отключил SIO_UDP_CONNRESET
Чем проверить
Нужны логи и метрики игрового сервера или клиента
Источников: 3
Winsock IOCTLsMicrosoft SIO_UDP_CONNRESET включает и выключает уведомления UDP «порт недоступен» (PORT_UNREACHABLE)
recvfrom function (winsock.h)Microsoft WSAECONNRESET на UDP-сокете означает, что на предыдущую отправку пришёл ответ ICMP Port Unreachable
ID sp-tick-overrun · Основной ответственный Команда разработки · Разработка сервера · Совместно Команда инфраструктуры · Серверная инфраструктура
Если работа одного тика не укладывается в бюджет, интервал тиков сервера растягивается, и вся локация идёт замедленно или с микрофризами.
Почему Работа на один тик (например, 50 ms) не укладывается в бюджет → Следствие Состояние игры, которое нужно считать 20 раз в секунду, считается только 8 раз → На экране Слоумо во всей локации (в зависимости от архитектуры сервера микрофризы), умения срабатывают с опозданием
Основной ответственный Команда разработки · Разработка сервера · Совместно Команда инфраструктуры · Серверная инфраструктура
Команда разработки: задачи
Сократить дорогие расчёты, распределить тик по нескольким потокам, распределять игроков (по каналам), записывать время обработки тика в метрики.
Команда инфраструктуры: задачи
Добавить время тика и загрузку CPU по ядрам в мониторинг и алерты, рассмотреть CPU и инстансы с высокой однопоточной производительностью (частотой).
Цифры для ориентира
У 20-тикового сервера бюджет 50 ms, у 30-тикового 33 ms, у 60-тикового 16,7 ms. На случай внезапного наплыва безопаснее держать запас и в обычное время расходовать примерно половину бюджета.
На графике
Растёт вслед за онлайном и нагрузкой · время тика сервера, число игроков по зонам и каналам, CPU игрового потока
Где смотреть
Вывести на один график время обработки тика (p99) и число превышений бюджета тика из метрик сервера вместе с числом игроков по зонам и каналам. Если метрик тика нет, смотреть загрузку CPU игрового потока через pidstat -t 1
Подтверждает
В моменты наплыва игроков время тика превышает бюджет (50 ms для 20-тикового сервера), а загрузка CPU игрового потока всё это время держится около 100%
Опровергает
Если тик не укладывается в бюджет, а CPU игрового потока загружен слабо, причина в ожидании (пауза GC, блокировки, синхронные вызовы). Если bcc runqlat показывает долгое ожидание в очереди выполнения, потоку не достаётся CPU: дело в нехватке CPU или избытке потоков
Чем проверить
Нужны логи и метрики игрового сервера или клиента
Подробнее
Как выглядят опаздывающие тики, зависит от архитектуры сервера. Если сервер за каждый тик продвигает состояние игры на фиксированное время (например, 50 ms), замедляется само игровое время, и получается слоумо. Если сервер за раз продвигает игру на реально прошедшее время, скорость игры сохраняется, но пакеты приходят реже, а объекты сдвигаются рывками, и это выглядит как микрофризы и телепортация. В обоих случаях отклик на ввод запаздывает. Если весь сервер обслуживает один игровой поток, тормозит весь сервер, а если у каждой локации свой поток, тормозит эта локация. Некоторые игры, например EVE Online, в крупных сражениях намеренно замедляют игровое время до 10 раз (Time Dilation), чтобы расчёты успевали.
VALORANT's 128-Tick ServersRiot Games 128-тиковый сервер должен укладываться в 7,8125 ms на кадр. Время серверного кадра измеряют по подсистемам и делят бюджет между ними
HED-GP Technical Retrospective: What a HED-acheCCP Games При перегрузке EVE Online замедляет игровое время через Time Dilation, нижний предел 10% (в 10 раз медленнее). В обычном режиме CPU узла ниже 80%
Handling variation in timeUnity Если симуляция с фиксированным шагом отстаёт, догоняющие шаги выполняются пачкой, а время сверх лимита отбрасывается, и игровое время идёт медленнее реального
ID sp-aoi · Основной ответственный Команда разработки · Разработка сервера
Если выяснять, кто кого видит, сравнивая всех со всеми, то при росте числа игроков в 10 раз расчёты растут в 100 раз.
Почему Расстояние сравнивается между всеми персонажами, или карта разбита на сетку, но вокруг одной ячейки собираются сотни игроков → Следствие Для 100 игроков около 10 000 сравнений, для 1 000 около 1 000 000 → На экране Там, где все собрались вместе (мировой босс, осада), время тика взлетает: слоумо, микрофризы
Основной ответственный Команда разработки · Разработка сервера
Команда разработки: задачи
Разбить мир на сетку или области и сравнивать только соседей, реже обновлять дальние объекты, ограничить число игроков, которых видит один игрок.
Цифры для ориентира
Если на каждую пару игроков с учётом сравнения расстояния и обновления списков видимости заложить 0,1 µs (одна десятимиллионная секунды), то для 1 000 игроков (около 1 000 000 пар) это 100 ms на тик. Вдвое больше бюджета 20-тикового сервера (50 ms).
На графике
Растёт вслед за онлайном и нагрузкой · время тика сервера, число игроков в одном месте
Где смотреть
Вывести на один график число игроков по зонам и каналам и время тика, а также отдельно измеренное время расчёта видимости внутри тика. Если отдельного замера нет, смотреть долю CPU по функциям игрового процесса через perf top -p
Подтверждает
Когда игроков в одном месте становится вдвое больше, время тика растёт почти в 4 раза, а большую часть процессорного времени занимают функции расчёта видимости и расстояний
Опровергает
Если время тика растёт пропорционально числу игроков или велика доля функций отправки и сериализации, дело во взрывном росте рассылки или в затратах на сериализацию и сжатие
Replication Graph in Unreal EngineEpic Games Стандартный подход, при котором для каждого актора перебираются все подключения, при большом числе игроков и акторов упирается в CPU сервера. В MMORPG и подобных играх мир делят на сетку и переиспользуют списки по ячейкам
perf-top(1) — Linux manual pageperf В реальном времени показывает долю CPU работающего процесса (-p) или потока (-t) по функциям (символам)
ID sp-broadcast · Основной ответственный Команда разработки · Разработка сервера · Совместно Команда инфраструктуры · Серверная инфраструктура
Если движение каждого игрока отправлять всем, кто его видит, число обновлений растёт как квадрат числа собравшихся.
Почему Изменение у одного игрока рассылается всем, кто его видит → Следствие Если 1 000 игроков видят друг друга, это 1 000 000 обновлений за тик → На экране Очереди отправки и пропускная способность забиты: задержки и потери (задержка ввода, перемотка, телепортация)
Основной ответственный Команда разработки · Разработка сервера · Совместно Команда инфраструктуры · Серверная инфраструктура
Команда разработки: задачи
Снижать частоту обновлений по расстоянию и важности (близкие враги каждый тик, дальние игроки несколько раз в секунду), ограничить объём отправки одному игроку и заполнять его в порядке важности, объединять несколько обновлений в один пакет, ограничить число отображаемых игроков.
Команда инфраструктуры: задачи
Сравнивать исходящую пропускную способность и число пакетов в секунду на каждом сервере с сетевыми лимитами NIC и инстанса и настроить алерты, проверять запас перед крупными событиями.
Цифры для ориентира
1 000 игроков × 1 000 игроков × 20 тиков = 20 000 000 обновлений в секунду. При 40 байтах на обновление это около 6,4 Gbps на весь сервер и около 6,4 Mbps на каждого получателя. Если ограничить число видимых игроков до 150, выходит около 1 Gbps на сервер и около 1 Mbps на игрока.
На графике
Растёт вслед за онлайном и нагрузкой · исходящие пакеты и байты сервера, число игроков в одном месте
Где смотреть
Смотреть txpck/s и txkB/s из sar -n DEV 1 (пакеты и KB, отправленные NIC сервера за секунду) вместе с графиком числа игроков. Для облачных инстансов смотреть счётчики превышения лимитов в ethtool -S (для AWS ENA bw_out_allowance_exceeded и pps_allowance_exceeded)
Подтверждает
С ростом числа собравшихся исходящие пакеты и байты растут круче, чем число игроков (почти квадратично), а с момента упора в лимит растут счётчики превышения лимитов или отбрасывания при отправке
Опровергает
Если исходящий трафик не меняется, а растёт только время тика, дело в расчёте видимости или игровой логике
Actor Priority in Unreal EngineEpic Games Когда пропускная способность соединения исчерпана, каждому актору назначается приоритет (расстояние, направление взгляда, время с последней отправки), и полоса раздаётся начиная с самых важных
Detailed Actor Replication Flow in Unreal EngineEpic Games NetUpdateFrequency задаёт частоту обновления для каждого актора. Акторы отправляются по приоритету, а когда соединение забито, остальные откладываются до следующего тика
sar(1) — Linux manual pagesysstat rxpck/s и txpck/s в sar -n DEV (принятые и отправленные пакеты в секунду), rxkB/s и txkB/s (принятые и отправленные KB в секунду)
ID sp-hotzone · Основной ответственный Команда разработки · Разработка сервера · Совместно Команда инфраструктуры · Серверная инфраструктура
Если каждую локацию обслуживает один поток, то при скоплении игроков в одном месте на 100% загружается только одно ядро.
Почему Одну локацию (канал) обслуживает один поток → Следствие Когда игроки собираются в одном месте, загружено только это ядро, остальные свободны → На экране Лагает только эта локация, в других всё нормально
Основной ответственный Команда разработки · Разработка сервера · Совместно Команда инфраструктуры · Серверная инфраструктура
Команда разработки: задачи
Распределять игроков по каналам, распараллелить обработку внутри локации, ограничить число игроков.
Команда инфраструктуры: задачи
Добавить загрузку CPU по ядрам в мониторинг и алерты (в среднем по серверу перегрузка одного ядра теряется).
Цифры для ориентира
На 16-ядерном сервере одно ядро на 100% даёт общую загрузку CPU всего около 6%. Найти это можно, только глядя на загрузку по ядрам.
На графике
Растёт вслед за онлайном и нагрузкой · загрузка CPU по ядрам, CPU по потокам
Где смотреть
Посмотреть загрузку по ядрам через mpstat -P ALL 1 и CPU по потокам игрового процесса через pidstat -t 1, сравнить с числом игроков в зоне, которую обслуживает самый загруженный поток
Подтверждает
Общая загрузка CPU низкая, но один поток (одно ядро) держится около 100%, и в это время в зоне этого потока скопились игроки
Опровергает
Если равномерно загружены многие ядра, это общая перегрузка сервера. Если высок только %soft (обработка приёма) на одном ядре, дело в том, что прерывания NIC сосредоточены на одном ядре
Чем проверить
Инструменты инфраструктуры (игровой код не нужен)
Подробнее
Другие локации в порядке, только если тики в каждой локации идут независимо. Если потоки локаций каждый тик ждут друг друга, чтобы вместе перейти к следующему тику, самая загруженная локация замедляет тики всего сервера.
Time Dilation – How’s That Going?CCP Games Time Dilation в EVE Online действует на весь узел, поэтому замедляются и далёкие звёздные системы на том же узле. Крупные сражения обрабатывают на усиленных узлах, где размещены только 4 системы
mpstat(1) — Linux manual pagesysstat Показывает загрузку по процессорам и общее среднее отдельно (-P ALL). %soft: доля времени на обработку программных прерываний
ID sp-lock · Основной ответственный Команда разработки · Разработка сервера
Если несколько потоков ждут одну блокировку, чтобы работать с одними и теми же данными, то сколько потоков ни добавляй, выполняется только один за раз.
Почему Несколько потоков одновременно работают с общими данными, например аукционом или хранилищем гильдии → Следствие Пока поток, захвативший блокировку, не закончит, остальные ждут → На экране Тормозит только определённая функция, в тяжёлых случаях отстают тики всего сервера
Основной ответственный Команда разработки · Разработка сервера
Команда разработки: задачи
Дробить блокировки, сокращать работу под блокировкой, перейти на архитектуру на сообщениях (у каждых данных свой поток-владелец, а остальные потоки только отправляют ему запросы сообщениями).
Цифры для ориентира
Если работа под блокировкой занимает 20% задачи, то сколько потоков ни добавляй, производительность вырастет максимум в 5 раз по сравнению с одним потоком, а при 40% остановится на 2,5 раза.
На графике
Растёт вслед за онлайном и нагрузкой · время обработки запросов, CPU и переключения контекста по потокам
Где смотреть
Смотреть добровольные переключения контекста по потокам через pidstat -w -t 1 (cswch/s, сколько раз поток останавливался в ожидании ресурса) и через bcc offcputime -p, где потоки ждут вне CPU (время ожидания по стекам вызовов). Для .NET смотреть число конфликтов блокировок в dotnet-counters (начиная с .NET 9 dotnet.monitor.lock_contentions, в 8 и ниже Monitor Lock Contention Count)
Подтверждает
С ростом нагрузки загрузка CPU остаётся низкой, а время обработки растёт. Большая часть ожидания приходится на стеки вызовов, пытающиеся захватить блокировку, и вместе с этим растёт число конфликтов блокировок
Опровергает
Если CPU загружен полностью, дело в объёме расчётов (превышение бюджета тика, перегрузка однопоточной локации). Если потоки ждут в вызовах БД или файлов, дело в синхронных вызовах в игровом потоке
Чем проверить
Инструменты инфраструктуры (игровой код не нужен)
Подробнее
Это бывает там, где несколько потоков вместе меняют игровые данные. Если каждую локацию или функцию обслуживает один поток и потоки общаются только сообщениями, блокировок почти нет, зато нужно следить, чтобы работа не скапливалась на одном потоке (перегрузка однопоточной локации). Если игровой поток ждёт блокировку, которую держит медленная операция сохранения, стоит весь тик.
Amdahl's Law in the Multicore EraIEEE Статья в IEEE Computer 2008 (авторская версия). Если доля работы, которую нельзя распараллелить, равна 1−f, то сколько ядер ни добавляй, ускорение не превысит 1/(1−f) (закон Амдала)
Request schedulingMicrosoft Грейны (акторы) Orleans работают по однопоточной модели и обрабатывают запросы по одному до конца, поэтому состояние не меняется одновременно. Если грейны ждут ответа друг от друга, возможен дедлок
pidstat(1) — Linux manual pagesysstat cswch/s в выводе -w: число добровольных переключений контекста, когда поток остановился в ожидании ресурса. -t выводит данные по потокам
Well-known EventCounters in .NETMicrosoft Monitor Lock Contention Count (monitor-lock-contention-count): сколько раз попытка захватить блокировку монитора наткнулась на конкуренцию
.NET runtime metrics.NET Начиная с .NET 9 dotnet.monitor.lock_contentions: сколько раз с запуска процесса попытка захватить блокировку монитора наткнулась на конкуренцию
ID sp-deadlock · Основной ответственный Команда разработки · Разработка сервера
Если два потока ждут блокировки, захваченные друг другом, они встают навсегда.
Почему Поток A держит блокировку 1 и ждёт блокировку 2, а поток B держит блокировку 2 и ждёт блокировку 1 → Следствие Оба встают навсегда, а за ними цепочкой встают и связанные потоки → На экране Весь сервер стоит, watchdog его перезапускает, у всех дисконнект
Основной ответственный Команда разработки · Разработка сервера
Команда разработки: задачи
Ввести правило порядка захвата блокировок, использовать блокировки с таймаутом, поставить watchdog и сохранять дамп потоков в момент зависания.
На графике
Массовый обрыв соединений · число подключений, исходящий трафик сервера
Где смотреть
Пока сервер стоит, снять стеки вызовов всех потоков. Для JVM jstack (сам находит и показывает дедлоки), для .NET dotnet-stack, для нативного сервера thread apply all bt в gdb, либо снять core-файл через gcore и разобрать его после перезапуска
Подтверждает
Два или больше потоков стоят со стеками, в которых каждый ждёт блокировку, захваченную другим, а загрузка CPU процессом всё это время близка к 0
Опровергает
Если во время зависания один поток крутится на 100% CPU, это бесконечный цикл. Если потоки ждут ответа БД или внешних сервисов, дело в синхронных вызовах или исчерпании пула потоков
Чем проверить
Инструменты инфраструктуры (игровой код не нужен)
Источников: 6
Runtime locking correctness validatorLinux kernel Если две блокировки захватываются в противоположном порядке, возникает циклическое ожидание и дедлок (lock inversion deadlock). Ядро Linux проверяет порядок захвата блокировок и предупреждает заранее
Liveness, Readiness, and Startup ProbesKubernetes Дедлок, при котором приложение работает, но не может продвинуться, ловят liveness-проверкой и перезапускают контейнер
ID sp-sync-call · Основной ответственный Команда разработки · Разработка сервера
Если посреди тика ждать ответа БД или записи в файл, на это время останавливается вся игра на сервере.
Почему Внутри тика поток ждёт запросов и сохранений в БД, записи логов, вызовов внешних API → Следствие Если БД отвечает 100 ms, тик тоже стоит 100 ms → На экране Каждый раз, когда тормозит БД или диск, вся открытая локация на миг замирает
Основной ответственный Команда разработки · Разработка сервера
Команда разработки: задачи
Всю медленную работу (запросы и сохранения в БД, запись логов, вызовы внешних API) выполнять асинхронно, а результат применять в следующем тике (если только поставить таймаут, на время ожидания игра всё равно встанет).
Цифры для ориентира
Даже RTT до БД в том же ЦОД 0,5 ms при 100 вызовах за тик даёт 50 ms. Это весь бюджет 20-тикового сервера.
На графике
Случайные всплески · время тика сервера, задержка запросов к БД
Где смотреть
Наложить на одну временную ось график времени тика, задержку запросов к БД (slow query log и т. п.) и задержку диска. Если метрик тика нет, смотреть через bcc offcputime -p, где ждёт игровой поток
Подтверждает
Всплески времени тика совпадают со всплесками задержки БД или файлов, а ожидание игрового потока приходится на стеки вызовов приёма ответа БД и записи в файл
Опровергает
Если задержки БД и диска ровные, а время тика скачет, дело в паузах GC или конкуренции за блокировки
ASP.NET Core Best PracticesMicrosoft Доступ к данным, ввод-вывод и долгие операции вызывать асинхронно. Синхронные блокирующие вызовы ведут к исчерпанию пула потоков и задержкам ответа
ID sp-queue · Основной ответственный Команда разработки · Разработка сервера
Если запросы поступают быстрее, чем обрабатываются, и копятся в очереди, запросы в её хвосте обрабатываются лишь через несколько секунд или выбрасываются.
Почему Запросы приходят быстрее, чем обрабатываются → Следствие Очередь растёт, а при превышении лимита запросы выбрасываются → На экране Умения и обмены срабатывают с опозданием или «съедаются»
Основной ответственный Команда разработки · Разработка сервера
Команда разработки: задачи
Мониторить длину очереди, ввести политику, при которой в первую очередь выбрасываются устаревшие запросы, распараллелить обработку.
На графике
Упор в лимит (плато) · длина очереди и возраст самого старого сообщения, число обработанных в секунду
Где смотреть
Смотреть метрики сервера по каждой очереди: длину, возраст самого старого сообщения, число поступивших, обработанных и выброшенных в секунду. Если метрик в коде нет, смотреть через ss (или netstat) Recv-Q игрового сокета (объём, который ядро уже приняло, а процесс ещё не прочитал)
Подтверждает
Пока поступает больше, чем обрабатывается, число обработанных упирается в одно значение и дальше не растёт, а длина и возраст очереди и число выброшенных постоянно растут
Опровергает
Если очередь короткая и сообщения в ней свежие, а отклик всё равно запаздывает, дело в задержке на линии или в запаздывании самих тиков
Avoiding insurmountable queue backlogsAWS Amazon Builders' Library. Затор отслеживают по возрасту ожидающих сообщений. Системы реального времени обрабатывают сначала свежие данные (ближе к LIFO), а устаревшие сообщения могут выбрасывать
ss(8) — Linux manual pageiproute2 Утилита для просмотра статистики сокетов (сведения похожи на netstat). -p показывает процесс, который использует сокет
netstat(8) — Linux manual pagenet-tools Recv-Q: число байтов в подключённом сокете, которые программа пользователя ещё не забрала
ID sp-timer-burst · Основной ответственный Команда разработки · Разработка сервера
Если респавн всех монстров, окончание всех баффов и награды ровно в начале часа приходятся на один тик, этот тик становится в десятки раз тяжелее.
Почему Таймеры респавна, окончания эффектов, наград и автосохранения выставлены на одно и то же время → Следствие В этот один тик работы в десятки раз больше обычного → На экране В определённое время каждый раз всё на миг замирает
Основной ответственный Команда разработки · Разработка сервера
Команда разработки: задачи
Немного разбрасывать время таймеров случайным образом, распределять обработку по нескольким тикам.
На графике
Всплески с постоянным периодом · время тика сервера
Где смотреть
Собрать моменты всплесков времени тика и посмотреть на интервалы (ровно в начале часа, каждые 5 минут и т. п.). Сверить со списком таймеров респавна, окончания баффов, наград и автосохранения, которые срабатывают в это время
Подтверждает
Время тика скачет каждый раз в одно и то же время или через одинаковые интервалы, и в эти моменты разом срабатывают игровые таймеры
Опровергает
Если периодичность есть, но всплески совпадают с паузами в логе GC или с запуском cron и бэкапов на сервере, дело в полной паузе GC на сервере или в плановых заданиях
Чем проверить
Нужны логи и метрики игрового сервера или клиента
Источников: 1
Timeouts, retries, and backoff with jitterAWS Amazon Builders' Library. Ко всем таймерам, периодическим и отложенным заданиям добавляют случайный разброс (jitter), чтобы рассеять нагрузку, которая скапливается в одно время. Пример: ежеминутные запросы с многих серверов скапливались в первые секунды каждой минуты
ID sp-pathfinding · Основной ответственный Команда разработки · Разработка сервера
Когда сотни монстров одновременно гонятся за игроками и рассчитывают путь, это сильно нагружает CPU.
Почему Из-за сбора монстров «паровозом» и массового спавна монстры одновременно преследуют игроков → Следствие Каждый монстр рассчитывает путь → На экране Слоумо только на этом месте фарма
Основной ответственный Команда разработки · Разработка сервера
Команда разработки: задачи
Кэшировать пути, ограничить число расчётов, распределять их по нескольким тикам.
На графике
Растёт вслед за онлайном и нагрузкой · время тика сервера, число монстров по зонам
Где смотреть
Смотреть число монстров, преследующих игроков, по зонам и время тика. Если отдельного подсчёта нет, смотреть долю CPU по функциям игрового процесса через perf top -p
Подтверждает
При сборе «паровозом» и массовом спавне время тика растёт, а функции поиска пути занимают большую долю процессорного времени
Опровергает
Если время тика растёт, когда монстров мало, а игроков много, дело в расчёте видимости или рассылке
Чем проверить
Нужны логи и метрики игрового сервера или клиента
Источников: 2
AI.NavMesh.pathfindingIterationsPerFrameUnity Поиск пути обрабатывает за кадр только заданное число узлов и распределяется на несколько кадров, поэтому игра идёт плавно, даже когда пути длинные или запросов сразу много
ID sp-serialize · Основной ответственный Команда разработки · Разработка сервера
Превращение данных для отправки в байты и их сжатие тоже требуют CPU, и при большом числе игроков эти затраты резко растут.
Почему Для каждого обновления структура преобразуется в байты и сжимается → Следствие Затраты растут пропорционально квадрату числа игроков → На экране Отправка запаздывает: задержка ввода
Основной ответственный Команда разработки · Разработка сервера
Команда разработки: задачи
Переиспользовать один собранный пакет для многих получателей, использовать лёгкий формат.
На графике
Растёт вслед за онлайном и нагрузкой · загрузка CPU сервера, CPU потока, собирающего пакеты
Где смотреть
Сравнить через perf top -p долю функций сериализации, сжатия и шифрования (включая функции библиотек вроде zlib, LZ4, OpenSSL) в процессорном времени игрового процесса при малом числе игроков и при наплыве
Подтверждает
Чем больше игроков, тем выше доля функций сериализации, сжатия и шифрования, и первым упирается в CPU поток, собирающий пакеты
Опровергает
Если доля этих функций мала, дело в расчёте видимости или игровой логике
Чем проверить
Инструменты инфраструктуры (игровой код не нужен)
Подробнее
Если соединение шифруется (TLS, DTLS и т. п.), CPU тратится ещё и на шифрование и расшифровку. Шифрование делается отдельно для каждого соединения, поэтому, даже если один собранный пакет переиспользуется для многих получателей, шифровать его приходится столько раз, сколько получателей. Симметричные шифры вроде AES-GCM настолько быстры, что одно ядро обрабатывает несколько GB в секунду, и обычно их доля невелика. Но скорость сильно зависит от размера единицы шифрования (записи), и когда, как в играх, много мелких пакетов, затраты на байт растут. При рукопожатии, которое выполняется один раз на подключение, сервер подписывает данные ключом сертификата и вычисляет обмен ключами (ECDHE). Одно ядро успевает в секунду от примерно 1 100 (RSA 2048) до 18 000 (ECDSA P-256) подписей и около 9 000 обменов ключами, поэтому при наплыве входов это заметная нагрузка.
Источников: 4
Introduction to Iris in Unreal EngineEpic Games Реплицируемое состояние хранится в одной квантованной копии, что сокращает дорогую работу, а её результат используют сразу несколько подключений
VALORANT's 128-Tick ServersRiot Games Сравнивать реплицируемые переменные для каждого клиента каждый кадр и собирать изменившиеся значения медленно: память читается вразброс, и это сильно нагружает CPU сервера
How "expensive" is crypto anyway?Cloudflare Замеры BoringSSL: AES-128-GCM около 3,7 GB в секунду (сильно зависит от размера записи). Одно ядро в секунду выполняет 1 120 подписей RSA 2048, 18 477 подписей ECDSA P-256 и 9 394 обмена P-256 ECDHE. На edge-серверах Cloudflare TLS-библиотека расходует около 1,8% CPU
ID sp-crash · Основной ответственный Команда разработки · Разработка сервера · Совместно Команда инфраструктуры · Серверная инфраструктура
Если процесс сервера падает из-за необработанной ошибки, у всех, кто был на этом сервере, одновременно обрывается соединение.
Почему Фатальная ошибка: обращение к несуществующему объекту (нулевая ссылка), некорректные данные, нехватка памяти и т. п. → Следствие Процесс сервера (или зоны) завершается → На экране Дисконнект у всех одновременно, прогресс после последнего сохранения может уйти в роллбэк
Основной ответственный Команда разработки · Разработка сервера · Совместно Команда инфраструктуры · Серверная инфраструктура
Команда разработки: задачи
Разбирать краш-дампы и исправлять причины, сохранять чаще.
Команда инфраструктуры: задачи
Настроить автоматический перезапуск процесса, сбор и хранение краш-дампов, мгновенный алерт при падении сервера.
На графике
Массовый обрыв соединений · число подключений, число перезапусков процесса
Где смотреть
Смотреть записи о core dump в coredumpctl list (время, PID, сигнал завершения) и записи менеджера сервисов (systemd) об аварийных завершениях и перезапусках. На серверах Windows смотреть дампы, сохранённые WER
Подтверждает
В момент, когда число подключений резко падает почти до 0, есть аварийное завершение процесса игрового сервера и core dump
Опровергает
Если процесс жив, а соединения оборвались, дело в сетевом оборудовании или таймауте простоя. Если есть запись о перезапуске watchdog после долгого зависания, дело в бесконечном цикле или дедлоке
Чем проверить
Инструменты инфраструктуры (игровой код не нужен)
Источников: 3
Collecting User-Mode DumpsMicrosoft Через отчёты об ошибках Windows (WER) можно настроить локальный сбор полных дампов и мини-дампов при падении программ пользовательского режима
systemd.service(5) — Linux manual pagesystemd Restart=on-failure автоматически перезапускает сервис при аварийном завершении, завершении по сигналу (в том числе с core dump) и срабатывании watchdog. Рекомендуется для долгоживущих сервисов
coredumpctl(1) — Linux manual pagesystemd list показывает core dump, сохранённые systemd-coredump: время падения, PID и сигнал, вызвавший падение
ID sp-threadpool · Основной ответственный Команда разработки · Разработка сервера
Если все рабочие потоки заняты медленными задачами, новые запросы ждут неопределённо долго.
Почему Рабочие потоки заняты ожиданием ответа внешних API или БД → Следствие Для новых запросов не остаётся свободных потоков → На экране Бесконечная загрузка в отдельных функциях, например при входе или в магазине
При наплыве игроков, Сразу после входа или техработ
Ответственные
Основной ответственный Команда разработки · Разработка сервера
Команда разработки: задачи
Поставить таймауты на медленные вызовы, разделить пулы потоков по функциям, перейти на асинхронные вызовы.
На графике
Упор в лимит (плато) · число потоков и длина очереди пула потоков, время обработки запросов
Где смотреть
Для .NET смотреть в dotnet-counters monitor число потоков пула и длину очереди (начиная с .NET 9 dotnet.thread_pool.thread.count и dotnet.thread_pool.queue.length, в 8 и ниже ThreadPool Thread Count и ThreadPool Queue Length) и через dotnet-stack проверить, где ждут рабочие потоки. Для JVM и нативных серверов то же самое проверяют по дампу потоков
Подтверждает
Загрузка CPU намного ниже 100%, а число потоков медленно, но постоянно растёт или держится на пределе, очередь копится, и большинство рабочих потоков ждут ответа на один и тот же внешний вызов (БД, HTTP)
Опровергает
Если очередь пуста, а запросы всё равно обрабатываются медленно, тормозит сам вызываемый сервис: дело в каскадном отказе или зависимости от внешних сервисов
Чем проверить
Инструменты инфраструктуры (игровой код не нужен)
Подробнее
Если приём пакетов и игровая логика делят один пул рабочих потоков, то, как только несколько медленных задач займут все потоки, обработка пакетов на всём сервере остановится.
Debug ThreadPool StarvationMicrosoft Если в пуле не осталось свободных потоков и новые задачи ждут, ответы замедляются. Причина в блокирующем коде, который занимает потоки. Признак исчерпания в dotnet-counters: CPU намного ниже 100%, а dotnet.thread_pool.thread.count медленно, но постоянно растёт (часто велик и dotnet.thread_pool.queue.length). Где ждут потоки, проверяют через dotnet-stack
Avoiding insurmountable queue backlogsAWS Число одновременно обрабатываемых запросов = интенсивность поступления × задержка (закон Литтла). При 100 запросах в секунду рост задержки со 100 ms до 10 с увеличивает нужное число потоков с 10 до 1 000, и пул исчерпывается
Bulkhead PatternMicrosoft Azure Если для каждого вызываемого сервиса держать отдельный пул соединений и потоков, сбой одного сервиса блокирует только его пул
.NET runtime metrics.NET dotnet.thread_pool.thread.count (число потоков пула) и dotnet.thread_pool.queue.length (число ожидающих задач) доступны начиная с .NET 9
Well-known EventCounters in .NETMicrosoft ThreadPool Thread Count (threadpool-thread-count) и ThreadPool Queue Length (threadpool-queue-length) в .NET 8 и ниже
ID sp-infinite-loop · Основной ответственный Команда разработки · Разработка сервера
Если из-за бага тик не заканчивается, сервер встаёт, и watchdog принудительно его перезапускает.
Почему Из-за ошибочного условия цикл не завершается, или рекурсия уходит вразнос → Следствие Тик не заканчивается, сервер стоит → На экране Фриз, затем дисконнект у всех
Основной ответственный Команда разработки · Разработка сервера
Команда разработки: задачи
Ограничить число итераций, поставить watchdog, написать тесты, воспроизводящие проблемный ввод.
На графике
Массовый обрыв соединений · число подключений, CPU по потокам
Где смотреть
Во время зависания посмотреть CPU по потокам через pidstat -t 1 и проверить через perf top -t (ID потока) или gdb, в какой функции крутится поток на 100%. Если сервер уже перезапущен, искать записи о срабатывании watchdog (WatchdogSec в systemd, проваленная liveness-проверка в Kubernetes)
Подтверждает
Пока сервер стоит, один игровой поток держится на 100% CPU, а его стек всё время крутится внутри одной функции или цикла
Опровергает
Если во время зависания загрузка CPU близка к 0, дело в дедлоке или ожидании внешнего ответа
Чем проверить
Инструменты инфраструктуры (игровой код не нужен)
Источников: 4
systemd.service(5) — Linux manual pagesystemd WatchdogSec=: если сервис не отправит сигнал жизни (WATCHDOG=1) за заданное время, он считается сбойным и завершается, а затем в зависимости от настройки Restart= автоматически перезапускается
Liveness, Readiness, and Startup ProbesKubernetes Состояние, когда приложение работает, но не продвигается, ловят liveness-проверкой и перезапускают. По умолчанию проверка идёт каждые 10 секунд, а после 3 неудач подряд следует перезапуск
ID sp-hot-entity · Основной ответственный Команда разработки · Разработка сервера
Когда сотни игроков одновременно бьют одного босса, все расчёты по этому боссу сходятся в одной точке, а информация о каждом ударе рассылается всем, кто его видит.
Почему Сотни игроков без остановки применяют к одному боссу умения, баффы и дебаффы → Следствие Расчёты здоровья босса, списка агро и дебаффов сходятся в одной точке, а пакеты с цифрами урона и эффектами за каждый удар рассылаются всем, кто это видит → На экране Умения проходят с опозданием, цифры урона вылетают пачкой, слоумо только вокруг босса
Основной ответственный Команда разработки · Разработка сервера
Команда разработки: задачи
Объединять или не показывать чужие цифры урона и эффекты, ограничить число дебаффов на одной цели, распределять обработку ударов по нескольким тикам.
Цифры для ориентира
Если 800 игроков бьют по 2 раза в секунду, это 1 600 ударов в секунду. Если сообщать о каждом всем 800 зрителям, выходит 1 280 000 сообщений в секунду.
На графике
Растёт вслед за онлайном и нагрузкой · время тика сервера, число отправленных сообщений
Где смотреть
Смотреть время тика и число отправленных пакетов во время боя с боссом вместе с числом игроков вокруг босса, а если есть возможность, и число событий (ударов, баффов, дебаффов) в секунду по целям
Подтверждает
С ростом числа игроков вокруг босса время тика и исходящий трафик круто растут, а событий в секунду у одного босса в десятки раз больше, чем у других целей
Опровергает
Если всё так же тормозит при любом скоплении игроков, независимо от босса, дело в расчёте видимости или взрывном росте рассылки
Чем проверить
Нужны логи и метрики игрового сервера или клиента
Источников: 1
HED-GP Technical Retrospective: What a HED-acheCCP Games Даже об одной атаке нужно сообщить всем видящим её клиентам, поэтому возникает нагрузка O(n²): n игроков оповещают n игроков. У атак дронов, порождающих много сообщений, эта нагрузка растёт ещё быстрее
ID sp-spawn-burst · Основной ответственный Команда разработки · Разработка сервера · Совместно Команда разработки · Разработка клиента
Когда игрок телепортируется в город, полный людей, сервер должен разом отправить внешность, экипировку и состояние сотен персонажей, которые стали видны.
Почему Игрок внезапно оказывается в людном месте после телепорта, входа в игру или смены канала → Следствие Полные данные по сотням персонажей собираются и отправляются за раз, и ПК игрока тоже загружает их разом → На экране Сразу после прибытия короткий фриз, персонажи появляются с опозданием по одному, ввод запаздывает
В движении и при смене локации, Сразу после входа или техработ
Ответственные
Основной ответственный Команда разработки · Разработка сервера · Совместно Команда разработки · Разработка клиента
Команда разработки: задачи
Сервер: отправлять в порядке близости, распределяя по нескольким тикам, кэшировать данные о внешности. Клиент: получать данные заранее, пока идёт экран загрузки, создавать полученных персонажей, распределяя по нескольким кадрам.
Цифры для ориентира
Если внешность, экипировка и баффы одного персонажа занимают 300 байт, то на 500 персонажей это около 150 KB. В один момент наваливается в десятки раз больше, чем обычно отправляется за тик (единицы KB).
На графике
Всплеск сразу после входа или техработ · исходящие байты по соединениям, время кадра на клиенте
Где смотреть
Смотреть число байтов и пакетов, отправленных по соединению за первые секунды после прибытия в людное место (лог сервера), и время кадра на клиенте (нетграф, лог клиента)
Подтверждает
Сразу после прибытия исходящий трафик по соединению взлетает в десятки раз выше обычного тика и затем спадает, и в тот же момент скачет время кадра на клиенте
Опровергает
Если фриз такой же и при переходе в безлюдное место, дело в переходе между зонами (передаче на другой сервер) или в загрузке на клиенте
Чем проверить
Нужны логи и метрики игрового сервера или клиента
Источников: 2
Detailed Actor Replication Flow in Unreal EngineEpic Games При первом открытии actor channel вместе с ним отправляются начальные данные вроде позиции и поворота, а если соединение забито, остальные акторы откладываются до следующего тика
Actor Priority in Unreal EngineEpic Games Приоритет назначается по расстоянию и направлению взгляда, и сначала отправляются близкие и видимые акторы
ID sp-entity-buildup · Основной ответственный Команда разработки · Разработка сервера
Если предметы на земле, призванные существа и отработавшие таймеры, которые должны исчезать, не удаляются и копятся, то чем дольше сервер работает, тем больше работы в каждом тике.
Почему Предметы на земле, призванные существа, истёкшие таймеры и данные пустых групп вовремя не удаляются → Следствие Списки, которые обходятся каждый тик, с каждым днём становятся длиннее → На экране Сразу после техработ всё нормально, а через несколько дней именно этот сервер или локация постепенно начинает тормозить
Основной ответственный Команда разработки · Разработка сервера
Команда разработки: задачи
Записывать число объектов по локациям в метрики и следить за трендом, задать для объектов время жизни и предельное количество, регулярно проводить очистку.
Цифры для ориентира
Если сервер каждый тик обходит все объекты, то при удвоении числа объектов эта часть времени тика тоже удваивается.
На графике
Пила: плавный рост и резкий сброс · число объектов по зонам, время тика сервера
Где смотреть
Смотреть число объектов (предметы на земле, призванные существа, таймеры) по зонам и серверам и время тика за период дольше цикла техработ (несколько недель)
Подтверждает
Число объектов и время тика начинают с низкого уровня после техработ, растут день ото дня и резко падают при техработах или перезапуске, и так по кругу, а памяти всё это время хватает
Опровергает
Если время тика не меняется, а растёт только память, дело в утечке памяти
Чем проверить
Нужны логи и метрики игрового сервера или клиента
Подробнее
Как и утечка памяти, проблема усиливается со временем работы, но отличается тем, что памяти хватает, а растёт только время тика. Если график числа объектов имеет форму пилы с периодом техработ, это тот самый случай.
Источников: 2
Actor Ticking in Unreal EngineEpic Games Если отдельно не задать интервал, акторы и компоненты выполняют тик раз в кадр, а когда он не нужен, тик можно отключить
AActor::SetLifeSpanEpic Games Если задать актору время жизни, по его истечении актор уничтожается автоматически
ID sp-patch-traffic · Основной ответственный Команда разработки · Разработка сервера · Совместно Команда инфраструктуры · Серверная инфраструктура, Команда инфраструктуры · Сетевая инфраструктура
Если новый контент, эффекты и синхронизируемые поля увеличивают размер и частоту пакетов, сервер, который работал нормально, после патча упирается в MTU, пропускную способность или лимиты по числу пакетов.
Почему С патчем добавились эффекты умений, синхронизируемые поля и данные предметов, и пакеты стали больше или чаще → Следствие Большие пакеты превышают MTU и фрагментируются, а возросший объём упирается в пропускную способность, лимит PPS в облаке или буфер отправки → На экране Сразу после патча в людных местах телепортация, «съеденные» умения и задержка ввода. В инфраструктуре ничего не меняли, а потерь стало больше
Весь сервер, Одна локация или канал, Один регион или провайдер
Когда
При наплыве игроков, Вечерний пик, Всегда
Ответственные
Основной ответственный Команда разработки · Разработка сервера · Совместно Команда инфраструктуры · Серверная инфраструктура, Команда инфраструктуры · Сетевая инфраструктура
Команда разработки: задачи
Самим разбивать данные на пакеты не больше 1 200 байт. Для новых синхронизируемых полей отправлять только изменения и снижать частоту по расстоянию и важности. Перед деплоем сравнить на тестовом сервере число пакетов и байтов в секунду на игрока и размер самого большого пакета с предыдущей сборкой. Записывать версию сборки в метрики трафика.
Команда инфраструктуры: задачи
Серверы и ОС: отмечать время деплоя на графиках, сравнивать число пакетов и байтов в секунду на игрока и средний размер пакета до и после деплоя, настроить алерты по счётчикам превышения лимитов инстанса, при необходимости взять инстанс крупнее. Сеть: проверить пределы производительности файрвола, балансировщика нагрузки и оборудования защиты от DDoS и не блокируют ли они фрагменты.
Цифры для ориентира
Безопасный размер UDP-пакета не больше 1 200 байт. MTU пути в интернете обычно 1 500 байт, а через туннель ещё меньше (в GRE-туннеле 1 476 байт). Пакеты больше MTU пути фрагментируются или отбрасываются, а фрагментированный пакет теряется целиком при потере одного фрагмента. Если число пакетов в секунду на игрока растёт на 20%, на весь сервер оно тоже растёт на 20%, и инстанс, который работал близко к лимиту, сразу его превышает.
На графике
Ступенька вверх с определённого момента · пакеты и байты в секунду на игрока, средний размер пакета
Где смотреть
Разделить пакеты и байты в секунду на NIC сервера (rxpck/s, txpck/s, rxkB/s, txkB/s в sar -n DEV, для EC2 NetworkPacketsOut и NetworkOut) на онлайн и сравнить до и после деплоя. Средний размер пакета: байты ÷ пакеты, распределение размеров: статистика Packet Lengths в Wireshark по захвату пакетов
Подтверждает
Сразу после деплоя пакеты и байты на игрока или средний размер пакета ступенькой поднимаются и так и остаются, и с того же момента растут число фрагментов, созданных сервером (fragcrt/s в sar -n IP), или счётчики превышения лимитов инстанса (pps_allowance_exceeded и bw_out_allowance_exceeded в AWS ENA)
Опровергает
Если характер трафика до и после деплоя одинаковый, а выросли только задержки и потери, смотреть изменения инфраструктуры в то же время (настройки, маршруты, оборудование, обновления ОС и ядра)
Чем проверить
Инструменты инфраструктуры (игровой код не нужен)
Подробнее
Если приходят жалобы «до патча всё было нормально», это первая причина на стороне игры, которую стоит проверить наряду с изменениями инфраструктуры. Даже если в патчноуте нет сетевых изменений, один новый эффект или синхронизируемое поле в людном месте умножается на сотни игроков. Где именно возросший трафик упирается в пределы, разобрано в причинах «IP-фрагментация UDP-пакетов», «Превышен лимит PPS в облаке», «Исчерпание пропускной способности NIC», «Нехватка буферов сокетов в ядре» и «Перегрузка промежуточного оборудования (файрвол, IPS, защита от DDoS)». Эта причина описывает случай, когда к пределу подвёл игровой патч, поэтому, прежде чем поднимать лимиты, сначала сокращают трафик, добавленный патчем. Если в то же время обновляли ОС и ядро, отличить эту причину от причины «Изменение производительности после обновления ОС, ядра, драйверов или прошивки» помогает то, изменился ли трафик на игрока.
Источников: 7
RFC 8085: UDP Usage GuidelinesIETF UDP-приложениям не следует отправлять датаграммы больше MTU пути (SHOULD NOT). При потере одного фрагмента теряется весь фрагментированный пакет, а некоторые NAT и файрволы отбрасывают все фрагменты
sar(1) — Linux manual pagesysstat rxpck/s и txpck/s (пакеты в секунду), rxkB/s и txkB/s (KB в секунду) в sar -n DEV, fragcrt/s в sar -n IP (IP-фрагменты, созданные за секунду, ipFragCreates)
ID mem-gc · Основной ответственный Команда разработки · Разработка сервера · Совместно Команда инфраструктуры · Серверная инфраструктура
Сервер на Java или C# останавливает все потоки на время сборки мусора (stop-the-world), и на это время замирает весь сервер.
Почему Куча заполняется, запускается GC → Следствие Все игровые потоки останавливаются на время сборки (чем больше живых данных, тем дольше) → На экране У всех игроков сервера одновременно фриз, затем перемотка
Основной ответственный Команда разработки · Разработка сервера · Совместно Команда инфраструктуры · Серверная инфраструктура
Команда разработки: задачи
Явно задать в параметрах запуска сборщик с короткими паузами (ZGC, Shenandoah, G1 с уменьшенной целевой паузой), сократить аллокации, подобрать размер кучи.
Команда инфраструктуры: задачи
Брать инстансы с запасом памяти под кучу, контейнерам выделять не меньше 2 CPU и около 1,8 GB памяти (при меньших ресурсах JDK 26 и ниже по умолчанию выбирает Serial GC), отслеживать длительность пауз GC.
Цифры для ориентира
Minor GC, который собирает только новые объекты (область Young), занимает от единиц до десятков ms. Full GC по всей куче с несколькими GB живых данных может длиться больше 1 секунды. У ZGC паузы короче 1 ms почти независимо от размера кучи, у Shenandoah паузы тоже короткие, потому что не растут вместе с кучей.
На графике
Всплески с постоянным периодом · время тика сервера, длительность пауз GC
Где смотреть
Включить GC-лог и наложить моменты и длительность пауз на график времени тика сервера. Для Java смотреть строки Pause в логе, который включает параметр запуска -Xlog:gc* (в JDK 8 и ниже -XX:+PrintGCDetails), для .NET метрику пауз GC в dotnet-counters (с .NET 9 dotnet.gc.pause.time, в 8 и ниже % Time in GC since last GC), для Go строки, которые GODEBUG=gctrace=1 пишет на каждый GC
Подтверждает
Всплески времени тика совпадают с паузами GC, длительность пауз близка к длительности всплесков. Во всех зонах и каналах сервера всплеск в один и тот же момент
Опровергает
Если в GC-логе нет длинных пауз, а тик всё равно скачет, причина другая: блокировки, синхронные вызовы, запись на диск. Если скачет только одна зона, это GC скриптового движка (mem-script-gc) или нагрузка в этой зоне
Чем проверить
Инструменты инфраструктуры (игровой код не нужен)
Подробнее
У G1 в Java целевая длительность одной паузы по умолчанию 200 ms, а на 20-тиковом сервере это 4 тика. Если контейнеру дать меньше 2 CPU или меньше примерно 1,8 GB памяти, Java версии JDK 26 и ниже выбирает по умолчанию Serial GC, который собирает мусор в один поток, и паузы становятся намного длиннее. На серверах C# (.NET) обычно включают серверный и фоновый GC, но сборка поколений 0 и 1 (Gen0 и Gen1), где лежат новые объекты, и Full GC со сжатием кучи по-прежнему останавливают все потоки. В Go паузы обычно короче 1 ms, но при большом объёме аллокаций горутине, которая запрашивает память, приходится брать на себя часть работы GC, и тик замедляется. При любом подходе, если аллокации идут быстрее сборки, игровые потоки в итоге останавливаются. G1 переходит к Full GC, а ZGC останавливает запросивший память поток до конца сборки.
Garbage-First (G1) Garbage CollectorOracle Целевая пауза G1 по умолчанию 200 ms (MaxGCPauseMillis). Если во время сборки кончается память, G1 переходит к Full GC с полной остановкой и сжатием всей кучи
JEP 439: Generational ZGCOpenJDK Паузы ZGC не дольше 1 ms и не зависят от размера кучи, паузы G1 от единиц ms до нескольких секунд. Если аллокации опережают освобождение памяти, возможна остановка аллокаций (allocation stall)
Background garbage collection.NET Фоновый GC применяется только к сборке поколения 2, а сборка поколений 0 и 1 (GC переднего плана) останавливает все управляемые потоки
A Guide to the Go Garbage CollectorGo GC в Go работает в основном конкурентно, полные остановки короткие. При большом объёме аллокаций горутины берут на себя часть работы GC (assist), и появляются задержки
JEP 271: Unified GC LoggingOpenJDK Начиная с JDK 9 GC-лог переведён на единое журналирование (-Xlog). -Xlog:gc, как прежний -XX:+PrintGC, пишет по строке на каждый GC
The java CommandOracle Таблица замены старых параметров GC-лога на -Xlog: -XX:+PrintGCDetails соответствует -Xlog:gc*
dotnet-counters diagnostic tool.NET В .NET 9 и новее метрики публикуются через System.Runtime (dotnet.gc.pause.time и др.), в .NET 8 и ниже через старые EventCounter (% Time in GC since last GC и др.)
runtime packageGo GODEBUG=gctrace=1: по строке на каждый GC, время по wall clock для каждой фазы, размер кучи в начале и в конце GC и целевой размер кучи
ID mem-script-gc · Основной ответственный Команда разработки · Разработка сервера
Если на сервере, пусть даже написанном на C++, квесты, AI и умения выполняются скриптами (например, на Lua), то на время работы GC скриптового движка эта зона останавливается.
Почему В каждой зоне скриптовый движок выполняет квесты, AI и события и создаёт массу временных объектов → Следствие Когда GC скриптового движка собирает много за один раз, тик этой зоны останавливается → На экране Короткие периодические подвисания только в определённой зоне или во время определённого события
Основной ответственный Команда разработки · Разработка сервера
Команда разработки: задачи
Включить инкрементальный или поколенческий режим GC, выполнять сборку понемногу каждый тик, сократить временные объекты в скриптах.
Цифры для ориентира
Когда куча скриптов вырастает до сотен MB, сборка за один проход (с выключенной инкрементальной сборкой или полная сборка в поколенческом режиме) может занимать от десятков до сотен ms.
На графике
Всплески с постоянным периодом · время тика по зонам, память скриптового движка
Где смотреть
Каждый тик записывать время тика по зонам и потребление памяти скриптовым движком этой зоны (в Lua collectgarbage("count")) и накладывать их на один график
Подтверждает
Резкие падения памяти скриптов (сборка за один проход) совпадают со всплесками тика в этой зоне, остальные зоны в порядке
Опровергает
Если тик скачет без изменений памяти скриптов, дело в нагрузке этой зоны или в блокировках. Если скачут сразу все зоны сервера, это GC сервера (mem-gc) или своп (mem-swap)
Чем проверить
Нужны логи и метрики игрового сервера или клиента
Источников: 1
Lua 5.4 Reference ManualLua.org Инкрементальный режим разбивает сборку на мелкие шаги и вставляет их между участками выполнения программы (если шаг сделать большим, получится полная остановка), major-сборка в поколенческом режиме обходит все объекты с полной остановкой, collectgarbage("count") возвращает общий объём памяти, занятой Lua (в KB)
ID mem-alloc · Основной ответственный Команда разработки · Разработка сервера
Если во время события создаётся масса временных объектов, GC запускается намного чаще обычного.
Почему Дроп предметов, боевые логи и награды события резко увеличивают число временных объектов → Следствие GC запускается в несколько раз чаще, объекты, которые не успели стать мусором, переходят в область Old, и Full GC тоже наступает раньше → На экране Короткие периодические подвисания только во время событий
Основной ответственный Команда разработки · Разработка сервера
Команда разработки: задачи
Завести пулы объектов и переиспользуемые буферы, профилировать аллокации.
На графике
Растёт вслед за онлайном и нагрузкой · число сборок GC, скорость аллокаций
Где смотреть
Считать число сборок GC в минуту по GC-логу (Java -Xlog:gc, Go GODEBUG=gctrace=1), для .NET смотреть объём аллокаций и число сборок в dotnet-counters (с .NET 9 dotnet.gc.heap.total_allocated и dotnet.gc.collections, в 8 и ниже Allocation Rate и Gen 0 GC Count). Накладывать на онлайн и время событий
Подтверждает
С началом события скорость аллокаций и число сборок растут быстрее онлайна, короткие паузы учащаются. После события всё возвращается к прежнему уровню
Опровергает
Если число сборок прежнее, а каждая пауза стала длиннее, вырос объём живых данных (mem-gc-thrash, mem-leak)
Чем проверить
Инструменты инфраструктуры (игровой код не нужен)
Источников: 3
Garbage Collector ImplementationOracle Когда заполняется область Young, выполняется minor GC, часть выживших объектов переносится в область Old, а когда заполняется Old, собирается вся куча (намного дольше, чем minor). -Xlog:gc пишет по строке на каждый GC
dotnet-counters diagnostic tool.NET В .NET 9 и новее это dotnet.gc.heap.total_allocated и dotnet.gc.collections, в .NET 8 и ниже Allocation Rate и Gen 0 GC Count
ID mem-leak · Основной ответственный Команда разработки · Разработка сервера · Совместно Команда инфраструктуры · Серверная инфраструктура
Неосвобождённая память понемногу накапливается, и через несколько дней это заканчивается трешингом GC, свопом или принудительным завершением процесса.
Почему Данные персонажей, вышедших из игры, и обработчики событий не освобождаются → Следствие Свободной памяти становится всё меньше в течение нескольких дней → На экране Сразу после техработ всё в порядке, с каждым днём лагает сильнее, в итоге сервер падает
Основной ответственный Команда разработки · Разработка сервера · Совместно Команда инфраструктуры · Серверная инфраструктура
Команда разработки: задачи
Анализировать дампы кучи, проводить длительные нагрузочные тесты.
Команда инфраструктуры: задачи
Отслеживать тренд потребления памяти по процессам, настроить алерты.
На графике
Плавный рост · память процесса (RSS), куча сразу после GC
Где смотреть
Смотреть память процесса игрового сервера (RSS в pidstat -r) на отрезке в несколько дней, а для сервера с GC смотреть, сколько кучи остаётся сразу после GC. В Java это значение после GC (строки -Xlog:gc показывают занятый объём до и после GC), в .NET размер кучи после GC в dotnet-counters (с .NET 9 dotnet.gc.last_collection.heap.size, в 8 и ниже GC Heap Size)
Подтверждает
Объём кучи сразу после GC (нижняя линия) после перезапуска растёт день ото дня и не опускается даже ночью при низком онлайне
Опровергает
Если нижняя линия кучи ровная, а растёт только RSS, дело во фрагментации (mem-fragment) или в нативной памяти. Если память растёт и падает вслед за онлайном, это нормальное потребление
Чем проверить
Инструменты инфраструктуры (игровой код не нужен)
Подробнее
Если сервер каждую неделю перезапускается на плановых техработах, утечка маскируется и долго остаётся незамеченной. Часто она внезапно проявляется, когда техработы один раз переносят или когда онлайн вырастает из-за события.
Источников: 5
Troubleshoot Memory LeaksOracle Если программа работает всё медленнее, стоит подозревать утечку, в итоге память кончается и процесс аварийно завершается. Главный материал для анализа утечки: дамп кучи
Debug a memory leak in .NET.NET Даже при наличии GC постоянные ссылки на ненужные объекты дают утечку, падение производительности и OutOfMemoryException. Проверка тренда памяти и анализ дампов
ID mem-gc-thrash · Основной ответственный Команда разработки · Разработка сервера · Совместно Команда инфраструктуры · Серверная инфраструктура
Когда живые данные приближаются к пределу кучи, GC почти нечего освобождать, и сборки идут одна за другой без перерыва.
Почему Из-за роста онлайна на событии или утечки живые данные заполняют кучу почти до предела → Следствие GC освобождает совсем немного, и сразу снова запускается Full GC, большую часть CPU занимает GC → На экране Весь сервер несколько минут то уходит в слоумо, то ловит фризы, а затем падает из-за нехватки памяти
Вечерний пик, При наплыве игроков, Чем дольше без перезапуска
Ответственные
Основной ответственный Команда разработки · Разработка сервера · Совместно Команда инфраструктуры · Серверная инфраструктура
Команда разработки: задачи
Задавать размер кучи с запасом относительно живых данных в пик (обычно как минимум в 2 раза больше), сокращать долгоживущие данные и утечки.
Команда инфраструктуры: задачи
Настроить алерт на долю времени GC, перезапускать сервер сразу, не дожидаясь, что он справится сам, брать инстансы с запасом памяти, чтобы можно было увеличить кучу.
Цифры для ориентира
Если GC занимает больше 10% времени работы, это обычно считают тревожным сигналом. Некоторые сборщики в Java выдают ошибку нехватки памяти, если тратят на GC 98% времени и почти ничего не освобождают.
На графике
Упор в лимит (плато) · куча сразу после GC, доля времени GC
Где смотреть
Смотреть, насколько куча после GC близка к максимальной и какую долю времени занимает GC. Для Java смотреть «после GC(размер кучи)» в строках -Xlog:gc и частоту строк Pause Full, для .NET dotnet-counters (в .NET 8 и ниже % Time in GC since last GC, с .NET 9 прирост dotnet.gc.pause.time), для Go интервалы между строками GODEBUG=gctrace=1
Подтверждает
Даже сразу после GC куча остаётся почти полной, Full GC идут один за другим, доля времени GC сильно выше обычной (как правило, больше 10%). Всё это время тик замедляется на всём сервере
Опровергает
Если после GC в куче есть запас, а паузы всё равно длинные, дело в выборе и настройке сборщика (mem-gc)
Чем проверить
Инструменты инфраструктуры (игровой код не нужен)
Источников: 5
The Parallel CollectorOracle Parallel GC выдаёт OutOfMemoryError, если тратит на GC больше 98% всего времени и освобождает меньше 2% кучи
Garbage-First Garbage Collector TuningOracle По умолчанию (GCTimeRatio=12) G1 подбирает размер кучи так, чтобы GC занимал не больше примерно 8% времени. Full GC из-за слишком заполненной кучи ищут в логе по строкам Pause Full (G1 Compaction Pause)
A Guide to the Go Garbage CollectorGo При GOGC=100 по умолчанию целевой размер кучи примерно в 2 раза больше живой кучи. Если упереться в лимит памяти, GC работает без остановки (трешинг). GODEBUG=gctrace=1 выводит трассировку GC
Garbage Collector ImplementationOracle Строка -Xlog:gc содержит тип GC (Pause Young, Pause Full), «занято до GC->занято после GC(размер кучи)» и длительность паузы
ID mem-swap · Основной ответственный Команда инфраструктуры · Серверная инфраструктура · Совместно Команда разработки · Разработка сервера
Когда памяти не хватает и ОС выгружает её часть на диск, при каждом обращении к этой памяти приходится ждать диск, который медленнее больше чем в 1 000 раз.
Почему Занятая память превышает физическую RAM → Следствие ОС выгружает часть памяти на диск и читает её обратно, когда она нужна → На экране Время тика вырастает до сотен ms, у всех игроков сервера слоумо и фризы
Основной ответственный Команда инфраструктуры · Серверная инфраструктура · Совместно Команда разработки · Разработка сервера
Команда разработки: задачи
Ограничить потребление памяти процессом (размер кучи и т. п.), проверять на утечки.
Команда инфраструктуры: задачи
Настроить игровые серверы так, чтобы они не использовали своп, реагировать по алертам на память. Без свопа процесс принудительно завершается (OOM) в тот же момент, когда памяти не хватает, поэтому RAM нужно брать с запасом сверх пикового потребления.
Цифры для ориентира
Чтение из RAM занимает около 100 ns, чтение выгруженной памяти обратно с SSD около 100 µs (в 1 000 раз дольше), с облачного диска по ту сторону сети около 1 ms (в 10 000 раз), с HDD 10 ms (в 100 000 раз).
На графике
Плавный рост · занятый своп, swap-in и swap-out
Где смотреть
Накладывать на время тика столбцы si и so в vmstat 1 (сколько в секунду прочитано из свопа и выгружено в него), some и full в /proc/pressure/memory (доля времени, проведённого в ожидании памяти) и majflt/s в pidstat -r для процесса игрового сервера (ошибки страниц, при которых пришлось читать с диска)
Подтверждает
В моменты лагов si больше 0, вместе растут majflt/s игрового сервера и значение full в memory
Опровергает
Если si и so равны 0 и PSI по памяти около 0, своп ни при чём. Если свопа нет, а majflt/s и PSI растут, память кончилась и ОС перечитывает страницы кода, поэтому сначала нужно добавить или освободить память
Чем проверить
Инструменты инфраструктуры (игровой код не нужен)
Подробнее
Сервер с GC при сборке читает кучу по всему объёму, поэтому, даже если в своп ушла только часть кучи, один цикл GC может растянуться до нескольких секунд или даже десятков секунд. Без свопа стадии замедления нет и процесс сразу принудительно завершается (OOM), поэтому сначала нужно обеспечить запас памяти. Даже без свопа, когда память почти кончилась, ОС выгружает из памяти страницы кода исполняемых файлов и читает их заново, и перед принудительным завершением весь сервер может какое-то время сильно тормозить.
Documentation for /proc/sys/vm/Linux kernel swappiness: относительная стоимость свопа и освобождения файловых страниц, своп дорог, потому что это случайный ввод-вывод
Concepts overviewLinux kernel Ядро освобождает страницы страничного кэша, у которых есть копия на диске, и страницы, которые можно выгрузить в своп, а если памяти всё равно не хватает, OOM killer завершает процесс
Solidigm™ D7-P5520 and D7-P5620 Product BriefSolidigm Задержка серверного NVMe SSD на уровне 99,99% (four-nines latency) 130 µs: основание для оценки, что одно чтение с SSD занимает около 100 µs
vmstat(8) — Linux manual pageprocps-ng si: память, прочитанная из свопа за секунду, so: память, выгруженная в своп за секунду
PSI - Pressure Stall InformationLinux kernel some в /proc/pressure/memory (доля времени, когда стояла часть задач) и full (доля времени, когда стояли все задачи одновременно)
ID mem-cache-miss · Основной ответственный Команда разработки · Разработка сервера
Если данные разбросаны по памяти, CPU каждый раз ждёт медленную RAM.
Почему Объекты разбросаны по памяти и связаны указателями, обращения к ним идут вразнобой → Следствие Данных нет в кэше CPU, и их каждый раз приходится читать из RAM (примерно в 100 раз медленнее) → На экране Та же работа обходится тику в несколько раз дороже, в тяжёлых случаях слоумо
Основной ответственный Команда разработки · Разработка сервера
Команда разработки: задачи
Размещать данные, которые часто используются вместе, подряд в памяти (data-oriented design).
На графике
Высоко с самого начала · время тика, загрузка CPU
Где смотреть
Запустить perf stat -d -p PID на процессе игрового сервера, измерить число инструкций за такт (insn per cycle) и промахи кэшей L1 и LLC, смотреть вместе со временем тика и загрузкой CPU
Подтверждает
CPU постоянно загружен, но insn per cycle низкий и промахов LLC много. Если в сборке с изменённым размещением данных время тика при том же онлайне заметно падает, причина подтверждена
Опровергает
Если загрузка CPU низкая, а тик медленный, дело в ожидании вне CPU: блокировки, ожидание ввода-вывода
perf-stat(1) — Linux manual pageperf С -p считает аппаратные события работающего процесса и показывает insn per cycle, -d добавляет события кэша данных L1 и LLC
ID mem-fragment · Основной ответственный Команда разработки · Разработка сервера
Когда из-за постоянных выделений и освобождений свободное место дробится на мелкие куски, процесс занимает намного больше памяти, чем реально использует.
Почему Много потоков долго выделяют и освобождают блоки памяти разного размера → Следствие Свободное место раздроблено, вернуть его ОС нельзя, и потребление растёт, как при утечке → На экране Чем дольше работает сервер, тем сильнее он тормозит из-за свопа и нехватки памяти, а затем принудительно завершается
Основной ответственный Команда разработки · Разработка сервера
Команда разработки: задачи
Завести пулы памяти по размерам блоков, перейти на аллокатор, устойчивый к фрагментации (jemalloc, mimalloc и др.).
На графике
Плавный рост · память процесса (RSS)
Где смотреть
Запустить два сервера одной сборки, на одном уменьшить число арен glibc переменной окружения MALLOC_ARENA_MAX или заменить аллокатор (например, на jemalloc) и несколько дней сравнивать RSS в pidstat -r
Подтверждает
При сопоставимом онлайне и числе объектов рост RSS останавливается или заметно замедляется только на изменённом сервере
Опровергает
Если и с другим аллокатором память растёт так же, это память, которую не освобождают (mem-leak)
Чем проверить
Инструменты инфраструктуры (игровой код не нужен)
Подробнее
Внешне это выглядит как утечка, но анализ кучи места утечки не покажет. Со стандартным аллокатором Linux (glibc) на серверах с большим числом потоков фрагментация особенно сильна, и одна только замена аллокатора иногда заметно снижает потребление.
Источников: 3
mallopt(3) — Linux manual pageLinux man-pages Чтобы потоки меньше конкурировали, malloc в glibc создаёт арены, число которых может доходить до кратного числу CPU, и чем больше арен, тем больше потребление памяти (ограничивается M_ARENA_MAX, задаётся и переменной окружения MALLOC_ARENA_MAX)
jemalloc memory allocatorjemalloc Универсальная реализация malloc, рассчитанная на защиту от фрагментации и масштабирование при параллельной работе
ID mem-numa · Основной ответственный Команда инфраструктуры · Серверная инфраструктура
На сервере с двумя процессорами обращение к памяти, подключённой к другому процессору, идёт медленнее.
Почему Потоки и их память оказываются на разных процессорных сокетах → Следствие Обращения к памяти замедляются (в 1,5–2 раза в зависимости от оборудования) → На экране На одинаковом железе процессы работают с разной скоростью
Основной ответственный Команда инфраструктуры · Серверная инфраструктура
Команда инфраструктуры: задачи
Привязать процесс и его память к одному сокету (numactl), а на двухсокетном сервере распределить процессы игрового сервера по сокетам.
На графике
Высоко только у некоторых · время тика по процессам, память по узлам NUMA
Где смотреть
Смотреть через numastat -p PID, на каком узле NUMA лежит память процесса игрового сервера, растут ли numa_miss и other_node в numastat, и сравнивать с узлом CPU, на котором работает процесс
Подтверждает
Только у медленных процессов большая часть памяти лежит на другом узле, чем их CPU, а после перезапуска с привязкой CPU и памяти к одному узлу через numactl разница исчезает
Опровергает
Если размещение по узлам такое же, как у быстрых процессов, а процесс всё равно медленный, причина другая: шумный сосед, троттлинг CPU, нагрузка на сам процесс
Чем проверить
Инструменты инфраструктуры (игровой код не нужен)
Источников: 3
What is NUMA?Linux kernel Память своей ячейки быстрее и имеет большую пропускную способность, обращение к памяти другой (удалённой) ячейки медленнее
numactl(8) — Linux manual pagenumactl --cpunodebind и --membind привязывают CPU и память процесса к определённому узлу NUMA
numastat(8) — Linux manual pagenumactl Счётчики numa_miss (память выделена не на том узле, где её запрашивали) и other_node (на этом узле выделил память процесс, работающий на другом узле), с -p показывает память процесса по узлам
ID dk-sync-log · Основной ответственный Команда разработки · Разработка сервера · Совместно Команда инфраструктуры · Серверная инфраструктура
Если игровой поток на каждой строке лога ждёт, пока диск завершит запись, то при занятом диске останавливается и игра.
Почему Боевые логи и логи обменов пишутся в файл прямо из игрового потока → Следствие Если требуется гарантированная запись (fsync) или буфер записи ОС (страничный кэш) заполнен до предела, при занятом диске одна запись длится десятки ms → На экране Подвисания в боях, где пишется много логов
Основной ответственный Команда разработки · Разработка сервера · Совместно Команда инфраструктуры · Серверная инфраструктура
Команда разработки: задачи
Перейти на асинхронное логирование (буфер в памяти и отдельный поток), сократить объём логов, не вызывать fsync в игровом потоке.
Команда инфраструктуры: задачи
Запускать ротацию и сжатие логов с пониженным приоритетом ввода-вывода, держать логи на отдельном от данных диске, отслеживать задержку записи на диск.
На графике
Случайные всплески · время тика сервера, задержка записи на диск
Где смотреть
Накладывать w_await и aqu-sz из iostat -x 1 на время тика и через perf trace -p PID --duration 10 искать в игровом сервере вызовы write и fsync дольше 10 ms и потоки, которые их сделали
Подтверждает
В моменты всплесков тика вызовы write и fsync в игровом потоке длятся десятки ms, и в тот же момент подскакивает задержка записи на диск. Часто это совпадает со временем ротации или сжатия логов
Опровергает
Если в игровом потоке нет долгих системных вызовов, а тик скачет, причина другая: GC, блокировки, превышение бюджета тика. Если долгие вызовы только в отдельном потоке логирования, на игру это не влияет
Чем проверить
Инструменты инфраструктуры (игровой код не нужен)
Подробнее
Обычно ОС сначала принимает запись в память (страничный кэш) и сбрасывает её на диск позже, поэтому строка лога, как правило, записывается мгновенно. Остановки бывают, когда fsync требует гарантированной записи, когда накопившиеся записи превышают лимит и ОС блокирует вызов записи, а также во время ротации или сжатия файлов логов. Поэтому обычно всё в порядке, а всплески появляются только в моменты, когда диск занят.
Источников: 5
fsync(2) — Linux manual pageLinux man-pages fsync сбрасывает изменённые данные на диск (включая кэш диска) и блокирует вызов, пока устройство не сообщит о завершении
Documentation for /proc/sys/vm/Linux kernel Когда накопленные несброшенные данные (dirty) достигают dirty_ratio, процесс, который пишет, сам берёт на себя запись на диск
ionice(1) — Linux manual pageutil-linux Задача с приоритетом ввода-вывода idle получает время диска, только когда диском не пользуются другие программы
iostat(1) — Linux manual pagesysstat -x: w_await (среднее время обработки запроса на запись, включая ожидание в очереди), aqu-sz (средняя длина очереди, прежнее название avgqu-sz)
perf-trace(1) — Linux manual pageperf -p трассирует системные вызовы работающего процесса, --duration показывает только вызовы дольше заданного числа ms
ID dk-fsync · Основной ответственный Команда разработки · Разработка сервера · Совместно Команда инфраструктуры · Серверная инфраструктура, Команда инфраструктуры · Инфраструктура БД
Запрос записать данные на диск «гарантированно» занимает от 0,1 ms до десятков ms в зависимости от диска, а когда таких запросов много, очередь растёт.
Почему Периодические сохранения и массовый выход из игры дают пачку запросов на гарантированную запись → Следствие Очередь к диску растёт → На экране Лаги в моменты сохранения, задержки при выходе из игры и смене канала
Основной ответственный Команда разработки · Разработка сервера · Совместно Команда инфраструктуры · Серверная инфраструктура, Команда инфраструктуры · Инфраструктура БД
Команда разработки: задачи
Группировать сохранения (несколько сохранений на один fsync), разносить сохранения по времени.
Команда инфраструктуры: задачи
Серверы и ОС: серверные SSD с защитой от потери питания, мониторинг длины очереди к диску и задержки fsync. Серверы БД: если сохранения идут в БД, диск журнала БД тоже на таком SSD, мониторинг задержки коммитов.
Цифры для ориентира
Время одного вызова зависит от оборудования, но примерно так: серверный SSD (с защитой от потери питания) 0,1 ms, обычный SSD от 1 до нескольких ms, облачный диск 1–2 ms, HDD 10 ms и больше. Если один поток ждёт вызовы по одному, HDD не успевает выполнить и 100 вызовов в секунду.
На графике
Всплески с постоянным периодом · длина очереди к диску, задержка сброса (flush) и записи
Где смотреть
Накладывать на время периодических сохранений и выходов из игры f/s и f_await из iostat -x 1 (число сбросов, обработанных диском, и их длительность), а также w/s, aqu-sz и w_await. Старые версии sysstat показывают aqu-sz как avgqu-sz. Для облачного диска смотреть VolumeQueueLength и VolumeAvgWriteLatency в EBS
Подтверждает
В моменты сохранений и массового выхода число сбросов и длина очереди растут вместе, w_await и f_await в несколько раз выше обычного. В это время задерживаются сохранения и смена канала
Опровергает
Если очередь растёт в моменты, не связанные с сохранениями и выходами, это бэкап или сжатие (dk-backup) либо лимит IOPS (dk-iops). Если число сбросов прежнее, а всё замедлилось, вероятнее исчерпание burst-кредитов (dk-burst)
Чем проверить
Инструменты инфраструктуры (игровой код не нужен)
Источников: 6
fsync(2) — Linux manual pageLinux man-pages fsync сбрасывает в том числе кэш диска и блокирует вызов, пока устройство не сообщит о завершении
Reliability (PostgreSQL Documentation)PostgreSQL У обычных SATA-дисков и многих SSD есть кэш записи, который теряется при отключении питания, поэтому для гарантированной записи нужен кэш с батареей или защитой от потери питания
Amazon EBS General Purpose SSD volumesAWS Задержка стандартного облачного диска (gp3): единицы ms, у io2 Block Express в среднем меньше 500 µs на операцию размером 16 KiB
iostat(1) — Linux manual pagesysstat -x: f/s и f_await (число запросов на сброс, обработанных диском, и их среднее время), w/s, w_await, aqu-sz (прежнее название avgqu-sz)
Amazon CloudWatch metrics for Amazon EBSAWS VolumeQueueLength (число запросов, ожидающих завершения), VolumeAvgWriteLatency (средняя задержка записи за 1 минуту, инстансы Nitro)
ID dk-burst · Основной ответственный Команда инфраструктуры · Серверная инфраструктура · Совместно Команда инфраструктуры · Инфраструктура БД
У некоторых облачных дисков и небольших конфигураций серверов есть burst-кредиты, которые позволяют какое-то время работать быстрее базовой производительности. Если высокая нагрузка держится долго и кредиты кончаются, скорость резко падает.
Почему Диск долго работает выше базовой производительности → Следствие Burst-кредиты кончаются, производительность резко падает до базовой → На экране Каждый вечер через несколько часов нагрузки начинаются лаги
Основной ответственный Команда инфраструктуры · Серверная инфраструктура · Совместно Команда инфраструктуры · Инфраструктура БД
Команда инфраструктуры: задачи
Серверы и ОС: диски с гарантированной производительностью (gp3, тип с заданным IOPS), алерт на остаток кредитов, проверка лимита burst для дисковой пропускной способности инстанса и CPU-кредитов. Серверы БД: перевести диски БД, включая управляемые БД, на тип с гарантированной производительностью, алерт на остаток кредитов.
Цифры для ориентира
Диск AWS gp2 на 100 GB обычно даёт 300 IOPS, в режиме burst 3 000 IOPS, и при полном запасе кредитов держит burst около 30 минут. gp3 всегда даёт 3 000 IOPS без всяких кредитов. Небольшие диски Azure Premium SSD тоже работают в режиме burst за счёт кредитов до 30 минут.
На графике
Упор в лимит (плато) · IOPS, остаток burst-кредитов
Где смотреть
Смотреть в CloudWatch EBS BurstBalance (gp2, st1, sc1), EBSIOBalance% и EBSByteBalance% инстанса (у части инстансов с burst), CPUCreditBalance у burst-инстансов. В Azure смотреть метрики использования burst-кредитов, например Data Disk Used Burst IO Credits Percentage
Подтверждает
С момента, когда остаток падает почти до 0, IOPS (VolumeReadOps, VolumeWriteOps) выходит на плато на уровне базовой производительности, а VolumeQueueLength и лаги растут вместе. Начинается после нескольких часов пика
Опровергает
Если запас всех кредитов большой, а IOPS стоит на плато, это фиксированный лимит тома или инстанса (dk-iops)
Чем проверить
Инструменты инфраструктуры (игровой код не нужен)
Подробнее
Даже если с диском всё в порядке, у небольших виртуальных серверов есть лимит burst на саму дисковую пропускную способность инстанса (например, не меньше 30 минут в сутки), и картина получается такая же. Дешёвые серверы с CPU-кредитами, когда кредиты кончаются, тоже замедляются до базовой производительности.
Источников: 7
Amazon EBS General Purpose SSD volumesAWS Базовая производительность gp2: 3 IOPS на GiB (минимум 100), burst до 3 000 IOPS за счёт I/O-кредитов, 5 400 000 кредитов хватает минимум на 30 минут. gp3 всегда даёт 3 000 IOPS без burst
Managed disk burstingMicrosoft Azure Premium SSD P20 и меньше используют burst на основе кредитов, при полном запасе кредитов максимальная скорость burst держится 30 минут
Amazon EBS-optimized instance typesAWS Некоторые инстансы держат максимальную производительность EBS только 30 минут раз в 24 часа, затем возвращаются к базовой
Amazon CloudWatch metrics for Amazon EBSAWS BurstBalance: остаток (%) I/O-кредитов gp2 и кредитов пропускной способности st1 и sc1, VolumeReadOps, VolumeWriteOps, VolumeQueueLength
CloudWatch metrics that are available for your instancesAWS EBSIOBalance% и EBSByteBalance%: остаток кредитов EBS у некоторых инстансов с burst на 30 минут раз в 24 часа, CPUCreditBalance: остаток CPU-кредитов burst-инстанса
Disk metricsMicrosoft Azure Data Disk Used Burst IO Credits Percentage и другие метрики использования burst-кредитов дисков и ВМ (интервал 5 минут)
ID dk-iops · Основной ответственный Команда инфраструктуры · Серверная инфраструктура · Совместно Команда разработки · Разработка сервера, Команда инфраструктуры · Инфраструктура БД
Если запросов больше, чем диск может обработать за секунду, очередь растёт и задержка резко увеличивается.
Почему Запросы на чтение и запись приближаются к пределу производительности диска → Следствие Очередь растёт (обычно резко при утилизации от 90%) → На экране Задержки сохранения и загрузки, а при синхронных вызовах фризы
Основной ответственный Команда инфраструктуры · Серверная инфраструктура · Совместно Команда разработки · Разработка сервера, Команда инфраструктуры · Инфраструктура БД
Команда разработки: задачи
Объединять запросы, кэшировать часто читаемые данные, делать ввод-вывод асинхронным, чтобы игровой поток не ждал диск.
Команда инфраструктуры: задачи
Серверы и ОС: более быстрые диски, проверка лимитов дисковой пропускной способности и IOPS для типа инстанса, алерты на утилизацию и очередь диска, копирование больших файлов в часы низкой нагрузки. Серверы БД: алерты на утилизацию IOPS и пропускной способности дисков БД, проверка дисковых лимитов конфигурации инстанса БД.
Цифры для ориентира
HDD около 150 IOPS, SATA SSD десятки тысяч, NVMe сотни тысяч. Стандартный облачный диск (AWS gp3) даёт 3 000 IOPS и 125 MiB/s, и если копирование большого файла исчерпывает лимит на объём передачи в секунду, который не зависит от IOPS, застревают даже мелкие записи.
На графике
Упор в лимит (плато) · IOPS, длина очереди к диску
Где смотреть
Смотреть r/s, w/s, rkB/s, wkB/s, aqu-sz, r_await и w_await в iostat -x 1. В облаке смотреть VolumeReadOps, VolumeWriteOps, VolumeQueueLength в EBS и признаки превышения лимита VolumeIOPSExceededCheck и VolumeThroughputExceededCheck, а со стороны инстанса InstanceEBSIOPSExceededCheck и InstanceEBSThroughputExceededCheck
Подтверждает
Число запросов или объём передачи в секунду выходит на плато на значении лимита, а aqu-sz и await вместе взлетают. В облаке метрики проверки превышения равны 1
Опровергает
Даже при %util 100% запас может оставаться, если await низкий. На SSD и RAID, которые обрабатывают запросы параллельно, %util не означает упор в лимит. Если лимит не достигнут, а высок только await, это собственная задержка диска (dk-hdd) или fsync (dk-fsync)
Чем проверить
Инструменты инфраструктуры (игровой код не нужен)
Подробнее
В облаке помимо лимитов диска есть лимиты дисковой пропускной способности и IOPS для каждой конфигурации сервера (типа инстанса). Даже если подключить дорогой диск, на маленьком сервере всё упрётся в лимит инстанса.
Источников: 8
Exos X18 Data SheetSeagate Случайное чтение блоками 4K на серверном HDD 7 200 rpm: 170 IOPS (QD16)
D3-S4520 SSDSolidigm Серверный SATA SSD: случайное чтение и запись блоками 4 KB до 92K/48K IOPS
Amazon EBS General Purpose SSD volumesAWS Базовая производительность gp3: 3 000 IOPS и 125 MiB/s, это два отдельных лимита, каждый можно увеличить независимо
Amazon EBS-optimized instance typesAWS Для каждого типа инстанса есть свои базовые и максимальные лимиты EBS по пропускной способности, объёму передачи и IOPS
iostat(1) — Linux manual pagesysstat -x: r/s и w/s, rkB/s и wkB/s, aqu-sz (прежнее название avgqu-sz), r_await и w_await, %util. На RAID и современных SSD, которые обрабатывают запросы параллельно, %util не показывает предел производительности
Amazon CloudWatch metrics for Amazon EBSAWS VolumeIOPSExceededCheck и VolumeThroughputExceededCheck: 1, если была попытка превысить лимит IOPS или объёма передачи тома (инстансы Nitro), VolumeQueueLength
ID dk-full · Основной ответственный Команда инфраструктуры · Серверная инфраструктура · Совместно Команда инфраструктуры · Инфраструктура БД, Команда разработки · Разработка сервера
Когда логи и дампы заполняют диск, запись завершается ошибкой, и если к этому не подготовиться, сервер падает.
Почему Логи, дампы и временные файлы заполняют диск на 100% → Следствие Запись не удаётся. Без обработки ошибок сервер падает, с обработкой не проходят сохранения → На экране Дисконнект, роллбэк прогресса
Основной ответственный Команда инфраструктуры · Серверная инфраструктура · Совместно Команда инфраструктуры · Инфраструктура БД, Команда разработки · Разработка сервера
Команда разработки: задачи
Обрабатывать ошибки записи: повторять сохранение и поднимать алерт вместо падения сервера, сократить ненужные логи и дампы.
Команда инфраструктуры: задачи
Серверы и ОС: ротация логов, алерты на заполнение, раздельные диски для логов и данных. Серверы БД: следить, чтобы журнал транзакций БД (WAL, binlog) не копился из-за остановки репликации или пропущенного бэкапа журнала.
На графике
Плавный рост · заполненность диска
Где смотреть
Смотреть заполненность в df -h и заполненность inode в df -i, искать ошибки ENOSPC в логах сервера и БД. Для БД смотреть слоты, у которых active равно false, в pg_replication_slots (PostgreSQL), число и размер файлов в SHOW BINARY LOGS (MySQL), log_reuse_wait_desc в sys.databases (SQL Server), FreeStorageSpace (RDS)
Подтверждает
Заполненность несколько дней стабильно растёт, момент достижения 100% совпадает с падением сервера или сбоями сохранения, в логах есть ENOSPC
Опровергает
Если места достаточно, а запись не проходит, причина другая: права доступа, лимит размера файла и т. п.
Чем проверить
Инструменты инфраструктуры (игровой код не нужен)
Подробнее
Журнал транзакций БД (WAL, binlog и др.) не удаляется и продолжает расти, если реплика остановилась или бэкап журнала не выполнился. Когда этот диск заполняется, в БД останавливаются все записи, и сохранения и обмены разом перестают проходить.
Troubleshoot a full transaction log (SQL Server Error 9002)Microsoft SQL Server Когда журнал заполнен, БД доступна только для чтения, изменять данные нельзя. Частые причины, которые мешают очистке журнала: пропущенный бэкап журнала, отставание репликации, длинные транзакции. Что именно мешает, показывает log_reuse_wait_desc в sys.databases
df(1) — Linux manual pagecoreutils Занятое место по файловым системам, -i показывает использование inode вместо блоков
ID dk-backup · Основной ответственный Команда инфраструктуры · Серверная инфраструктура · Совместно Команда инфраструктуры · Инфраструктура БД
Когда ночной бэкап, сжатие логов или проверка безопасности занимают диск целиком, чтение и запись игрового сервера застревают.
Почему Запускается плановый бэкап или сжатие → Следствие Задание забирает большую часть пропускной способности диска и IOPS → На экране Лаги каждый день в одно и то же время
Основной ответственный Команда инфраструктуры · Серверная инфраструктура · Совместно Команда инфраструктуры · Инфраструктура БД
Команда инфраструктуры: задачи
Серверы и ОС: понизить приоритет ввода-вывода для бэкапа, сжатия и сканирования, разнести их по времени. Серверы БД: делать бэкап с реплики.
На графике
Всплески с постоянным периодом · утилизация диска, время ожидания диска
Где смотреть
Через sar -d наложить по дням %util, await и aqu-sz из записей за последние несколько дней (суточные файлы в /var/log/sa, sadc должен собирать и данные дисков с ключом -S DISK), в эти же моменты через pidstat -d 1 найти процессы с наибольшими kB_rd/s и kB_wr/s и сверить с расписанием cron и таймеров systemd
Подтверждает
Каждый день в одно и то же время подскакивают await и %util, и в это время большую часть чтения и записи на диск занимают процессы бэкапа, сжатия или сканирования
Опровергает
Если время всплесков каждый день разное, плановое задание маловероятно. Если в эти моменты основную часть ввода-вывода даёт сам игровой сервер, дело в сохранениях и логах (dk-fsync, dk-sync-log)
Чем проверить
Инструменты инфраструктуры (игровой код не нужен)
Источников: 4
ionice(1) — Linux manual pageutil-linux Задача класса idle получает время диска, только когда диском не пользуются другие программы
sar(1) — Linux manual pagesysstat -d: await, aqu-sz и %util по устройствам из суточных файлов (по умолчанию /var/log/sa), данные дисков нужно собирать ключом -S DISK у sadc
ID dk-lazy-load · Основной ответственный Команда разработки · Разработка сервера · Совместно Команда инфраструктуры · Серверная инфраструктура
Если сервер читает данные данжа или карты с диска в момент первого запроса, на этот тик останавливаются все.
Почему Кто-то впервые входит в данж или локацию → Следствие Сервер читает данные с диска в игровом потоке → На экране У всех на этом сервере короткий фриз
Основной ответственный Команда разработки · Разработка сервера · Совместно Команда инфраструктуры · Серверная инфраструктура
Команда разработки: задачи
Загружать данные заранее при старте сервера, загружать асинхронно.
Команда инфраструктуры: задачи
Сервер, только что созданный из снапшота, перед вводом в работу прогревать (один раз прочитать все блоки диска) или использовать быстрое восстановление из снапшота.
На графике
Случайные всплески · время тика сервера, чтение с диска
Где смотреть
Сопоставить моменты остановок с записями о первом входе в данж или локацию в логе игрового сервера и смотреть в эти моменты чтение с диска игровым сервером (kB_rd/s в pidstat -d) и долгие вызовы read и open через perf trace --duration. Если облачный сервер только что поднят, сравнить VolumeAvgReadLatency в EBS со старыми серверами
Подтверждает
Остановка только в момент первого входа, при повторном входе туда же остановки нет. Во время остановки игровой поток ждёт чтения файла
Опровергает
Если такие же остановки бывают и в уже загруженных локациях, причина другая: превышение бюджета тика, GC
Чем проверить
Нужны логи и метрики игрового сервера или клиента
Подробнее
В облаке сервер, только что созданный из снапшота (копии диска), при первом чтении каждого блока забирает его из удалённого хранилища и работает гораздо медленнее обычного. Если первый вход особенно долгий только на серверах, которые только что поднялись при автомасштабировании, стоит заподозрить эту причину.
Источников: 5
Initialize Amazon EBS volumesAWS Том, созданный из снапшота, пока подтягивает блоки из S3, работает с повышенной задержкой и пониженной производительностью. Его заранее инициализируют, прочитав все блоки через dd или fio
Amazon EBS fast snapshot restoreAWS Быстрое восстановление из снапшота сразу выдаёт инициализированный том, и задержки при первом обращении нет
ID dk-coredump · Основной ответственный Команда инфраструктуры · Серверная инфраструктура · Совместно Команда разработки · Разработка сервера
При падении сервер пишет на диск несколько GB памяти, и перезапуск может задерживаться на несколько минут.
Почему Сервер падает и записывает всю память в файл → Следствие Пока пишутся несколько GB, перезапустить сервер нельзя → На экране Сервер падает, у всех дисконнект, после чего ещё долго ошибка входа
Основной ответственный Команда инфраструктуры · Серверная инфраструктура · Совместно Команда разработки · Разработка сервера
Команда разработки: задачи
Рассмотреть мини-дампы, где хранится только нужная часть памяти, исправить причину падения.
Команда инфраструктуры: задачи
Ограничить размер дампа (настройки core dump в ОС), использовать быстрый диск, отделить перезапуск от дампа (сжатие и выгрузку дампа делать отдельно после перезапуска).
На графике
Массовый обрыв соединений · число подключений, время перезапуска сервера
Где смотреть
Сопоставить время падения, размер core-файла (coredumpctl list и info или файл там, куда указывает core_pattern), время окончания записи файла и время, когда сервис снова поднялся, и смотреть в этом интервале wkB/s в iostat -x
Подтверждает
После падения, пока пишется core-файл на несколько GB, запись на диск держится около лимита, и перезапуск начинается только после окончания записи
Опровергает
Если core dump выключен или получился маленьким, а перезапуск всё равно долгий, дело в процессе старта сервера: загрузка карт, холодный кэш БД (db-cold-cache) и т. п.
Чем проверить
Инструменты инфраструктуры (игровой код не нужен)
Источников: 4
core(5) — Linux manual pageLinux man-pages RLIMIT_CORE задаёт предел размера core-файла, coredump_filter выбирает, какие области памяти включать, core dump можно передать по конвейеру в программу и обработать отдельно
Minidump FilesMicrosoft Мини-дамп содержит только полезную часть информации аварийного дампа, поэтому создаётся быстро и занимает мало места
coredumpctl(1) — Linux manual pagesystemd list: список core dump в журнале (TIME: время падения по данным ядра), info: подробности по каждому дампу и записанный на диск размер
ID dk-hdd · Основной ответственный Команда инфраструктуры · Серверная инфраструктура · Совместно Команда инфраструктуры · Инфраструктура БД, Команда разработки · Разработка сервера
У HDD головка должна перемещаться над пластинами (позиционирование, seek), поэтому каждое чтение или запись разбросанных данных занимает почти 10 ms.
Почему HDD на старых серверах или в дешёвых хранилищах → Следствие Около 10 ms на каждое случайное чтение или запись → На экране Сохранение и загрузка в целом идут медленно
Основной ответственный Команда инфраструктуры · Серверная инфраструктура · Совместно Команда инфраструктуры · Инфраструктура БД, Команда разработки · Разработка сервера
Команда разработки: задачи
Проектировать запись так, чтобы она была в основном последовательной.
Команда инфраструктуры: задачи
Серверы и ОС: заменить на SSD (начиная с дисков для сохранений, где больше всего случайного чтения и записи). Серверы БД: в первую очередь перевести на SSD диски БД с наибольшим объёмом случайного чтения и записи.
На графике
Высоко с самого начала · задержка чтения и записи на диск (r_await, w_await)
Где смотреть
Проверить через lsblk -d -o NAME,ROTA, вращающийся ли это диск (HDD), и смотреть r/s, w/s, r_await и w_await в iostat -x 1. Для виртуального сервера тип диска смотреть в характеристиках облака или хранилища
Подтверждает
Диск вращающийся, и при нагрузке всего от десятков до сотни с небольшим запросов в секунду r_await и w_await постоянно держатся на уровне от единиц до десятков ms
Опровергает
Если диск SSD, а задержка высокая, вероятнее насыщение очереди (dk-iops) или исчерпание burst-кредитов (dk-burst)
ID db-no-index · Основной ответственный Команда разработки · Разработка сервера · Совместно Команда инфраструктуры · Инфраструктура БД
Без индекса, чтобы найти строки по условию, приходится читать всю таблицу (полное сканирование).
Почему С деплоем новой функции появляется поиск по условию, для которого нет индекса → Следствие Сканируются все миллионы строк, один запрос занимает от сотен ms до нескольких секунд → На экране Долго загружаются почта и история обменов, соединения заняты, и в очереди стоят даже другие запросы
Основной ответственный Команда разработки · Разработка сервера · Совместно Команда инфраструктуры · Инфраструктура БД
Команда разработки: задачи
Перед деплоем проверять план выполнения новых запросов, добавлять индексы, проверять, что изменяющие запросы (UPDATE, DELETE) тоже используют индекс.
Команда инфраструктуры: задачи
Следить за журналом медленных запросов, находить запросы с полным сканированием и передавать их команде разработки, индексы на работающей БД добавлять онлайн-способом с короткими блокировками.
Цифры для ориентира
С индексом запрос занимает единицы ms, а без индекса замедляется пропорционально объёму данных, на больших таблицах в сотни и даже десятки тысяч раз.
На графике
Ступенька вверх с определённого момента · задержка запросов к БД, число прочитанных строк
Где смотреть
В MySQL смотреть Rows_examined и Rows_sent в slow query log (с включённым log_queries_not_using_indexes туда пишутся и запросы без индекса), SUM_NO_INDEX_USED и SUM_ROWS_EXAMINED в performance_schema events_statements_summary_by_digest и запускать EXPLAIN. В PostgreSQL смотреть seq_scan и seq_tup_read в pg_stat_user_tables и запускать EXPLAIN
Подтверждает
Новый после деплоя запрос читает строк (Rows_examined) в тысячи раз больше, чем возвращает (Rows_sent), EXPLAIN показывает полное сканирование таблицы (в MySQL type ALL, в PostgreSQL Seq Scan). seq_tup_read у большой таблицы резко растёт с момента деплоя
Опровергает
Если индекс используется, а запрос всё равно медленный, это ожидание блокировок (db-hot-row, db-ddl-lock) или смена плана выполнения (db-plan-flip). Полное сканирование маленькой таблицы может быть нормой
Чем проверить
Инструменты инфраструктуры (игровой код не нужен)
Подробнее
Медленнее становится не только чтение. Изменяющий запрос (UPDATE, DELETE) без индекса в некоторых БД блокирует все просканированные строки и может задержать сохранения даже тех игроков, которых этот запрос не касается.
Источников: 8
How MySQL Uses IndexesMySQL Без индекса БД читает всю таблицу с первой строки, и чем больше таблица, тем дороже запрос
Locks Set by Different SQL Statements in InnoDBMySQL Если подходящего индекса нет и таблица сканируется целиком, блокируются все строки, и другие пользователи не могут даже добавлять записи
The Slow Query LogMySQL Запись запросов дольше long_query_time (по умолчанию 10 секунд), отдельно можно записывать и запросы, которые не используют индекс
Statement Summary TablesMySQL events_statements_summary_by_digest: по каждому шаблону запроса SUM_NO_INDEX_USED (сколько раз он выполнялся без индекса) и SUM_ROWS_EXAMINED
EXPLAIN Output FormatMySQL type ALL означает полное сканирование таблицы, обычно его устраняют добавлением индекса
ID db-hot-row · Основной ответственный Команда разработки · Разработка сервера · Совместно Команда инфраструктуры · Инфраструктура БД
Когда все пытаются изменить одну и ту же строку (гильдейский склад, популярный лот на аукционе, общий счётчик сервера), блокировку получает только один запрос за раз.
Почему Из-за события или популярного предмета все изменения приходятся на одну и ту же строку → Следствие Запросы ждут, пока получат блокировку → На экране Сбои обменов, «Повторите попытку позже», таймауты
Основной ответственный Команда разработки · Разработка сервера · Совместно Команда инфраструктуры · Инфраструктура БД
Команда разработки: задачи
Разделить строку на несколько (шардированный счётчик), сделать транзакции короче, накапливать изменения в памяти и применять одним разом.
Команда инфраструктуры: задачи
Мониторить время и число ожиданий блокировок строк, находить строки, за которые идёт борьба, и сообщать о них команде разработки.
Цифры для ориентира
Если один запрос держит блокировку 10 ms, строку можно изменить не больше 100 раз в секунду. Если внутри транзакции есть обращение к другому серверу и обратно, это число падает ещё сильнее.
На графике
Растёт вслед за онлайном и нагрузкой · число и время ожиданий блокировок строк
Где смотреть
В MySQL смотреть прирост Innodb_row_lock_waits и Innodb_row_lock_time и значение Innodb_row_lock_current_waits, а через sys.innodb_lock_waits выяснять, кто кого ждёт. В PostgreSQL смотреть сессии, у которых wait_event_type равен Lock, в pg_stat_activity и запросы, у которых granted равно false, в pg_locks, а если включить log_lock_waits (по умолчанию выключен), долгие ожидания блокировок попадают в лог
Подтверждает
Ожидания блокировок резко растут вслед за событием и онлайном, и большинство ждущих запросов указывает на одну и ту же строку (один ключ) одной таблицы
Опровергает
Если ожидания равномерно распределены по многим таблицам и строкам, дело в насыщении диска или CPU. Если одна сессия долго держит блокировку и не отпускает её, это долго открытая транзакция (db-long-tx)
Чем проверить
Инструменты инфраструктуры (игровой код не нужен)
Источников: 7
InnoDB LockingMySQL Когда транзакция ставит блокировку на строку (запись индекса), другие транзакции не могут изменить эту строку и ждут
How to Minimize and Handle DeadlocksMySQL Рекомендация держать транзакции маленькими и короткими и коммитить сразу после связанных изменений, чтобы уменьшить конфликты
Server Status VariablesMySQL Innodb_row_lock_waits и Innodb_row_lock_time показывают число и время ожиданий блокировок строк, Innodb_row_lock_current_waits показывает, сколько запросов ждут сейчас
ID db-deadlock · Основной ответственный Команда разработки · Разработка сервера · Совместно Команда инфраструктуры · Инфраструктура БД
Если две транзакции (операции БД, которые выполняются как единое целое) ждут строки, заблокированные друг другом, БД принудительно отменяет одну из них.
Почему Обмен A блокирует строки в порядке «предмет → валюта», обмен B в порядке «валюта → предмет» → Следствие БД обнаруживает дедлок и делает роллбэк одной из транзакций → На экране Обмены и крафт иногда срываются, предметы возвращаются назад
Основной ответственный Команда разработки · Разработка сервера · Совместно Команда инфраструктуры · Инфраструктура БД
Команда разработки: задачи
Захватывать блокировки в едином порядке, делать транзакции короче, автоматически повторять при сбое.
Команда инфраструктуры: задачи
Держать обнаружение дедлоков включённым, собирать записи о дедлоках и передавать их команде разработки, на серверах MySQL с отключённым обнаружением уменьшить лимит ожидания блокировки (по умолчанию 50 секунд).
Цифры для ориентира
В MySQL (InnoDB) дедлок обнаруживается почти мгновенно, в PostgreSQL по умолчанию через 1 секунду, в SQL Server максимум примерно через 5 секунд. Всё это время оба запроса стоят. Если на сервере MySQL обнаружение отключено из-за очень большого числа одновременных запросов, ожидание длится до лимита ожидания блокировки (по умолчанию 50 секунд).
На графике
Случайные всплески · число дедлоков, число сбоев обменов
Где смотреть
В MySQL смотреть LATEST DETECTED DEADLOCK в SHOW ENGINE INNODB STATUS (только последний случай), все дедлоки в журнале ошибок при включённом innodb_print_all_deadlocks и lock_deadlocks в INFORMATION_SCHEMA.INNODB_METRICS. В PostgreSQL смотреть deadlocks в pg_stat_database, в SQL Server xml_deadlock_report в сессии system_health, включённой по умолчанию. Коды ошибок на стороне игрового сервера: MySQL 1213, PostgreSQL 40P01, SQL Server 1205
Подтверждает
В моменты сбоев обменов и крафта число дедлоков растёт, а две записанные транзакции блокируют одни и те же таблицы в противоположном порядке
Опровергает
Если число дедлоков не меняется, а сбои есть, это превышение лимита ожидания блокировки (ошибка MySQL 1205) или горячая строка (db-hot-row)
Чем проверить
Инструменты инфраструктуры (игровой код не нужен)
Источников: 10
InnoDB Startup Options and System VariablesMySQL При включённом обнаружении (по умолчанию) InnoDB сразу обнаруживает дедлок и делает роллбэк, innodb_lock_wait_timeout по умолчанию 50 секунд
Deadlock DetectionMySQL При очень высокой конкурентности само обнаружение может замедлиться, поэтому его иногда отключают и полагаются на лимит ожидания блокировки
Deadlocks guideMicrosoft SQL Server Интервал проверки на дедлок по умолчанию 5 секунд, при частых дедлоках он сокращается до 100 ms. Сессия system_health, включённая по умолчанию, собирает xml_deadlock_report, жертва получает ошибку 1205
How to Minimize and Handle DeadlocksMySQL Изменять несколько строк и таблиц всегда в одном порядке, при сбое повторять, innodb_print_all_deadlocks записывает все дедлоки
InnoDB Standard Monitor and Lock Monitor OutputMySQL LATEST DETECTED DEADLOCK: две транзакции последнего дедлока, удерживаемые и ожидаемые блокировки, транзакция, для которой сделан роллбэк
ID db-pool · Основной ответственный Команда разработки · Разработка сервера · Совместно Команда инфраструктуры · Инфраструктура БД
Число соединений с БД фиксировано, поэтому, когда медленные запросы занимают соединения, остальные запросы ждут.
Почему Медленные запросы или наплыв запросов занимают все соединения → Следствие Новые запросы ждут, пока освободится соединение → На экране Бесконечная загрузка при входе, задержки сохранения, таймауты
Сразу после входа или техработ, При наплыве игроков
Ответственные
Основной ответственный Команда разработки · Разработка сервера · Совместно Команда инфраструктуры · Инфраструктура БД
Команда разработки: задачи
Убрать медленные запросы, настроить размер пула и таймаут ожидания (не раздувать пул без оглядки), разделить пулы по функциям.
Команда инфраструктуры: задачи
Проверить максимальное число соединений БД и запас по CPU и IOPS, перед добавлением серверов и автомасштабированием проверять, что число серверов × размер пула не превышает максимум соединений, добавить в мониторинг метрики ожидания соединений и блокировок.
Цифры для ориентира
Нужное число соединений прикидывают как «запросов в секунду × время, на которое один запрос занимает соединение». При 2 000 запросов в секунду по 5 ms в среднем постоянно заняты 10 соединений. С учётом пиков обычно берут в два-три раза больше. Если запрос замедлится до 150 ms, при той же нагрузке понадобится 300 соединений.
На графике
Упор в лимит (плато) · число занятых соединений с БД, время ожидания соединения
Где смотреть
Считать состояние соединений по каждому игровому серверу на стороне БД. В MySQL смотреть Host, Command (у простаивающих соединений Sleep) и Time в SHOW PROCESSLIST, Threads_connected и Threads_running, а также число отклонённых соединений Connection_errors_max_connections. В PostgreSQL считать pg_stat_activity с группировкой по client_addr и state. Если библиотека пула соединений в игровом сервере отдаёт число ожидающих запросов и время ожидания, смотреть и их
Подтверждает
Все соединения одного игрового сервера (столько, сколько позволяет пул) выполняют запросы, свободных 0, и в это время вход и сохранения ждут. Либо общее число соединений с БД дошло до max_connections, и новые соединения отклоняются
Опровергает
Если свободных соединений достаточно, а всё медленно, дело в задержке самих запросов (db-no-index, db-hot-row) или в нехватке ресурсов БД
Чем проверить
Инструменты инфраструктуры (игровой код не нужен)
Подробнее
Если без оглядки раздувать пул, растёт только нагрузка на CPU БД и конкуренция за блокировки, и замедляются все. А если число серверов × размер пула превышает максимум соединений БД, новые или перезапущенные серверы не могут даже подключиться. Это часто случается при автомасштабировании и сразу после техработ.
Источников: 6
Number Of Database ConnectionsPostgreSQL Когда ресурсы БД исчерпаны, рост числа соединений даже снижает производительность. И для задержки, и для пропускной способности лучше держать столько активных соединений, сколько позволяют ресурсы, а остальные запросы держать в очереди
Too many connectionsMySQL Когда все max_connections заняты, новые соединения отклоняются с ошибкой Too many connections
SHOW PROCESSLIST StatementMySQL Host (адрес клиента), Command (у простаивающей сессии Sleep), Time, State
Server Status VariablesMySQL Threads_connected и Threads_running, Connection_errors_max_connections (число соединений, отклонённых из-за достижения max_connections)
ID db-replica-lag · Основной ответственный Команда инфраструктуры · Инфраструктура БД · Совместно Команда разработки · Разработка сервера
Если запись идёт в основную БД, а чтение с реплики, то при отставании реплики только что записанные данные не видны.
Почему Из-за потока записей в основную БД реплика отстаёт на несколько секунд → Следствие Если читать только что сохранённые данные с реплики, их там ещё нет → На экране Только что купленный предмет не виден, на торговой площадке старые цены, баги с двойной выдачей
Основной ответственный Команда инфраструктуры · Инфраструктура БД · Совместно Команда разработки · Разработка сервера
Команда разработки: задачи
Только что записанные данные читать из основной БД, проверку факта выдачи и саму выдачу делать в основной БД одной транзакцией (дубли отсекать уникальным ключом или условным UPDATE).
Команда инфраструктуры: задачи
Настроить алерт на отставание репликации, делать реплики не слабее основной БД, включить параллельную репликацию, массовые удаления выполнять мелкими порциями, контролировать долгие агрегирующие запросы на репликах.
На графике
Растёт вслед за онлайном и нагрузкой · отставание репликации (с)
Где смотреть
В MySQL смотреть на реплике Seconds_Behind_Source в SHOW REPLICA STATUS (в версиях до 8.0.22 SHOW SLAVE STATUS). В PostgreSQL смотреть write_lag, flush_lag и replay_lag в pg_stat_replication на основном сервере, в RDS смотреть ReplicaLag
Подтверждает
В моменты жалоб «не видно» отставание составляет несколько секунд и больше, а когда оно рассасывается, всё отображается нормально. Отставание растёт во время потока записей, массовых удалений или долгих агрегирующих запросов на реплике
Опровергает
Если отставание около 0, а данных всё равно не видно, дело в кэше или синхронизации на игровом сервере
Чем проверить
Инструменты инфраструктуры (игровой код не нужен)
Подробнее
Отставание бывает и без большого потока записей. Одно массовое удаление, которое на основной БД заняло 10 минут, повторно выполняется на реплике и на столько же её задерживает, а долгие агрегирующие запросы на реплике тоже мешают ей догонять.
Источников: 6
SHOW REPLICA STATUS StatementMySQL Seconds_Behind_Source: сколько прошло с момента, когда событие, которое реплика применяет сейчас, было записано на основной БД (отставание репликации)
Replica Server Options and VariablesMySQL replica_parallel_workers: несколько потоков применяют транзакции параллельно (по умолчанию 4, при 0 один поток применяет их по порядку)
Log-Shipping Standby Servers (PostgreSQL Documentation)PostgreSQL Потоковая репликация по умолчанию асинхронная, поэтому между коммитом и появлением данных на реплике есть задержка (если реплика успевает, обычно меньше 1 секунды)
The Cumulative Statistics System (PostgreSQL Documentation)PostgreSQL write_lag, flush_lag и replay_lag в pg_stat_replication: время от записи WAL на основном сервере до подтверждения от реплики, что она записала его, сбросила на диск и применила
ID db-checkpoint · Основной ответственный Команда инфраструктуры · Инфраструктура БД
В моменты, когда БД периодически сбрасывает накопленные в памяти изменения на диск, запросы замедляются.
Почему Изменения накапливаются и периодически записываются на диск → Следствие В этот момент диск занят, и запросы задерживаются → На экране Сохранения и загрузки периодически замедляются
Основной ответственный Команда инфраструктуры · Инфраструктура БД
Команда инфраструктуры: задачи
Растягивать контрольные точки мелкими равномерными порциями, делать журнал транзакций (redo-лог, WAL) с запасом, ставить быстрые диски.
На графике
Всплески с постоянным периодом · задержка запросов к БД, объём записи на диск
Где смотреть
Для PostgreSQL смотреть в логе log_checkpoints (в последних версиях включён по умолчанию) время контрольных точек и число записанных буферов, число контрольных точек (с версии 17 num_timed и num_requested в pg_stat_checkpointer, в 16 и ниже checkpoints_timed и checkpoints_req в pg_stat_bgwriter) и предупреждения checkpoint_warning. Для MySQL смотреть в секции LOG вывода SHOW ENGINE INNODB STATUS разницу между Log sequence number и Last checkpoint at. Накладывать на объём и задержку записи на диск сервера
Подтверждает
Всплески задержки запросов совпадают с контрольными точками, и в эти моменты подскакивают объём и задержка записи на диск. Если в PostgreSQL контрольных точек по запросу (num_requested) намного больше, чем по времени (num_timed), значит WAL часто достигает max_wal_size и контрольные точки наступают раньше срока
Опровергает
Если всплески идут с периодом, не связанным с контрольными точками, это бэкап или пакетные задания (dk-backup, db-batch)
Чем проверить
Инструменты инфраструктуры (игровой код не нужен)
Подробнее
Если журнал транзакций, куда записываются изменения (redo-лог в MySQL, WAL в PostgreSQL), слишком мал, то при каждом заполнении журнала БД в спешке делает контрольную точку, и производительность записи ненадолго сильно падает.
Источников: 7
WAL Configuration (PostgreSQL Documentation)PostgreSQL Контрольная точка выполняется по умолчанию каждые 5 минут или каждый 1 GB WAL (max_wal_size) и стоит дорого, потому что записывает все грязные страницы. checkpoint_completion_target растягивает запись, чтобы избежать всплеска ввода-вывода. Если интервал между контрольными точками короче checkpoint_warning, в лог пишется предупреждение с советом увеличить max_wal_size
Configuring Buffer Pool FlushingMySQL Когда redo-лог заполняется, резкая (sharp) контрольная точка ненадолго снижает производительность, адаптивный сброс распределяет запись равномерно
PostgreSQL 17 Release NotesPostgreSQL Появилось представление pg_stat_checkpointer, столбцы, связанные с контрольными точками, перенесены в него из pg_stat_bgwriter
ID db-cold-cache · Основной ответственный Команда инфраструктуры · Инфраструктура БД · Совместно Команда разработки · Разработка сервера
После перезапуска БД кэш в памяти пуст, и какое-то время все запросы читают данные с диска.
Почему БД перезапускается на техработах → Следствие Часто используемых данных нет в памяти, они читаются с диска → На экране Сразу после техработ какое-то время медленно проходят вход и загрузка
Основной ответственный Команда инфраструктуры · Инфраструктура БД · Совместно Команда разработки · Разработка сервера
Команда разработки: задачи
Открывать сервер постепенно (через очередь на вход поэтапно увеличивать число входящих игроков).
Команда инфраструктуры: задачи
Прогревать кэш после перезапуска (проверить настройки сохранения и восстановления буферного пула), у БД, восстановленной из снапшота, заранее прочитать и диск.
На графике
Всплеск сразу после входа или техработ · чтение с диска, доля попаданий в буферный кэш
Где смотреть
В MySQL смотреть отношение Innodb_buffer_pool_reads (сколько раз данных не было в буферном пуле и пришлось читать с диска) к Innodb_buffer_pool_read_requests и ход прогрева в Innodb_buffer_pool_load_status. В PostgreSQL смотреть blks_read и blks_hit в pg_stat_database. Смотреть и число чтений с диска на сервере БД
Подтверждает
Сразу после перезапуска чтение с диска подскакивает, доля попаданий низкая и со временем восстанавливается, и на этом отрезке медленно проходят вход и загрузка
Опровергает
Если доля попаданий обычная, а после техработ всё медленно, это наплыв входов и N+1 (db-login-storm) или пул соединений (db-pool)
Чем проверить
Инструменты инфраструктуры (игровой код не нужен)
Подробнее
MySQL при выключении сохраняет список страниц буферного пула, а при запуске в фоне читает их заново, но на полное заполнение нужно время. Если в облаке БД восстановлена из снапшота (копии диска), то и сам диск медленно отдаёт каждый блок при первом чтении, и прогрев затягивается ещё сильнее.
Saving and Restoring the Buffer Pool StateMySQL Чтобы сократить прогрев после перезапуска, при выключении сохраняется список недавно использованных страниц (по умолчанию 25%), а при запуске они читаются заново. Обе функции включены по умолчанию
Initialize Amazon EBS volumesAWS Том, созданный из снапшота, пока не подтянет все блоки, работает с повышенной задержкой и пониженной производительностью
Server Status VariablesMySQL Innodb_buffer_pool_reads (число логических чтений, которые не нашли данных в буферном пуле и читали напрямую с диска), Innodb_buffer_pool_read_requests, Innodb_buffer_pool_load_status (ход прогрева)
ID db-login-storm · Основной ответственный Команда разработки · Разработка сервера · Совместно Команда инфраструктуры · Инфраструктура БД
Если для загрузки одного персонажа нужны десятки отдельных запросов, одновременный вход десятков тысяч игроков превращается в миллионы запросов.
Почему При загрузке персонажа предметы, умения и квесты запрашиваются по отдельности → Следствие Сразу после техработ одновременные входы резко увеличивают число запросов → На экране Бесконечная загрузка при входе, застревают даже сохранения тех, кто уже играет
Основной ответственный Команда разработки · Разработка сервера · Совместно Команда инфраструктуры · Инфраструктура БД
Команда разработки: задачи
Запрашивать данные одним пакетом, ввести очередь на вход, кэшировать, проверить, сколько запросов порождает ленивая загрузка в ORM.
Команда инфраструктуры: задачи
Составлять рейтинг запросов по числу вызовов и передавать его команде разработки, мониторить число запросов и соединений в часы входа сразу после техработ.
На графике
Всплеск сразу после входа или техработ · запросов к БД в секунду, число входов
Где смотреть
Накладывать число входов сразу после техработ на число запросов к БД в секунду (в MySQL прирост Questions) и считать число запросов на один вход. Запросы с наибольшим числом вызовов выбирать по COUNT_STAR в events_statements_summary_by_digest в MySQL и по calls в pg_stat_statements в PostgreSQL
Подтверждает
На один вход приходятся десятки запросов, а в топе одинаковые короткие запросы по одному ID персонажа. Если после патча число запросов на вход выросло, разбор начинают с этого патча
Опровергает
Если запросов на вход мало, но каждый медленный, это холодный кэш (db-cold-cache) или индекс (db-no-index)
Чем проверить
Инструменты инфраструктуры (игровой код не нужен)
Подробнее
Ленивая загрузка в ORM (библиотеке, которая сама строит запросы к БД) порождает такие запросы незаметно даже для разработчиков. На сервере разработки всего несколько персонажей, и проблемы не видно, а впервые она проявляется при одновременном входе на живых серверах.
Источников: 5
Efficient Querying.NET Ленивая загрузка в ORM порождает проблему N+1, когда на каждый элемент уходит ещё один запрос, и сильно снижает производительность. Рекомендуется загружать данные одним разом (eager loading)
ID db-batch · Основной ответственный Команда разработки · Разработка сервера · Совместно Команда инфраструктуры · Инфраструктура БД
Если подсчёт рейтингов, массовую рассылку почты или чистку старых данных запускать во время работы сервиса, они занимают блокировки и диск.
Почему Массовая операция запускается в рабочие часы сервиса → Следствие Блокировки на широкий диапазон, заняты диск и CPU → На экране В определённые часы срываются обмены и сохранения, медленно идёт загрузка
Основной ответственный Команда разработки · Разработка сервера · Совместно Команда инфраструктуры · Инфраструктура БД
Команда разработки: задачи
Дробить работу на мелкие порции, агрегацию выполнять на реплике.
Команда инфраструктуры: задачи
Выделить реплику для агрегации, планировать пакетные задания на часы низкой нагрузки, следить за эскалацией блокировок и ожиданиями gap-блокировок.
На графике
Всплески с постоянным периодом · задержка запросов к БД, ожидания блокировок
Где смотреть
Найти долгие запросы, которые выполнялись в момент лагов. Для MySQL смотреть slow query log, для PostgreSQL query_start и query в pg_stat_activity и сверять с метриками ожидания блокировок за то же время и с расписанием пакетных заданий (cron, планировщик событий БД). В SQL Server записывать эскалацию блокировок расширенным событием lock_escalation
Подтверждает
Каждый раз в одно и то же время идут массовые UPDATE, DELETE или агрегирующие запросы, и в это время вместе растут ожидания блокировок и утилизация диска
Опровергает
Если в это время долгих запросов нет, это контрольная точка (db-checkpoint) или бэкап сервера (dk-backup)
Чем проверить
Инструменты инфраструктуры (игровой код не нужен)
Подробнее
SQL Server, когда один оператор захватывает больше примерно 5 000 блокировок строк, заменяет их блокировкой таблицы (эскалация блокировок). В этот момент останавливаются все запросы к этой таблице. MySQL в настройках по умолчанию при изменении по условию диапазона тоже блокирует промежутки между строками (gap-блокировка) и не даёт добавлять новые строки.
Источников: 4
Transaction Locking and Row Versioning GuideMicrosoft SQL Server Если один оператор захватывает 5 000 и больше блокировок в одной таблице (или индексе), происходит эскалация блокировок, её записывает расширенное событие lock_escalation
InnoDB LockingMySQL При уровне изоляции InnoDB по умолчанию REPEATABLE READ поиск и сканирование используют next-key-блокировки, и gap-блокировка не даёт добавлять новые строки в этот промежуток
The Slow Query LogMySQL Записывает запросы дольше long_query_time вместе с временем выполнения (Query_time), временем блокировки (Lock_time) и числом прочитанных строк
ID db-failover · Основной ответственный Команда инфраструктуры · Инфраструктура БД · Совместно Команда разработки · Разработка сервера
Пока после отказа основной БД идёт переключение на резервную, запись невозможна, а последние данные, которые не успели реплицироваться, могут пропасть.
Почему Из-за отказа основной БД резервная повышается до основной → Следствие Во время переключения запись невозможна от нескольких секунд до нескольких минут, при асинхронной репликации возможна потеря нереплицированных данных → На экране Ненадолго не проходят все сохранения, роллбэк предметов и опыта
Основной ответственный Команда инфраструктуры · Инфраструктура БД · Совместно Команда разработки · Разработка сервера
Команда разработки: задачи
Делать сохранения, которые можно безопасно повторить, настроить быстрый сброс оборванных соединений и переподключение по новому адресу (пул соединений, кэш DNS), проверять переподключение на учениях по переключению.
Команда инфраструктуры: задачи
Использовать синхронную или полусинхронную репликацию (ценой роста задержки записи), проводить учения по переключению, отслеживать время переключения и отставание репликации.
Цифры для ориентира
Автоматическое переключение управляемой БД обычно занимает от десятков секунд до 2 минут. При асинхронной репликации можно потерять последние сохранения за время, равное отставанию репликации (от менее чем 1 секунды до нескольких секунд).
На графике
Массовый обрыв соединений · число соединений с БД, число ошибок записи
Где смотреть
Поставить на один график записи о переключении на стороне БД (в RDS события RDS-EVENT-0013 начало переключения и RDS-EVENT-0049 окончание, в самостоятельно управляемой БД лог повышения реплики) и число соединений с БД и ошибок соединения на игровых серверах. При асинхронной репликации смотреть и отставание репликации перед отказом (ReplicaLag в RDS, replay_lag в pg_stat_replication в PostgreSQL)
Подтверждает
Сбои сохранения сосредоточены в одном отрезке, и он совпадает с интервалом между началом и концом переключения. Потерянный отрезок прогресса примерно равен отставанию репликации перед отказом. Игровой сервер, у которого ошибки продолжаются и после переключения, всё ещё использует соединения со старым адресом
Опровергает
Обрывы соединений в моменты, когда записей о переключении нет, указывают на сеть или перегрузку БД
Failing over a Multi-AZ DB instance for Amazon RDSAWS Переключение Multi-AZ обычно занимает 60–120 секунд, после него нужно заново установить соединения, TTL кэша DNS в JVM рекомендуется не больше 60 секунд
High availability for Amazon AuroraAWS Во время сбоя чтение и запись не проходят, восстановление обычно в пределах 60 секунд (часто в пределах 30)
Semisynchronous ReplicationMySQL При асинхронной репликации после отказа основной БД закоммиченных транзакций может не оказаться на реплике. Полусинхронная репликация сокращает этот риск, дожидаясь подтверждения получения от одной реплики, но задержка растёт
Log-Shipping Standby Servers (PostgreSQL Documentation)PostgreSQL Передача журнала асинхронная, поэтому при отказе основного сервера ещё не отправленные транзакции теряются, отставание потоковой репликации обычно меньше 1 секунды
ID db-save-interval · Основной ответственный Команда разработки · Разработка сервера · Совместно Команда инфраструктуры · Инфраструктура БД
Если ради снижения нагрузки сохранять прогресс раз в несколько минут, то при падении сервера в промежутке прогресс пропадает.
Почему Состояние персонажа сохраняется раз в несколько минут → Следствие В промежутке сервер падает или происходит сбой → На экране После перезахода персонаж в состоянии нескольких минут назад (роллбэк)
Основной ответственный Команда разработки · Разработка сервера · Совместно Команда инфраструктуры · Инфраструктура БД
Команда разработки: задачи
Важные события (обмен, редкая добыча) сохранять сразу, вести журнал изменений.
Команда инфраструктуры: задачи
Проверить, хватит ли у БД запаса IOPS и CPU на рост записи при сокращении интервала сохранения.
На графике
Массовый обрыв соединений · число подключений, число жалоб на роллбэк
Где смотреть
Сопоставить время падения или сбоя и время последнего сохранения персонажей, на которых пожаловались из-за роллбэка (лог сохранений игрового сервера или столбец времени изменения в БД)
Подтверждает
Момент, к которому вернулся персонаж, совпадает с последним сохранением перед падением, а потерянное время меньше интервала сохранения
Опровергает
Если в логе игрового сервера сохранение отмечено как завершённое, а прогресс всё равно вернулся назад, это потеря данных при переключении БД на резерв (db-failover) или старое значение, прочитанное с реплики (db-replica-lag)
Чем проверить
Нужны логи и метрики игрового сервера или клиента
Источников: 2
Asynchronous Commit (PostgreSQL Documentation)PostgreSQL Если накапливать записи и сбрасывать их позже, производительность растёт, но при сбое могут пропасть самые последние транзакции (тот же компромисс)
Redis persistenceRedis Если делать снапшоты RDB раз в несколько минут, при аварийном завершении нужно быть готовым потерять данные за последние несколько минут
ID db-cache-stampede · Основной ответственный Команда разработки · Разработка сервера · Совместно Команда инфраструктуры · Инфраструктура БД
Когда кэш популярных данных истекает одновременно, тысячи запросов разом идут в БД.
Почему Популярные данные в Redis или другом кэше истекают одновременно → Следствие Запросы, которые заново строят те же данные, разом обрушиваются на БД → На экране БД перегружена, и одна функция за другой начинает тормозить или перестаёт отвечать
Основной ответственный Команда разработки · Разработка сервера · Совместно Команда инфраструктуры · Инфраструктура БД
Команда разработки: задачи
Разносить время истечения случайным образом, обновлять данные одним запросом, а остальным отдавать старое значение.
Команда инфраструктуры: задачи
Настроить для Redis реплики и автоматическое переключение, чтобы при перезапуске или сбое кэш не опустел целиком, проверить, выдержит ли БД пустой кэш.
На графике
Всплески с постоянным периодом · доля попаданий в кэш, запросов к БД в секунду
Где смотреть
Накладывать keyspace_hits и keyspace_misses (доля попаданий), expired_keys и признак перезапуска (uptime_in_seconds) из Redis INFO на число запросов к БД в секунду и считать, сколько одинаковых запросов одновременно выполняется в БД в этот момент (MySQL SHOW PROCESSLIST, PostgreSQL pg_stat_activity)
Подтверждает
В момент резкого скачка промахов кэша вместе подскакивает число запросов к БД, и большинство одновременных запросов одинаковые и читают одни и те же данные. Совпадает с периодом истечения популярного ключа или с перезапуском Redis
Опровергает
Если промахов кэша столько же, сколько обычно, а растут только запросы к БД, это наплыв входов (db-login-storm) или пакетное задание (db-batch)
Чем проверить
Инструменты инфраструктуры (игровой код не нужен)
Подробнее
То же самое бывает, когда Redis перезапускается или из-за сбоя кэш пустеет целиком. Особенно опасно, если в расчёте на кэш БД сделали маломощной.
Источников: 6
Scaling Memcache at Facebook (NSDI '13)USENIX Когда инвалидируется часто используемый ключ, множество чтений устремляется в БД (thundering herd). Это предотвращают арендой (lease, обновляет только один клиент) и выдачей старого значения, кластер с пустым кэшем прогревают отдельно
Optimal Probabilistic Cache Stampede PreventionVLDB Endowment Когда истекает популярный элемент, его одновременно пересоздают многие запросы (cache stampede). Это предотвращают вероятностным досрочным обновлением до истечения
INFORedis keyspace_hits и keyspace_misses (число успешных и неуспешных поисков ключа), expired_keys (число истёкших ключей), uptime_in_seconds (время с момента запуска)
SHOW PROCESSLIST StatementMySQL Для каждой сессии выполняемый оператор (Info) и время в текущем состоянии (Time, в секундах)
ID db-long-tx · Основной ответственный Команда разработки · Разработка сервера · Совместно Команда инфраструктуры · Инфраструктура БД
Если одна транзакция долго остаётся открытой, она продолжает держать блокировки, а БД не может очистить (purge) старые версии данных, и всё постепенно замедляется.
Почему Транзакция остаётся открытой, пока ждёт ответа другого сервера, или на основной БД в рабочее время идёт долгий агрегирующий запрос → Следствие Захваченные блокировки не освобождаются, старые версии данных, которые нужно удалить, продолжают копиться → На экране Таймауты в функциях, которые обращаются к этой строке, за несколько часов в целом замедляются сохранения и чтение данных
Основной ответственный Команда разработки · Разработка сервера · Совместно Команда инфраструктуры · Инфраструктура БД
Команда разработки: задачи
Не ждать внутри транзакции сетевых вызовов и ввода пользователя, агрегирующие запросы выполнять на реплике.
Команда инфраструктуры: задачи
Настроить алерт на долго открытые транзакции и принудительно их завершать, выделить реплику для агрегации, следить за ростом undo-лога и мёртвых строк.
На графике
Плавный рост · длина undo-лога (History list length), число мёртвых строк
Где смотреть
В MySQL искать самую старую транзакцию по trx_started в INFORMATION_SCHEMA.INNODB_TRX и смотреть History list length (объём ещё не очищенного undo-лога) в секции TRANSACTIONS вывода SHOW ENGINE INNODB STATUS. В PostgreSQL смотреть xact_start в pg_stat_activity и сессии в состоянии idle in transaction, а также n_dead_tup в pg_stat_user_tables
Подтверждает
Есть транзакция возрастом от нескольких минут до нескольких часов, всё это время History list length или n_dead_tup растут, а после завершения этой транзакции очистка (purge, VACUUM) их снижает
Опровергает
Если старых транзакций нет, а в целом всё медленно, дело в контрольных точках (db-checkpoint) или в диске
Чем проверить
Инструменты инфраструктуры (игровой код не нужен)
Подробнее
Чтобы читающие видели данные в состоянии до изменения, БД хранит старые версии (MVCC). Удалить эти записи можно только после завершения самой старой транзакции, поэтому если одна транзакция открыта несколько часов, в MySQL копится undo-лог, а в PostgreSQL мёртвые строки (dead tuple), которые не может убрать VACUUM. В SQL Server журнал транзакций не сокращается и может заполнить диск.
Источников: 7
InnoDB Multi-VersioningMySQL Пока остаётся транзакция, которой могут понадобиться старые версии, update undo-лог нельзя удалить и rollback-сегмент растёт. Рекомендуется часто коммитить даже транзакции, которые только читают
Routine Vacuuming (PostgreSQL Documentation)PostgreSQL Старые версии строк нельзя удалить, пока их может видеть другая транзакция, долго открытую транзакцию нужно завершить или закрыть её сессию
Purge ConfigurationMySQL Purge очищает список undo-логов закоммиченных транзакций (history list), отставание показывает History list length в секции TRANSACTIONS вывода SHOW ENGINE INNODB STATUS
ID db-redis-block · Основной ответственный Команда разработки · Разработка сервера · Совместно Команда инфраструктуры · Инфраструктура БД
Redis обрабатывает команды по одной, поэтому одна медленная команда блокирует все запросы за ней.
Почему В рабочее время выполняется полный перебор через KEYS, рейтинг или список из миллионов элементов читается или удаляется целиком → Следствие Пока команда не закончится, все остальные запросы ждут (от десятков ms до нескольких секунд) → На экране Одновременно подвисают функции, которые используют сессии, рейтинги и кэш, задерживается вход
Основной ответственный Команда разработки · Разработка сервера · Совместно Команда инфраструктуры · Инфраструктура БД
Команда разработки: задачи
Использовать SCAN вместо KEYS, дробить большие ключи, удалять через UNLINK (фоновое удаление), разносить время истечения ключей, которое приходится на одну и ту же секунду.
Команда инфраструктуры: задачи
Следить за журналом медленных команд (SLOWLOG), запретить опасные команды вроде KEYS на боевых серверах, регулярно проверять большие ключи, отключить THP и держать запас памяти для fork, сохранять RDB и AOF на реплике.
Цифры для ориентира
Обычная команда выполняется меньше чем за 1 ms. Операция над миллионами элементов за раз может занять от сотен ms до нескольких секунд.
На графике
Случайные всплески · задержка ответа Redis, число медленных команд
Где смотреть
Через SLOWLOG GET смотреть команды дольше slowlog-log-slower-than, включить монитор задержек (по умолчанию выключен) через CONFIG SET latency-monitor-threshold и смотреть задержки по событиям вроде fork и expire-cycle в LATENCY LATEST и LATENCY DOCTOR. Время fork и большие ключи проверять по latest_fork_usec в INFO и через redis-cli --bigkeys
Подтверждает
В момент подвисания в SLOWLOG есть KEYS или команды, которые целиком обрабатывают большой ключ, либо в LATENCY в то же время записаны события fork или expire-cycle на десятки ms и больше
Опровергает
Если SLOWLOG и LATENCY пусты, а медленно только со стороны игрового сервера, дело в сети или в ожидании внутри игрового сервера (SLOWLOG измеряет только время выполнения команды без обмена данными с клиентом)
Чем проверить
Инструменты инфраструктуры (игровой код не нужен)
Подробнее
Redis останавливается и в момент, когда для создания файла сохранения (снапшота RDB) или перезаписи AOF копирует процесс (fork). На современных серверах это около 10 ms на 1 GB памяти, то есть для 30 GB около 300 ms. Если включены большие страницы (THP), после fork каждая запись копирует большую страницу целиком (copy-on-write), и паузы и потребление памяти сильно растут, поэтому THP обычно отключают и держат большой запас памяти. Когда в одну и ту же секунду истекает очень много ключей, Redis тоже ненадолго останавливается, чтобы их удалить.
Источников: 7
Diagnosing latency issuesRedis Запросы по очереди обрабатывает один поток, и медленная команда блокирует всё за ней, SCAN вместо KEYS, fork по измерениям на физических серверах и современных ВМ занимает около 9–13 ms на 1 GB, THP из-за копирования после fork резко увеличивает задержки и память, массовое истечение ключей в одну секунду вызывает остановку
KEYSRedis В боевой среде использовать с крайней осторожностью, на большой базе может убить производительность (на бюджетном ноутбуке 40 ms на 1 000 000 ключей)
UNLINKRedis Асинхронное удаление: ключ сразу отсоединяется, а память освобождается в другом потоке
SLOWLOGRedis Журнал медленных команд записывает команды дольше slowlog-log-slower-than, время выполнения не включает ввод-вывод при обмене с клиентом
Redis latency monitoringRedis latency-monitor-threshold по умолчанию 0 (выключен), LATENCY LATEST и LATENCY DOCTOR, запись задержек по событиям вроде fork и expire-cycle
INFORedis latest_fork_usec: длительность последнего fork (в микросекундах)
Redis CLIRedis --bigkeys: просматривает пространство ключей и находит большие ключи
ID db-plan-flip · Основной ответственный Команда инфраструктуры · Инфраструктура БД · Совместно Команда разработки · Разработка сервера
Код не менялся, но если БД меняет способ выполнения того же запроса (план выполнения), вчерашний запрос на 2 ms сегодня занимает сотни ms.
Почему Автоматическое обновление статистики, перезапуск БД или изменение распределения данных заставляют БД построить план заново → Следствие Выбирается план без индекса, тот же запрос становится медленнее в десятки или сотни раз и надолго занимает соединения → На экране Деплоя не было, но загрузка в какой-то функции внезапно замедляется, и ждут даже другие запросы
Основной ответственный Команда инфраструктуры · Инфраструктура БД · Совместно Команда разработки · Разработка сервера
Команда разработки: задачи
Запросы, у которых число результатов сильно зависит от значения параметра, разделять или рассмотреть подсказки плана, проектировать запросы так, чтобы они гарантированно использовали индекс.
Команда инфраструктуры: задачи
Следить за медленными запросами и записями планов выполнения, фиксировать хорошие планы (хранилище запросов SQL Server и др.), управлять временем обновления статистики.
На графике
Ступенька вверх с определённого момента · среднее время выполнения по запросам
Где смотреть
Периодически собирать среднее время запросов одного вида и смотреть динамику. В MySQL это AVG_TIMER_WAIT в events_statements_summary_by_digest, в PostgreSQL mean_exec_time в pg_stat_statements (в 12 и ниже mean_time). Планы выполнения до и после замедления сравнивать через EXPLAIN или auto_explain в PostgreSQL, в SQL Server через представление «Регрессированные запросы» (Regressed Queries) хранилища запросов
Подтверждает
В отсутствие деплоя среднее время одного запроса ступенькой вырастает в несколько десятков раз, этот момент совпадает с обновлением статистики или перезапуском БД, и план выполнения изменился
Опровергает
Если план выполнения тот же, а запрос замедлился, дело в росте данных, ожидании блокировок (db-hot-row) или диске
Чем проверить
Инструменты инфраструктуры (игровой код не нужен)
Подробнее
SQL Server повторно использует план, построенный под первое пришедшее значение (прослушивание параметров, parameter sniffing). Если план, построенный для нового персонажа с несколькими предметами, применяется к старому персонажу с десятками тысяч предметов, запрос сильно замедляется, и обратная ситуация тоже частая. Когда перезапуск очищает планы, всё приходит в норму, а потом может снова испортиться.
Источников: 7
Query Processing Architecture GuideMicrosoft SQL Server Прослушивание параметров: план выполнения строится под значения параметров, переданные при компиляции или перекомпиляции
Parameter Sensitive Plan OptimizationMicrosoft SQL Server Если данные распределены неравномерно, один закэшированный план подходит не для всех значений параметров
Monitor performance by using the Query StoreMicrosoft SQL Server Изменения статистики, схемы или индексов меняют план, а кэш планов хранит только последний план. Принудительный план в хранилище запросов фиксирует хороший план, представление «Регрессированные запросы» (Regressed Queries) позволяет сравнить замедлившиеся запросы и их планы
Statement Summary TablesMySQL events_statements_summary_by_digest: по каждому виду запроса COUNT_STAR и AVG_TIMER_WAIT (среднее время)
ID db-ddl-lock · Основной ответственный Команда инфраструктуры · Инфраструктура БД · Совместно Команда разработки · Разработка сервера
Если во время работы сервиса добавить в таблицу столбец или индекс, из-за одной кратковременной блокировки могут встать все запросы к этой таблице.
Почему Хотфиксом в рабочую таблицу добавляется столбец или индекс → Следствие Изменение схемы ждёт ранее открытую длинную транзакцию, а все следующие запросы ждут изменение схемы → На экране Функции, которые используют эту таблицу (инвентарь, почта и т. п.), полностью перестают работать, запросы завершаются по таймауту
Основной ответственный Команда инфраструктуры · Инфраструктура БД · Совместно Команда разработки · Разработка сервера
Команда разработки: задачи
Хотфиксы с изменением схемы согласовывать по срокам с инфраструктурой БД, сначала деплоить код, который работает и без нового столбца.
Команда инфраструктуры: задачи
Ставить короткий лимит ожидания блокировки и при сбое повторять, запускать, когда нет длинных транзакций, использовать инструменты онлайн-изменения схемы, большие таблицы менять во время техработ.
На графике
Ступенька вверх с определённого момента · число сессий в ожидании блокировки, задержка запросов к этой таблице
Где смотреть
В MySQL считать сессии с State Waiting for table metadata lock в SHOW PROCESSLIST и искать блокирующую сессию (blocking_pid) через sys.schema_table_lock_waits. В PostgreSQL смотреть запросы, у которых granted равно false, и AccessExclusiveLock в pg_locks и искать блокирующую сессию через pg_blocking_pids()
Подтверждает
С момента запуска изменения схемы все запросы к этой таблице копятся в ожидании блокировки, а в начале очереди стоит незавершённая транзакция или оператор изменения схемы
Опровергает
Если ожидания сосредоточены только на определённых строках, а остальные строки той же таблицы обрабатываются нормально, это горячая строка (db-hot-row)
Чем проверить
Инструменты инфраструктуры (игровой код не нужен)
Подробнее
При изменении схемы MySQL ненадолго берёт блокировку метаданных, а PostgreSQL самую сильную блокировку таблицы. Само изменение мгновенное, но если перед ним висит одна незавершённая транзакция, все запросы за ним встают в очередь.
Источников: 8
Online DDL Performance and ConcurrencyMySQL Даже онлайн-DDL в конце ненадолго требует эксклюзивную блокировку метаданных. Если есть длинная транзакция, DDL её ждёт, а ожидающий запрос блокировки задерживает все последующие транзакции
Server System VariablesMySQL lock_wait_timeout: лимит ожидания блокировки метаданных, по умолчанию 31 536 000 секунд (1 год)
ID in-gateway · Основной ответственный Команда разработки · Разработка сервера · Совместно Команда инфраструктуры · Серверная инфраструктура, Команда разработки · Разработка клиента
Если поставить между клиентом и игровым сервером промежуточный сервер, каждый проход через него добавляет время обработки, а сам он становится единой точкой отказа.
Почему Схема клиент ↔ шлюз ↔ игровой сервер → Следствие Промежуточный сервер добавляет обработку и ожидание, при его перегрузке страдают все → На экране Пинг растёт у всех, при отказе шлюза дисконнект у всех игроков, которые через него подключены
Основной ответственный Команда разработки · Разработка сервера · Совместно Команда инфраструктуры · Серверная инфраструктура, Команда разработки · Разработка клиента
Команда разработки: задачи
Сервер: заложить возможность добавлять шлюзы и восстановление сессии, чтобы при падении шлюза персонаж продолжал игру после переподключения к другому шлюзу. Клиент: автоматически переподключаться при обрыве связи со шлюзом.
Команда инфраструктуры: задачи
Масштабировать шлюзы горизонтально (добавлять машины), мониторить CPU, число соединений и задержку обработки на каждом шлюзе.
Цифры для ориентира
Внутри одного ЦОД один проход обычно занимает меньше 1 ms. При перегрузке шлюза это время вырастает до десятков и сотен ms.
На графике
Растёт вслед за онлайном и нагрузкой · задержка обработки на шлюзе, CPU и число соединений шлюза
Где смотреть
Смотреть CPU и число соединений шлюза, Recv-Q его сокетов (ss, netstat) и разницу задержки до шлюза и после него. Для вызовов HTTP и gRPC через service mesh сравнить стандартную метрику Istio istio_request_duration_milliseconds на стороне отправителя (reporter=source) и получателя (reporter=destination)
Подтверждает
Время обработки на игровом сервере не меняется, растёт только задержка на участке шлюза, и в это же время CPU шлюза упирается в потолок или копится Recv-Q
Опровергает
Если маршрут в обход этого шлюза (прямое подключение, другой шлюз) тормозит так же, проблема в линии связи или на игровом сервере
Чем проверить
Инструменты инфраструктуры (игровой код не нужен)
Подробнее
С service mesh (Istio и т. п.) добавляется ещё одно звено: sidecar-прокси (Envoy), который работает рядом с каждым сервером. Запрос между сервисами проходит сначала через sidecar отправителя, потом через sidecar получателя, и чем больше функций добавлено в прокси (например, сбор логов и метрик), тем больше время обработки и ожидания.
Performance and ScalabilityIstio В режиме sidecar запрос проходит по очереди через sidecar-прокси отправителя и получателя. Чем больше функций, тем длиннее путь обработки внутри прокси, а сбор телеметрии увеличивает ожидание следующего запроса
What is EnvoyEnvoy Envoy работает отдельным процессом рядом с каждым сервером приложений, и приложение обменивается данными через Envoy на localhost
Istio Standard MetricsIstio istio_request_duration_milliseconds (распределение времени обработки запросов HTTP и gRPC), метка reporter различает прокси отправителя (source) и получателя (destination)
netstat(8) — Linux manual pagenet-tools Recv-Q: число байтов в подключённом сокете, которые программа пользователя ещё не забрала
ID in-zone-transfer · Основной ответственный Команда разработки · Разработка сервера · Совместно Команда инфраструктуры · Серверная инфраструктура
При входе в другую локацию или данж данные персонажа передаются на другой сервер, и на этом этапе возникают задержки и сбои.
Почему Вход в данж или переход на другой континент меняет обслуживающий сервер → Следствие Сохранение → передача → загрузка; если целевой сервер перегружен или нет свободного инстанса данжа, приходится ждать → На экране Долгая загрузка, неудачный вход, дисконнект во время перехода
Основной ответственный Команда разработки · Разработка сервера · Совместно Команда инфраструктуры · Серверная инфраструктура
Команда разработки: задачи
Сократить объём передаваемых данных, заранее резервировать место на целевом сервере, при неудаче возвращать персонажа на прежнее место.
Команда инфраструктуры: задачи
Мониторить запас свободных инстансов на серверах данжей и зон, до пика заранее поднимать нужное число серверов.
На графике
Растёт вслед за онлайном и нагрузкой · время перехода между зонами, число неудачных переходов
Где смотреть
Смотреть в логах сервера время каждого этапа передачи (сохранение, передача, загрузка) и причины сбоев, число игроков и свободных инстансов на целевом сервере
Подтверждает
В моменты жалоб на долгую загрузку и неудачный вход время передачи растёт или копятся сбои, а целевой сервер перегружен или свободные инстансы закончились
Опровергает
Если передача закончилась быстро, а фриз начинается уже после прибытия, причина скорее в лавине спавна при входе в людное место или в загрузке на клиенте
Чем проверить
Нужны логи и метрики игрового сервера или клиента
Подробнее
Даже в бесшовном мире без загрузок при пересечении границы сервера меняется обслуживающий сервер. Возле границы возможны короткие замирания или откидывание назад.
Источников: 1
The Unique Architecture behind Amazon Games’ Seamless MMO New WorldAWS Мир без загрузок делится сеткой на участки, которые обслуживают разные серверы (хабы), и при перемещении игрока его состояние передаётся от хаба к хабу. Сессионные режимы берут свободные серверы из общего пула
ID in-cascade · Основной ответственный Команда разработки · Разработка сервера · Совместно Команда инфраструктуры · Сетевая инфраструктура
Когда один сервис тормозит, вызывающие его серверы зависают в ожидании ответа, и останавливаются даже функции, которые с ним не связаны.
Почему Тормозит один сервис, например БД или авторизация → Следствие Потоки и соединения вызывающих серверов заняты ожиданием ответа, а повторные попытки неудачных запросов добавляют нагрузку → На экране Тормозят или останавливаются даже функции, которые кажутся никак не связанными
Основной ответственный Команда разработки · Разработка сервера · Совместно Команда инфраструктуры · Сетевая инфраструктура
Команда разработки: задачи
Ставить таймауты на все вызовы, использовать circuit breaker (предохранитель для вызовов) и изоляцию функций друг от друга (bulkhead), повторять с растущим интервалом и ограничением числа попыток, отделить ответы на health check от тяжёлой работы.
Команда инфраструктуры: задачи
Дать запас по числу неудач и интервалу health check балансировщика, чтобы ненадолго притормозивший сервер не выводился сразу, и ограничить число серверов, выводимых одновременно.
На графике
Упор в лимит (плато) · время ответа и доля ошибок по сервисам, число занятых потоков и соединений
Где смотреть
Вывести на один экран с общей шкалой времени время ответа, долю ошибок и число повторов по сервисам и найти место, которое замедлилось первым. За балансировщиком смотреть время ответа целевых серверов (в AWS ALB это TargetResponseTime), число ответов 5xx от них (HTTPCode_Target_5XX_Count) и число целевых серверов, выведенных как неисправные (UnHealthyHostCount)
Подтверждает
Сначала растёт задержка одного сервиса, затем у вызывающих его сторон число занятых потоков и соединений упирается в лимит, ошибки переходят на другие сервисы, а вместе с ними растут число повторов и число выведенных целевых серверов
Опровергает
Если несколько сервисов замедлились в один и тот же момент, сначала проверить сбой общего ресурса (БД, сеть, хост)
Чем проверить
Инструменты инфраструктуры (игровой код не нужен)
Подробнее
Health check (проверка, жив ли сервер) тоже раскручивает каскад. Если занятый сервер отвечает на проверку с опозданием, балансировщик выводит исправный сервер из ротации, его трафик уходит на оставшиеся, и следующий сервер тоже начинает опаздывать с ответами.
Site Reliability Engineering, Chapter 22: Addressing Cascading FailuresGoogle Перегруженный сервер не проходит health check и выводится, нагрузка ложится на оставшиеся, а повторы её усиливают. Рекомендуются лимит повторов, экспоненциальная задержка повтора со случайным разбросом и дедлайны
Circuit Breaker PatternMicrosoft Azure Запросы, которые висят до таймаута, держат потоки и соединения с БД, и из-за этого отказывают даже не связанные функции. Если за заданное время накопилось слишком много неудач, вызовы сразу отклоняются
Timeouts, retries, and backoff with jitterAWS Amazon Builders' Library. В цепочке из 5 вызовов при 3 повторах на каждом уровне нагрузка на БД вырастает в 243 раза. Повторять нужно только в одном месте и ограничивать повторы через token bucket
CloudWatch metrics for your Application Load BalancerAWS TargetResponseTime (время от выхода запроса из балансировщика до начала ответа целевого сервера), HTTPCode_Target_5XX_Count (число ответов 5xx от целевых серверов), UnHealthyHostCount (число неисправных целевых серверов)
ID in-subservice · Основной ответственный Команда разработки · Разработка сервера · Совместно Команда инфраструктуры · Серверная инфраструктура
Если отказывает сервер, который работает отдельно от игрового (чат, группы, аукцион), перестаёт работать только эта функция.
Почему Выделенный сервер функции тормозит или падает → Следствие Нет ответа только на запросы этой функции → На экране Не работает чат, приглашение в группу остаётся без ответа, бесконечная загрузка торговой площадки (бои идут нормально)
Основной ответственный Команда разработки · Разработка сервера · Совместно Команда инфраструктуры · Серверная инфраструктура
Команда разработки: задачи
Проектировать так, чтобы игра продолжалась при сбое функции, показывать состояние каждой функции, не собирать несколько функций на одном центральном сервере.
Команда инфраструктуры: задачи
Настроить health check и алерты для каждого вспомогательного сервера, резервирование и автоматический перезапуск.
На графике
Массовый обрыв соединений · доля успешных запросов по функциям, число соединений и health check вспомогательных серверов
Где смотреть
Смотреть health check, состояние процессов и число соединений каждого вспомогательного сервера (чат, группы, аукцион), долю успешных запросов и время ответа по функциям. За балансировщиком смотреть UnHealthyHostCount целевой группы
Подтверждает
Health check не проходит или число соединений резко падает только у сервера той функции, на которую жалуются, а тики игрового сервера и бои в норме
Опровергает
Если разом остановились несколько функций, причина скорее в центральном сервере, через который они все идут, или в каскадном отказе
Чем проверить
Инструменты инфраструктуры (игровой код не нужен)
Подробнее
Если группы, гильдии, личные сообщения и переходы между серверами идут через один центральный сервер (сервер мира или сервер-менеджер), то при его замедлении сразу останавливаются несколько функций.
Источников: 3
Bulkhead PatternMicrosoft Azure Если разнести компоненты по изолированным пулам, при отказе одного остальные продолжают работать и сбой не распространяется
ID in-deploy · Основной ответственный Команда разработки · Разработка сервера · Совместно Команда инфраструктуры · Серверная инфраструктура
Если при перезапуске сервера ради обновления не перенести соединения, у всех игроков на этом сервере будет дисконнект, а сохранения перед остановкой и переподключения придут разом.
Почему Серверы по очереди перезапускаются при деплое хотфикса → Следствие Сервер останавливается без переноса соединений на другой, и сохранения всех игроков с этого сервера разом идут в БД → На экране Дисконнект без предупреждения, лавина переподключений
Основной ответственный Команда разработки · Разработка сервера · Совместно Команда инфраструктуры · Серверная инфраструктура
Команда разработки: задачи
Сделать drain (закрыть только новые подключения и ждать, пока уйдут текущие игроки), переносить персонажей на другой сервер, растягивать сохранения перед остановкой, после перезапуска объявлять готовность только после загрузки кэша и прогрева JIT, при горячей перезагрузке заранее читать данные в отдельном потоке и подменять их разом между тиками.
Команда инфраструктуры: задачи
Настроить деплой так, чтобы серверы перезапускались по одному после drain, а перезапущенный сервер получал трафик только после подтверждения готовности (прогрев завершён), заранее объявлять время деплоя.
Цифры для ориентира
Если на одном сервере 5 000 игроков, за несколько секунд до остановки в БД приходят 5 000 сохранений.
На графике
Массовый обрыв соединений · число подключений по серверам, число записей в БД
Где смотреть
Наложить журнал деплой-инструмента (время перезапуска каждого сервера) вертикальными линиями (аннотациями) на графики числа подключений, обрывов, записей в БД и запросов на вход
Подтверждает
Число подключений на серверах по очереди резко падает в моменты перезапуска, прямо перед этим подскакивают записи в БД, сразу после него запросы на вход
Опровергает
Если время обрывов не совпадает с журналом деплоя и перезапусков, причина в падении сервера или в сетевом оборудовании
Чем проверить
Инструменты инфраструктуры (игровой код не нужен)
Подробнее
Первые несколько минут после запуска сервер тоже работает медленно. Кэш пуст, и запросы к БД идут лавиной, а серверы на Java и C# ещё не закончили оптимизацию кода во время выполнения (прогрев JIT), поэтому та же работа занимает больше времени. Перечитывание скриптов и таблиц данных без остановки сервера (горячая перезагрузка) тоже останавливает тик на время чтения и даёт короткий фриз.
Источников: 3
Site Reliability Engineering, Chapter 20: Load Balancing in the DatacenterGoogle Получив SIGTERM, сервер переходит в состояние lame duck: отправляет новые запросы на другие серверы и только завершает текущие. В первые минуты после перезапуска JIT-оптимизация ещё не выполнена и ресурсов уходит больше, поэтому трафик дают только после прогрева
Liveness, Readiness, and Startup ProbesKubernetes Проверка готовности (readiness) не пускает трафик, пока не установлены соединения, не загружены файлы и не прогрет кэш
ID in-autoscale · Основной ответственный Команда инфраструктуры · Серверная инфраструктура · Совместно Команда разработки · Разработка сервера
При наплыве игроков серверы добавляются автоматически, но подготовка занимает несколько минут, и всё это время существующие серверы перегружены.
Почему Резкий рост подключений со стартом события → Следствие Несколько минут, пока новый сервер запустится и будет готов → На экране Первые несколько минут после старта события слоумо и ошибки входа
При наплыве игроков, Сразу после входа или техработ
Ответственные
Основной ответственный Команда инфраструктуры · Серверная инфраструктура · Совместно Команда разработки · Разработка сервера
Команда разработки: задачи
Распределять игроков по каналам (тех, кто уже сидит в переполненном канале, на новый сервер не перенести), сократить время старта и загрузки данных на новом сервере.
Команда инфраструктуры: задачи
Масштабировать заранее до события, держать прогретые резервные серверы, при сокращении выключать сервер только после ухода оставшихся игроков.
Цифры для ориентира
На обнаружение нагрузки уходит от 1 до нескольких минут (метрики усредняются за несколько минут), ещё несколько минут на запуск нового сервера, чтение игровых данных и заполнение кэша.
На графике
Всплеск сразу после входа или техработ · число инстансов, загрузка CPU, очередь на вход
Где смотреть
Наложить журнал автомасштабирования (момент решения о масштабировании и момент ввода нового инстанса в работу) на графики загрузки CPU и числа подключений. В AWS смотреть метрики группы Auto Scaling (видны, только если их включить) GroupDesiredCapacity (целевое число), GroupPendingInstances (готовятся) и GroupInServiceInstances (в работе)
Подтверждает
Несколько минут после всплеска подключений растут только целевое число и число готовящихся инстансов, а CPU существующих серверов держится у лимита и отпускает с того момента, когда растёт число инстансов в работе
Опровергает
Если и после ввода новых инстансов всё тормозит, причина не связана с числом серверов (общий ресурс вроде БД, каскадный отказ)
Чем проверить
Инструменты инфраструктуры (игровой код не нужен)
Подробнее
Автомасштабирование обычно применяют там, где новых игроков достаточно принять на новом сервере: авторизация, шлюзы, данжи. Проблемы бывают и при сокращении. Если ночью, когда игроков мало, выключать лишние серверы, не дожидаясь ухода оставшихся игроков, у этих игроков будет дисконнект.
Amazon CloudWatch metrics for Amazon EC2 Auto ScalingAWS Метрики группы публикуются с шагом 1 минута, только если их включить: GroupDesiredCapacity (сколько инстансов нужно поддерживать), GroupPendingInstances (число инстансов, ещё не введённых в работу), GroupInServiceInstances (число инстансов в работе)
ID in-monitoring · Основной ответственный Команда разработки · Разработка сервера · Совместно Команда инфраструктуры · Серверная инфраструктура
При сбое логи растут лавиной, и серверы, которые отправляют логи синхронно, из-за этого тормозят ещё сильнее.
Почему Из-за ошибок резко растёт объём логов и метрик → Следствие Сборщик логов не успевает, серверы с синхронной отправкой ждут → На экране Во время сбоя микрофризы и фризы усиливаются из-за логов
Основной ответственный Команда разработки · Разработка сервера · Совместно Команда инфраструктуры · Серверная инфраструктура
Команда разработки: задачи
Отправлять асинхронно, делать сэмплирование, при переполнении буфера отбрасывать, одинаковые ошибки отправлять пачкой.
Команда инфраструктуры: задачи
Рассчитать мощность сборщика логов на всплеск объёма при сбое, настроить алерт на отставание сборщика.
На графике
Случайные всплески · объём логов, очередь сборщика логов
Где смотреть
Смотреть число строк и байтов логов в секунду на сервере, очередь и число отброшенных записей у агента сбора логов вместе с временем тика. Если есть остановившиеся потоки, проверить через bcc offcputime -p, не ждут ли они записи или отправки логов
Подтверждает
В моменты всплесков времени тика объём логов в десятки раз выше обычного, а время ожидания игрового потока сосредоточено в стеках вызовов записи и отправки логов
Опровергает
Если объём логов обычный или игровой поток не ждёт на логах, всплеск логов только следствие сбоя, и причину первой ошибки нужно искать отдельно
Чем проверить
Инструменты инфраструктуры (игровой код не нужен)
Источников: 3
Logging in C#Microsoft Методы логирования в .NET синхронные, поэтому при медленном хранилище рекомендуется сначала писать в быстрое хранилище, а потом переносить
Asynchronous loggersApache Software Foundation Асинхронное логирование сглаживает короткие всплески очередью, но если вывод долго остаётся медленным, очередь заполняется, и скорость падает до скорости самого медленного вывода, либо логи отбрасываются по заданной политике (Discard)
ID in-clock-skew · Основной ответственный Команда инфраструктуры · Серверная инфраструктура · Совместно Команда разработки · Разработка сервера
Если часы на серверах немного расходятся, проверки кулдаунов, баффов и начала событий на разных серверах дают разный результат.
Почему На сервере с остановившейся синхронизацией времени часы расходятся с другими серверами на сотни ms или несколько секунд → Следствие Если передавать между серверами абсолютное время (например, момент окончания баффа), проверки расходятся → На экране После перехода пропадает бафф или кулдаун начинается заново
Основной ответственный Команда инфраструктуры · Серверная инфраструктура · Совместно Команда разработки · Разработка сервера
Команда разработки: задачи
Передавать между серверами оставшееся время вместо абсолютного.
Команда инфраструктуры: задачи
Следить за синхронизацией времени (NTP, chrony), настроить алерт на расхождение часов между серверами.
Цифры для ориентира
При нормальной синхронизации времени (NTP, chrony) серверы одного ЦОД обычно расходятся не больше чем на единицы ms. Если синхронизация остановилась или виртуальный сервер долго стоял и потом возобновил работу, расхождение доходит до сотен ms и нескольких секунд.
На графике
Плавный рост · смещение часов по серверам
Где смотреть
Собрать с каждого сервера значения System time (разница между системными часами и временем NTP), Last offset и Ref time (момент, когда последний раз учтено измерение источника времени) из chronyc tracking и сравнить
Подтверждает
Смещение проблемного сервера отличается от остальных на сотни ms и больше или Ref time давно не обновлялось, и расхождения проверок бывают только при переходах на этот сервер и с него
Опровергает
Если смещение на всех серверах в пределах единиц ms, причина в расчёте времени в игре или в ошибке синхронизации часов на клиенте
Чем проверить
Инструменты инфраструктуры (игровой код не нужен)
Подробнее
Разовый скачок часов одного сервера вперёд или назад разобран в слое ОС сервера, в причине «Скачок системных часов (шаговая коррекция NTP)».
chrony – Frequently Asked Questionschrony Дрейф часов обычного компьютера меньше 100 ppm, у виртуальных машин может быть больше. После паузы и возобновления у виртуальной машины время сбивается, и может понадобиться шаговая коррекция
clock_gettime(2) — Linux manual pageLinux man-pages CLOCK_REALTIME может скачкообразно меняться при ручной установке и коррекции NTP, а CLOCK_MONOTONIC такие скачки не затрагивают
chronyc(1)chrony System time (разница между временем NTP и системными часами), Last offset (смещение, оценённое при последней коррекции), Ref time (момент, когда учтено последнее измерение источника времени) из chronyc tracking
ID in-bots · Основной ответственный Команда разработки · Разработка сервера · Совместно Команда инфраструктуры · Сетевая инфраструктура
Боты шлют запросы гораздо чаще людей и съедают производительность сервера.
Почему Массовое подключение ботов, которые без перерыва фармят, ходят и торгуют → Следствие Растут нагрузка на сервер и на БД → На экране Тормозит отдельная локация для фарма или весь сервер (слоумо, задержка ввода)
Основной ответственный Команда разработки · Разработка сервера · Совместно Команда инфраструктуры · Сетевая инфраструктура
Команда разработки: задачи
Обнаруживать ботов, ограничивать частоту запросов по аккаунтам и персонажам.
Команда инфраструктуры: задачи
Ограничить частоту подключений и запросов по IP (с запасом, потому что в компьютерных клубах и мобильных сетях много игроков сидят за одним IP), блокировать диапазоны адресов ботов на файрволе и WAF.
На графике
Высоко только у некоторых · запросы в секунду по аккаунтам и IP
Где смотреть
Смотреть в логах игрового сервера распределение числа запросов в секунду по аккаунтам и персонажам и топ по этому числу. Если метрик в коде нет, смотреть число запросов по IP на файрволе и WAF
Подтверждает
Небольшое число аккаунтов или IP без перерыва шлёт запросы с частотой, недоступной человеку, и после их ограничения нагрузка на сервер заметно падает
Опровергает
Если запросы равномерно распределены по аккаунтам, это обычный рост онлайна (превышение бюджета тика, задержка автомасштабирования)
ID in-external · Основной ответственный Внешние стороны · Внешние стороны · Совместно Команда разработки · Разработка сервера
Если тормозит или останавливается внешний сервис (вход через платформу, оплата, подтверждение личности), всё застревает на этом этапе.
Почему Сбой или задержка внешнего сервиса авторизации или оплаты → Следствие На этом этапе идёт ожидание ответа → На экране Не удаётся войти, платёж не проходит. Те, кто уже в игре, играют нормально
Сразу после входа или техработ, При определённом действии
Ответственные
Основной ответственный Внешние стороны · Внешние стороны · Совместно Команда разработки · Разработка сервера
Команда разработки: задачи
Ставить таймауты на внешние вызовы и показывать понятное сообщение, кэшировать результат авторизации, предусмотреть повтор платежа и порядок компенсации.
Внешние стороны: задачи
Запросить у провайдеров авторизации, оплаты и платформы подтверждение сбоя и восстановление, сообщить игрокам, что сбой на стороне внешнего сервиса.
На графике
Ступенька вверх с определённого момента · время ответа и доля ошибок внешних вызовов, число успешных входов
Где смотреть
Смотреть время ответа, долю ошибок и число таймаутов по каждому внешнему вызову (вход через платформу, оплата, подтверждение личности) и страницу статуса провайдера
Подтверждает
С момента, когда пошли неудачные входы и платежи, ошибки и таймауты одного внешнего вызова поднимаются ступенькой и держатся, а на странице статуса провайдера на то же время отмечен сбой
Опровергает
Если внешние вызовы в норме, а вход не работает, причина в самом сервере авторизации (исчерпание пула потоков, БД) или в очереди подключений ОС (backlog)
Timeouts, retries, and backoff with jitterAWS Amazon Builders' Library. Пока идёт ожидание ответа, заняты ресурсы вроде потоков и соединений, поэтому нужен таймаут, а API с побочными эффектами можно повторять, только если гарантирована идемпотентность
Circuit Breaker PatternMicrosoft Azure Вызов, который скорее всего не пройдёт, отклоняется сразу, без ожидания таймаута, чтобы время ответа оставалось в норме
ID in-region-match · Основной ответственный Команда разработки · Разработка сервера · Совместно Команда разработки · Разработка клиента, Команда инфраструктуры · Сетевая инфраструктура, Внешние стороны · Внешние стороны
Если игрока отправили на сервер в дальнем регионе вместо ближнего, у него одного пинг всегда высокий, даже если с подключением всё в порядке.
Почему Ошибки в данных GeoIP, VPN, выбор сервера для всей группы по среднему пингу участников, правило расширения поиска на дальние регионы при нехватке игроков, выбор по местоположению DNS-резолвера → Следствие Подключение к серверу в регионе за океаном, хотя есть ближний регион → На экране В игре с серверами в нескольких регионах только у одного игрока (или одной группы) постоянно высокий пинг, задержка ввода, откидывание назад и съеденные умения
Основной ответственный Команда разработки · Разработка сервера · Совместно Команда разработки · Разработка клиента, Команда инфраструктуры · Сетевая инфраструктура, Внешние стороны · Внешние стороны
Команда разработки: задачи
Сервер: выбирать регион по пингу до каждого региона, измеренному клиентом, вместо GeoIP, ограничить пинг в правиле расширения на дальние регионы, для группы смотреть средний пинг вместе с самым высоким пингом участника, писать в лог выбранный регион и пинг на тот момент. Клиент: измерять пинг до каждого региона по UDP и отправлять его вместе с запросом на матчмейкинг, показывать на экране регион подключения и пинг, дать возможность выбрать регион вручную.
Команда инфраструктуры: задачи
Если регион выбирается через DNS, проверить, поддерживает ли авторитативный DNS EDNS Client Subnet (если резолвер игрока его не передаёт, выбор идёт по местоположению резолвера), регулярно обновлять базу GeoIP, добавлять к логам подключений серверов в каждом регионе страну и ASN по GeoIP и искать страны и провайдеров, которые попадают в дальний регион.
Внешние стороны: задачи
Посоветовать игроку выключить VPN или игровой ускоритель и переподключиться, игрокам с корпоративным или зарубежным DNS посоветовать перейти на DNS провайдера, запросить у поставщика GeoIP исправление неверного местоположения.
Цифры для ориентира
Если игрока из Сеула отправить вместо Токио в регион на западе США, пинг вырастает примерно с 30 ms до примерно 130 ms. GeoIP верно определяет страну примерно в 99,8% случаев, но с точностью до города даже в США в пределах 50 km попадает только около 66%, а с VPN вместо игрока определяется местоположение VPN-сервера.
На графике
Высоко только у некоторых · RTT (пинг) по игрокам, распределение по выбранным регионам
Где смотреть
Добавить к IP клиентов из журналов подключений серверов каждого региона (логи доступа балансировщика, VPC Flow Logs) страну и ASN по GeoIP и посчитать, к какому региону подключаются игроки из каждой страны и от каждого провайдера. Для одного игрока сравнить регион, к которому он реально подключён, с пингом до ближнего региона (измеряет игрок, или mtr до IP игрока с сервера в том регионе)
Подтверждает
Игроки и страны с высоким RTT подключены к дальнему региону вместо ближнего, а пинг до ближнего региона низкий
Опровергает
Если игрок правильно попал в ближний регион, а пинг всё равно высокий, причина в неоптимальной маршрутизации или в подключении и Wi-Fi игрока
Чем проверить
Инструменты инфраструктуры (игровой код не нужен)
Подробнее
При выборе региона через DNS (DNS с маршрутизацией по географии или задержке) местоположение угадывается по адресу DNS-резолвера, которым пользуется игрок, вместо адреса самого игрока. Если резолвер не поддерживает EDNS Client Subnet (передачу части адреса пользователя), игроки с корпоративным или далёким DNS получают регион по месту резолвера. Система матчмейкинга тоже может оценивать группу по среднему пингу участников или после долгого ожидания расширять порог пинга и отправлять в дальний регион. В AWS GameLift Servers пинг группы по умолчанию тоже считается как среднее, а в качестве примера приводится настройка, которая расширяет лимит пинга с 50 ms до 100 ms и 200 ms. У игрока с включённым VPN дополнительная задержка от промежуточного сервера (причина «Трафик через VPN или игровой ускоритель») может накладываться на выбор дальнего региона. Различают их так: выключить VPN, переподключиться и посмотреть, сменился ли регион. Случай, когда ближнего региона нет вовсе и приходится подключаться к дальнему, разобран в причине «Задержка распространения (физическое расстояние)».
Источников: 8
RFC 7871: Client Subnet in DNS QueriesIETF DNS, который отвечает по-разному в зависимости от местоположения, угадывает местоположение по адресу резолвера, отправившего запрос, и если пользователь работает через центральный резолвер далеко от себя, ответ получается неподходящим. EDNS Client Subnet (необязательное расширение) передаёт часть адреса пользователя
How Amazon Route 53 uses EDNS0 to estimate the location of a userAWS Если резолвер не поддерживает edns-client-subnet, местоположение пользователя угадывается по адресу резолвера, и ответ даётся по месту резолвера (общее для маршрутизации по географии и по задержке)
Geolocation accuracyMaxMind На уровне страны около 99,8%, на уровне города в США (в пределах 50 km) около 66%. С VPN определяется местоположение VPN-сервера вместо конечного пользователя, а IP мобильных сетей используются на большой территории, поэтому точное место не определить. Базу нужно постоянно обновлять, можно запросить исправление
FlexMatch rule typesAWS Правило задержки (maxLatency) смотрит задержку игрока до каждой локации, для группы по умолчанию берётся среднее по участникам (partyAggregation avg), очередь может разместить игру и в регионе, который не проходит правило задержки
Create a player latency policyAWS Игра размещается в локации с наименьшей средней задержкой для всех игроков, но игроки с экстремальной задержкой тоже попадают в игру. Пример политики, которая расширяет лимит пинга с 50 ms до 100 ms и 200 ms
Amazon GameLift Servers UDP ping beaconsAWS Игровой клиент измеряет задержку через UDP-эндпоинты в каждой локации хостинга и использует её для размещения и матчмейкинга. Это ближе к реальному игровому трафику, чем ICMP-пинг
ID in-cert · Основной ответственный Команда инфраструктуры · Сетевая инфраструктура · Совместно Команда инфраструктуры · Серверная инфраструктура, Команда разработки · Разработка клиента
Если у сервера авторизации, API или патчей истекает сертификат или пропадает промежуточный сертификат, с этого момента у новых подключений клиентов не устанавливается TLS-соединение.
Почему Срок действия сертификата истёк, сервер отдаёт цепочку без промежуточного сертификата, или на устройстве игрока неверные дата и время → Следствие Клиент не проходит проверку сертификата и разрывает TLS-соединение → На экране Ошибка входа или бесконечная загрузка на этапе входа или патча, не работают только функции через HTTPS, например магазин. У тех, кто уже был в игре, обычно всё в порядке
Сразу после входа или техработ, При определённом действии
Ответственные
Основной ответственный Команда инфраструктуры · Сетевая инфраструктура · Совместно Команда инфраструктуры · Серверная инфраструктура, Команда разработки · Разработка клиента
Команда разработки: задачи
Записывать ошибку сертификата отдельным кодом, отличным от других сбоев подключения, и показывать сообщение, при ошибке даты советовать включить автоматическую установку даты и времени на устройстве, при закреплении сертификата (pinning) добавить резервный ключ и согласовать график смены сертификатов с командой инфраструктуры.
Команда инфраструктуры: задачи
Сеть: если TLS терминируется на балансировщике или CDN, следить за автообновлением управляемых сертификатов и настроить алерт на число оставшихся дней (в ACM это DaysToExpiry), сохранять DNS-записи для проверки. Серверы и ОС: если TLS терминируется на сервере, автоматизировать обновление и перечитывание конфигурации после него, настроить полную цепочку с промежуточным сертификатом, регулярно проверять снаружи оставшийся срок действия для каждого адреса авторизации, API и патчей и слать алерт.
Цифры для ориентира
Сертификаты Let’s Encrypt выдаются на 90 дней, и обновлять их рекомендуется каждые 60 дней, а AWS Certificate Manager проверяет сертификаты, подтверждённые через DNS, за 45 дней до истечения и обновляет их автоматически. Если автообновление тихо сломалось, ровно в момент истечения разом перестают проходить все новые подключения.
На графике
Массовый обрыв соединений · число успешных входов, число ошибок TLS-рукопожатия
Где смотреть
Посмотреть через openssl s_client -connect HOST:443 -showcerts, какие сертификаты сервер реально отдаёт, и проверить срок действия каждого (notAfter) через openssl x509 -noout -enddate. Если TLS терминируется на балансировщике, смотреть число ошибок согласования TLS (в AWS ALB и NLB это ClientTLSNegotiationErrorCount) и число успешных входов
Подтверждает
Срок действия истёк или в отдаваемом списке нет промежуточного сертификата, а рост ошибок начался в момент истечения или замены сертификата
Опровергает
Если список сертификатов и сроки в порядке, а ошибка только у части игроков, проверить дату и время на их устройствах или список корневых сертификатов в старой ОС
Чем проверить
Инструменты инфраструктуры (игровой код не нужен)
Подробнее
Конфигурация без промежуточного сертификата может выглядеть рабочей, если открыть адрес в браузере на ПК. Браузер помнит промежуточные сертификаты, полученные с других сайтов, и подставляет недостающие, а клиент без такой памяти, например Android-приложение, получает ошибку. Сроки действия тоже сокращаются. Let’s Encrypt планирует уменьшить стандартный срок до 64 дней в 2027 году и до 45 дней в 2028 году, поэтому при жёстко заданном обновлении раз в 60 дней у 64-дневного сертификата запас всего четыре дня, а 45-дневный успеет истечь. AWS Certificate Manager к тому же не обновляет автоматически импортированные (import) сертификаты, а если удалить DNS-запись для проверки, обновление не пройдёт. Внешне отказ входа похож на причину «Сбои и задержки DNS», но при проблеме с сертификатом адрес сервера находится, а сбой происходит на TLS-рукопожатии, и начало совпадает со временем истечения или замены сертификата.
FAQLet's Encrypt Стандартный срок действия сертификата 90 дней, рекомендуется обновлять каждые 60 дней
Decreasing Certificate Lifetimes to 45 DaysLet's Encrypt Стандартный срок действия сокращается до 64 дней с февраля 2027 года и до 45 дней с февраля 2028 года. Обновления с фиксированным интервалом 60 дней станет недостаточно, рекомендуется обновлять примерно на 2/3 срока действия
Renewal for domains validated by DNSAWS За 45 дней до истечения проверяется, используется ли сертификат в сервисах AWS и есть ли CNAME-запись для проверки, и сертификат обновляется автоматически. Если проверить не удалось, уведомления приходят за 30, 15, 7, 3 и 1 день до истечения
Supported CloudWatch metricsAWS DaysToExpiry: число дней до истечения сертификата, публикуется два раза в сутки, пока сертификат не истёк
Security with network protocolsAndroid (Google) Если сервер отдаёт цепочку без промежуточного сертификата, Android-приложение получает SSLHandshakeException, а браузер на ПК может подставить сохранённый промежуточный сертификат и обойтись без ошибки. Цепочку, которую отдаёт сервер, проверяют через openssl s_client
Network security configurationAndroid (Google) При закреплении сертификата нужно добавить резервный ключ на случай смены ключа или CA, иначе соединения не будут проходить до обновления приложения
openssl-s_clientOpenSSL -showcerts: показывает сертификаты в том порядке, в каком их отправил сервер (это не проверенная цепочка)
openssl-x509OpenSSL -enddate: выводит дату истечения сертификата (notAfter), -checkend: проверяет, истечёт ли сертификат в течение заданного числа секунд
CloudWatch metrics for your Application Load BalancerAWS ClientTLSNegotiationErrorCount: число соединений, для которых не удалось установить TLS-сессию, в том числе когда клиент не прошёл проверку сертификата сервера и разорвал соединение
ID in-login-queue · Основной ответственный Команда разработки · Разработка сервера · Совместно Команда разработки · Разработка клиента, Команда инфраструктуры · Серверная инфраструктура
Когда сразу после релиза или техработ идёт наплыв подключений, очередь на вход упирается в лимит и перестаёт принимать новых игроков, а тот, кто уже ждал, при коротком обрыве теряет место и снова оказывается в конце очереди.
Почему Желающих войти больше, чем сервер авторизации может принять за раз, поэтому есть очередь, а когда она слишком длинная, сервер ради самозащиты перестаёт ставить в неё новых игроков → Следствие Чем длиннее очередь, тем дольше ожидание, и за это время достаточно короткого обрыва Wi-Fi или мобильной сети, чтобы потерять место → На экране Ошибка входа / бесконечная загрузка, игра закрывается с ошибкой во время ожидания, ждать приходится снова с конца очереди
Основной ответственный Команда разработки · Разработка сервера · Совместно Команда разработки · Разработка клиента, Команда инфраструктуры · Серверная инфраструктура
Команда разработки: задачи
Сервер: подогнать лимит очереди под реальную производительность сервера авторизации, на какое-то время сохранять место игрока, у которого оборвалось соединение в очереди (окно переподключения), показывать номер в очереди и ожидаемое время, писать в метрики длину очереди, число отказов и число обрывов в очереди. Клиент: при обрыве в очереди автоматически переподключаться на то же место, не закрывая игру, разносить повторные попытки во времени экспоненциальной задержкой (backoff) со случайным разбросом (джиттером).
Команда инфраструктуры: задачи
Серверы и ОС: до релиза измерить нагрузочным тестом предел серверов авторизации и лобби, к релизу подготовить резервные машины, которые можно быстро подключить, смотреть метрики очереди на одном графике с числом попыток подключения.
Цифры для ориентира
При выходе дополнения FINAL FANTASY XIV в 2021 году, когда в очереди одного логического дата-центра было больше 17 000 человек, новые места не выдавались (Error 2002). Если соединение обрывалось во время ожидания, лобби-сервер ждал от нескольких десятков секунд до 1 минуты, и игрок, успевший переподключиться, продолжал с того же места в очереди.
На графике
Упор в лимит (плато) · длина очереди на вход, число отказов из-за лимита, число обрывов во время ожидания
Где смотреть
Вывести на один график с числом попыток подключения длину очереди, среднее время ожидания, число отказов из-за лимита и число обрывов во время ожидания по данным серверов авторизации и лобби
Подтверждает
Сразу после релиза или техработ длина очереди упирается в лимит и выходит на плато, в это время растёт число отказов, а обрывы во время ожидания приходятся в основном на игроков с Wi-Fi и мобильной сетью
Опровергает
Если очередь короткая, а вход медленный, причина в БД (db-login-storm) или в очереди подключений ОС (so-backlog)
Чем проверить
Нужны логи и метрики игрового сервера или клиента
Подробнее
Замедление БД из-за наплыва входов разобрано в причине «Наплыв входов и запросы N+1», переполнение очереди подключений в ОС в причине «Переполнение очереди подключений (backlog)». Здесь речь о проектировании очереди на вход, которую игра вводит намеренно. Лимит очереди защищает сервер авторизации, и убрать его нельзя: чтобы сервер продолжал обрабатывать посильные запросы, лишние нужно отклонять как можно раньше. Поэтому важно уменьшить ущерб, который отказы и обрывы наносят игрокам, ведь чем длиннее очередь, тем больше ошибок достаётся игрокам с нестабильным подключением через Wi-Fi или мобильную сеть.
Response to Congestion (as of Dec. 11)Square Enix Когда в очереди логического дата-центра больше 17 000 человек, новые места не выдаются, чтобы сервер авторизации не упал (Error 2002). При обрыве во время ожидания лобби-сервер ждёт от десятков секунд до 1 минуты: успевший переподключиться игрок продолжает с того же места, остальные попадают в конец очереди
Using load shedding to avoid overloadAmazon Builders' Library Отсечение нагрузки (load shedding): лишние запросы отклоняются рано, чтобы сервер продолжал обрабатывать те, с которыми справляется
ID sy-request-response · Основной ответственный Команда разработки · Разработка клиента · Совместно Команда разработки · Разработка сервера
После нажатия кнопки нет ни анимации, ни звука, пока не придёт ответ сервера. Скорость отклика становится равна пингу.
Почему Умения, перемещение и подбор предметов проигрываются только после подтверждения сервера → Следствие С момента нажатия никакой реакции в течение пути туда и обратно плюс ожидания тика → На экране При пинге 150 ms каждое действие запаздывает примерно на 0,2 с
Основной ответственный Команда разработки · Разработка клиента · Совместно Команда разработки · Разработка сервера
Команда разработки: задачи
Клиент: анимацию, звук и эффекты запускать сразу при нажатии (опережающий фидбек), результат (урон, награду) показывать только после подтверждения сервера, перемещение и базовую атаку предсказывать и применять сразу, а получив от сервера коррекцию позиции, повторно применять от этой позиции ещё не подтверждённый ввод. Сервер: самому рассчитывать перемещение по полученному вводу и отправлять коррекцию, только если расхождение с позицией, предсказанной клиентом, превышает порог.
Цифры для ориентира
Время отклика ≈ пинг + половина интервала тика + один кадр. На 20-тиковом сервере при пинге 150 ms около 190 ms.
На графике
Высоко с самого начала · время от ввода до начала анимации, RTT (пинг)
Где смотреть
Писать в лог клиента в development-сборке время нажатия кнопки, начала первой анимации и звука и прихода ответа сервера и смотреть рядом с внутриигровым RTT. Менять пинг, добавляя задержку через эмуляцию сети в движке (Unreal NetEmulation.PktLag) или через tc netem в Linux на тестовом сервере, и замерять
Подтверждает
Анимация всегда начинается в момент прихода ответа сервера, время от ввода до анимации равно RTT плюс ожидание тика и растёт ровно на добавленную задержку
Опровергает
Если анимация начинается сразу при нажатии, а запаздывает только результат вроде цифр урона, архитектура нормальная. Если даже при низком пинге задержка больше интервала тика, это двойное ожидание тика или проблема с кадрами на клиенте
Чем проверить
Нужны логи и метрики игрового сервера или клиента
Подробнее
Для игр, где быстрая реакция не нужна (пошаговые, карточные, idle-игры), эта модель самая простая и надёжная. Проблема возникает, когда в игре с управлением в реальном времени так же сделаны перемещение и даже базовая атака.
Using Gameplay Abilities in Unreal EngineEpic Games Local Predicted выполняется сразу при нажатии, а окончательно решает сервер. В Server Initiated предсказания нет, и тот, кто применяет способность, видит задержку
Using Network Emulation in Unreal EngineEpic Games Тестирование с минимальной и максимальной задержкой и долей потерь пакетов на сервере и клиенте, в консоли задаётся, например, как NetEmulation.PktLag
tc-netem(8) — Linux manual pageiproute2 Инструмент для тестирования, который добавляет к исходящим пакетам задержку и джиттер (delay TIME JITTER) и потери (loss random PERCENT), имитируя реальную сеть
ID sy-chatty · Основной ответственный Команда разработки · Разработка сервера · Совместно Команда разработки · Разработка клиента
Если для одного действия нужно несколько обменов с сервером по очереди, пинг умножается на их число.
Почему Открытие магазина → запрос списка → проверка цены → покупка → обновление инвентаря, каждое отдельным запросом → Следствие Следующий запрос уходит только после ответа на предыдущий → На экране При пинге 150 ms одна покупка занимает почти 1 с. Загрузки подозрительно долгие
При определённом действии, Сразу после входа или техработ
Ответственные
Основной ответственный Команда разработки · Разработка сервера · Совместно Команда разработки · Разработка клиента
Команда разработки: задачи
Сервер: изменить протокол так, чтобы несколько шагов шли одним запросом и ответом (например, класть обновлённый инвентарь в ответ на покупку). Клиент: заранее загружать нужные данные, делать UI, который не ждёт результата.
Цифры для ориентира
Время ≈ число обменов × (пинг + обработка на сервере + ожидание тика). При 5 обменах и пинге 150 ms около 0,85–1 с.
На графике
Высоко с самого начала · время выполнения по функциям, число обменов на одно действие
Где смотреть
В захвате пакетов на стороне сервера (Wireshark) посчитать, сколько раз запросы и ответы сменяют друг друга за одно действие тестового аккаунта (покупка в магазине, вход) и с какими интервалами. Если есть лог запросов на сервере, сгруппировать по ID сессии и смотреть число запросов и время прихода и ответа каждого
Подтверждает
Одно действие состоит из нескольких последовательных запросов, каждый ждёт предыдущего ответа, время выполнения примерно равно числу обменов × RTT, и чем выше пинг в регионе игрока, тем пропорционально медленнее та же функция
Опровергает
Если обменов один-два, а долго идёт один ответ, причина в обработке на сервере или в БД. Если все игроки тормозят одинаково независимо от пинга, смотреть нагрузку на сервер
Чем проверить
Инструменты инфраструктуры (игровой код не нужен)
Источников: 1
Chatty I/O antipatternMicrosoft Azure Множество мелких запросов ввода-вывода накапливает задержку и сильно ухудшает отзывчивость. Рекомендуется объединять их в более крупные и редкие запросы
ID sy-no-queue · Основной ответственный Команда разработки · Разработка клиента · Совместно Команда разработки · Разработка сервера
Если следующее умение можно нажать только после подтверждения сервера, что предыдущее закончилось, в каждую связку вклинивается путь туда и обратно.
Почему Ввод следующего умения принимается только «после подтверждения предыдущего» → Следствие Между умениями появляется пустой промежуток длиной в пинг → На экране Между приёмами связки появляются паузы, и чем выше пинг, тем ниже DPS
Основной ответственный Команда разработки · Разработка клиента · Совместно Команда разработки · Разработка сервера
Команда разработки: задачи
Клиент: ввести окно буфера ввода, чтобы нажатие в течение некоторого времени до конца кулдауна (например, 0,3–0,4 с) принималось и сразу отправлялось на сервер. Сервер: принимать ввод, пришедший чуть раньше, и выполнять его в момент окончания кулдауна.
Цифры для ориентира
В связке с кулдауном 1 с при пинге 150 ms между умениями пустует 0,15 с и больше, и за то же время применяется больше чем на 13% меньше умений.
На графике
Высоко с самого начала · пустой промежуток между умениями, RTT (пинг)
Где смотреть
Писать в лог сервера для каждого персонажа время окончания кулдауна, время прихода запроса на следующее умение и время его выполнения, сравнивать пустой промежуток между ними с RTT игрока
Подтверждает
От окончания кулдауна до выполнения следующего умения всегда проходит примерно RTT, и чем выше пинг игрока, тем длиннее промежуток и тем меньше умений применено за то же время
Опровергает
Если промежуток постоянный и не зависит от пинга, это заложено в дизайне (глобальный кулдаун или длина анимации). Если промежуток лишь иногда резко растёт, смотреть джиттер и потери или превышение бюджета тика
Чем проверить
Нужны логи и метрики игрового сервера или клиента
Подробнее
Например, в World of Warcraft есть окно буфера ввода, и игрок может настроить его длину. Если окно длиннее пути туда и обратно, пинг между приёмами связки почти не заметен.
ID sy-short-window · Основной ответственный Команда разработки · Разработка сервера · Совместно Команда разработки · Разработка клиента, Команда инфраструктуры · Серверная инфраструктура
Если на реакцию (уклонение, парирование, блок) отведено мало времени, пинг съедает это время, и появляются атаки, от которых невозможно уйти.
Почему Короткие окна реакции, например предупреждение об атаке босса за 0,5 с или окно парирования 0,2 с → Следствие Предупреждение игрок видит поздно (задержка на пути к нему + интерполяция), и его ввод тоже приходит поздно (задержка на пути к серверу + ожидание тика) → На экране Точно увернулся, а удар прошёл, парирование «съело»
Основной ответственный Команда разработки · Разработка сервера · Совместно Команда разработки · Разработка клиента, Команда инфраструктуры · Серверная инфраструктура
Команда разработки: задачи
Сервер: планировать предупреждение об атаке по серверному времени и отправлять его заранее, расширять окно реакции на величину пинга (компенсация задержки). Клиент: проигрывать полученное предупреждение в запланированный момент по серверному времени.
Команда инфраструктуры: задачи
Размещать серверы ближе к регионам, где много игроков (региональные серверы), чтобы уменьшить сам пинг.
Цифры для ориентира
При пинге 150 ms и интерполяции 100 ms предупреждение появляется на экране игрока примерно через 0,18 с, а ввод игрока доходит до сервера примерно за 0,1 с. Если добавить 0,25 с на реакцию человека, увернуться от атаки с предупреждением за 0,5 с почти невозможно.
На графике
Высоко только у некоторых · доля неудачных уклонений и парирований (по диапазонам пинга)
Где смотреть
Писать в лог сервера время начала и конца окна реакции, время прихода ввода игрока на сервер и RTT этого игрока, смотреть долю неудач в разбивке по диапазонам пинга (например, с шагом 50 ms)
Подтверждает
Чем выше диапазон пинга, тем заметно выше доля неудач, а неудачный ввод приходит вскоре после закрытия окна (в пределах суммы RTT и времени интерполяции)
Опровергает
Если доля неудач примерно одинакова во всех диапазонах пинга, дело в сложности паттерна. Если ввод пришёл внутри окна, а засчитан как неудача, смотреть код проверки или серверную валидацию
ID sy-no-lagcomp · Основной ответственный Команда разработки · Разработка сервера · Совместно Команда разработки · Разработка клиента
Если сервер проверяет попадание только по «текущей позиции на сервере», результат расходится с тем, что игрок видел на своём экране.
Почему Противник на экране игрока стоит там, где был примерно 0,2 с назад (при пинге 150 ms и интерполяции 100 ms) → Следствие Сервер проверяет по текущей позиции, и там, куда целился игрок, цели уже нет → На экране Точно попал, а промах. По движущейся цели приходится стрелять с упреждением
Основной ответственный Команда разработки · Разработка сервера · Совместно Команда разработки · Разработка клиента
Команда разработки: задачи
Сервер: проверять попадание, отмотав время назад к моменту, который видел атакующий (компенсация задержки), или перейти на выбор цели (таб-таргет). Клиент: при атаке отправлять момент, который видел игрок (серверное время, на котором идёт интерполяция).
На графике
Высоко только у некоторых · точность по движущимся целям (по диапазонам пинга)
Где смотреть
Писать в лог проверок на сервере вместе время атаки, позицию цели на экране атакующего (значение от клиента), позицию цели на сервере, по которой шла проверка, и RTT атакующего. Если в development-сборке рисовать поверх экрана клиента позицию, которую сервер использовал для проверки, расхождение видно сразу
Подтверждает
В промахах разница двух позиций примерно равна скорости цели × (RTT атакующего + время интерполяции), и с ростом пинга падает точность только по движущимся целям
Опровергает
Если промахи бывают и по неподвижным целям, проблема в хитбоксах или проверке столкновений. Если отмотка времени есть, а расхождение остаётся, проверить, правильно ли клиент сообщает серверу время интерполяции
Peeking into VALORANT's NetcodeRiot Games Сервер отматывает время назад к состоянию игры, которое видел игрок в момент выстрела, и проверяет попадание. Клиент вместе с выстрелом отправляет время симуляции, которое он видел
ID sy-lagcomp-overreach · Основной ответственный Команда разработки · Разработка сервера
Если отматывать время слишком далеко в пользу атакующего, в того, кто уже спрятался, всё равно попадают.
Почему Ради атакующего с высоким пингом сервер проверяет попадание с большой отмоткой назад → Следствие На экране того, в кого попали, он уже был в укрытии → На экране «В меня попали, когда я уже был за стеной», преимущество у игроков с высоким пингом
Основной ответственный Команда разработки · Разработка сервера
Команда разработки: задачи
Ограничить глубину отмотки (например, 200–250 ms), атакующему с более высоким пингом отматывать только до лимита, а остальное он компенсирует упреждением сам.
На графике
Высоко только у некоторых · глубина отмотки для каждого попадания (по пингу атакующего)
Где смотреть
Писать в лог проверок на сервере для каждого попадания глубину отмотки, RTT атакующего и серверное время, когда цель зашла в укрытие. В development-сборке рисовать на экране отмотанные хитбоксы (в движке Source это sv_showlagcompensation)
Подтверждает
Попадания из жалоб «попали, когда я уже был за стеной» приходятся на атакующих с большой глубиной отмотки, а глубина отмотки растёт вслед за пингом атакующего без всякого лимита
Опровергает
Если попадания по игроку за стеной бывают и при малой глубине отмотки, проблема в хитбоксах или проверке столкновений. Если высокий пинг у того, в кого попали, его перемещение просто поздно дошло до сервера
Чем проверить
Нужны логи и метрики игрового сервера или клиента
Подробнее
Проверка попадания с отмоткой работает по принципу «приоритет стреляющего». Предложено и исключение «приоритет цели»: если цель на своём экране уже зашла в безопасное место, отмотка не выполняется.
Источников: 3
Peeking into VALORANT's NetcodeRiot Games Без лимита отмотки игрок с задержкой 500 ms может попасть по цели через 0,5 с после того, как она ушла в укрытие, поэтому лимит нужен
Source SDK 2013: player_lagcompensation.cppValve Лимит отмотки в движке Source sv_maxunlag по умолчанию 1 с (максимум 1 с), sv_showlagcompensation показывает на экране отмотанные хитбоксы
ID sy-client-auth · Основной ответственный Команда разработки · Разработка сервера · Совместно Команда разработки · Разработка клиента
Если каждый клиент сам определяет свои результаты, на экране игрока всё плавно, но результаты расходятся с экранами других, и игра уязвима для читов.
Почему Позицию и попадания определяет клиент, а сервер только пересылает → Следствие Два игрока утверждают, что каждый попал первым, а сервер не может это проверить → На экране Противник телепортируется или проходит сквозь стены, «я попал, а урона нет»
Основной ответственный Команда разработки · Разработка сервера · Совместно Команда разработки · Разработка клиента
Команда разработки: задачи
Сервер: важные результаты (попадания и т. п.) проверять самому, перемещение проверять по скорости и расстоянию. Клиент: получив от сервера отказ или коррекцию, возвращать состояние к значению сервера.
На графике
Высоко с самого начала · число отчётов с невозможной скоростью перемещения и противоречащих друг другу попаданий
Где смотреть
Записывать на сервере позиции и попадания в том виде, в каком их прислал клиент, по последовательным отчётам о позиции считать скорость перемещения и подсчитывать отчёты с превышением максимальной скорости и случаи, когда два игрока сообщают, что каждый попал первым
Подтверждает
Сервер пересылает отчёты другим клиентам без проверки, а невозможные скорости и противоречащие попадания появляются постоянно, независимо от патча и региона
Опровергает
Если сервер сам рассчитывает или проверяет результаты, причина не эта. Тогда при телепортации смотреть потери пакетов или буфер интерполяции
ID sy-lockstep · Основной ответственный Команда разработки · Разработка сервера · Совместно Команда разработки · Разработка клиента
В схеме, где все вместе рассчитывают один и тот же ход, при опоздании ввода одного игрока ждут все.
Почему Каждый ход можно рассчитать, только собрав ввод всех игроков → Следствие Ввод одного игрока приходит поздно из-за джиттера или потерь → На экране У всех одновременно замирание, в тяжёлых случаях окно «Ожидание игрока»
Основной ответственный Команда разработки · Разработка сервера · Совместно Команда разработки · Разработка клиента
Команда разработки: задачи
Сервер: автоматически подстраивать задержку применения ввода под пинг, ненадолго исключать только опаздывающего игрока, чтобы остальные продолжали без ожидания. Клиент: соблюдать заданную задержку применения ввода; в P2P без промежуточного сервера подстройку этой задержки и обработку опаздывающих тоже берёт на себя клиент-хост.
Цифры для ориентира
Если задержку применения ввода (input delay) сделать меньше, чем «время доставки ввода сопернику + джиттер», фризы станут частыми. Время доставки при прямом обмене равно половине пинга, а через промежуточный сервер примерно половине суммы пингов двух игроков.
На графике
Случайные всплески · время ожидания хода, задержка прихода ввода по игрокам
Где смотреть
Записывать для каждого хода время прихода ввода от каждого игрока и время, которое ход простоял в ожидании, и смотреть, чьего ввода ждал остановившийся ход. Если есть промежуточный сервер, это видно и по интервалам прихода пакетов ввода от каждого игрока в захвате пакетов на сервере
Подтверждает
В каждом остановившемся ходе ввод одного и того же игрока пришёл позже, чем позволяет задержка применения ввода, и в это время у него подскакивают джиттер и потери
Опровергает
Если весь ввод пришёл вовремя, а игра всё равно стоит, проблема во времени расчёта на самом медленном ПК или в обработке на сервере. Если фризов нет, а расходятся только результаты на двух экранах, это рассинхронизация результатов расчёта (desync), и нужно смотреть расхождение расчёта пути при синхронизации команд
Чем проверить
Нужны логи и метрики игрового сервера или клиента
Источников: 3
Deterministic LockstepGaffer On Games Кадр n можно рассчитать, только когда пришёл весь ввод, поэтому при опоздании игра ждёт. Если буфер задержки воспроизведения, поглощающий джиттер, мал, бывают замирания
ID sy-rollback · Основной ответственный Команда разработки · Разработка клиента
Игра предсказывает ввод соперника и показывает результат заранее, а при ошибке отматывает назад и пересчитывает. Чем больше пинг, тем глубже отмотка.
Почему Соперник сменил ввод (не так, как предсказано) → Следствие Реальный ввод приходит с опозданием на половину пинга, и на столько же приходится отматывать назад и пересчитывать → На экране Движение соперника проскакивает несколько кадров или внезапно меняется
Основной ответственный Команда разработки · Разработка клиента
Команда разработки: задачи
Добавить задержку применения ввода (input delay) в 1–3 кадра, чтобы уменьшить глубину отмотки, ограничить глубину отмотки.
Цифры для ориентира
При пинге 100 ms (50 ms в одну сторону) и 60 fps отматывается около 3 кадров. Если задержать применение ввода на 2 кадра, отмотка сократится до 1 кадра.
На графике
Случайные всплески · число отмотанных кадров, RTT (пинг)
Где смотреть
Записывать на клиенте при каждой отмотке число отмотанных кадров, RTT в этот момент, настройку задержки применения ввода и время, ушедшее на отмотку и пересчёт
Подтверждает
В моменты, когда движение соперника дёрнулось, число отмотанных кадров большое, средняя глубина отмотки примерно равна (задержка в одну сторону − задержка применения ввода) ÷ время кадра и растёт с пингом
Опровергает
Если отмотка небольшая, а микрофризы есть, это проблема производительности: пересчёт не укладывается в один кадр. Если и после отмотки результаты на двух экранах расходятся, это рассинхронизация (desync)
Чем проверить
Нужны логи и метрики игрового сервера или клиента
Источников: 2
GGPO Rollback Networking SDKGGPO Ввод соперника предсказывается, игра идёт вперёд, а если реальный ввод другой, всё пересчитывается от момента расхождения до текущего
ID sy-no-timestamp · Основной ответственный Команда разработки · Разработка клиента · Совместно Команда разработки · Разработка сервера
Если сервер не прикрепляет к событиям время, когда они произошли, а клиент проигрывает их сразу при получении, сетевой джиттер напрямую сбивает тайминг анимаций.
Почему События «начало атаки», «запуск эффекта» выполняются сразу по приходу → Следствие У каждого пакета своё время доставки, и интервалы скачут → На экране Серия атак то ускоряется, то замедляется, тайминг паттернов босса каждый раз разный
Основной ответственный Команда разработки · Разработка клиента · Совместно Команда разработки · Разработка сервера
Команда разработки: задачи
Клиент: проигрывать по времени, прикреплённому к событию (планирование событий, буфер интерполяции). Сервер: прикреплять к событиям время, когда они произошли (серверное время).
На графике
Случайные всплески · интервалы воспроизведения событий, интервалы прихода пакетов
Где смотреть
Сопоставить по номеру события время из лога сервера с временем прихода и воспроизведения из лога клиента и сравнить интервалы. В development-сборке воспроизвести, добавив джиттер (значение джиттера в tc netem, минимальная и максимальная задержка в эмуляции сети Unreal)
Подтверждает
На сервере события происходят с равными интервалами, а интервалы воспроизведения повторяют неравномерные интервалы прихода
Опровергает
Если пакеты приходят ровно, а воспроизведение скачет, проблема с кадрами на клиенте (всплески времени кадра). Если неравномерны уже интервалы на сервере, это превышение бюджета тика
Snapshot InterpolationGaffer On Games Если рисовать снапшоты сразу по приходу, из-за джиттера картинка дёргается, а если ненадолго накапливать их в буфере интерполяции, движение плавное
tc-netem(8) — Linux manual pageiproute2 Инструмент для тестирования, который добавляет к исходящим пакетам задержку и джиттер (delay TIME JITTER) и потери (loss random PERCENT), имитируя реальную сеть
Using Network Emulation in Unreal EngineEpic Games Тестирование с минимальной и максимальной задержкой и долей потерь пакетов на сервере и клиенте, в консоли задаётся, например, как NetEmulation.PktLag
ID sy-double-tick · Основной ответственный Команда разработки · Разработка сервера
Если запросы копятся до следующего тика и только тогда обрабатываются, а результат уходит ещё через тик, интервал тика добавляется дважды.
Почему Полученный запрос обрабатывается в следующем тике → Следствие Результат тоже копится и уходит в следующем тике отправки → На экране Сетевой пинг низкий, а отклик стабильно запаздывает примерно на 1,5 интервала тика. На 10-тиковом сервере в среднем 0,15 с, в худшем случае 0,2 с
Основной ответственный Команда разработки · Разработка сервера
Команда разработки: задачи
Отправлять ответ сразу в тике обработки, поднять тикрейт, важные ответы отправлять немедленно.
Цифры для ориентира
На 10-тиковом сервере один тик длится 100 ms, поэтому одно только ожидание тиков добавляет в среднем 150 ms, в худшем случае 200 ms. При одном ожидании в среднем 50 ms.
На графике
Высоко с самого начала · время от прихода запроса до отправки ответа
Где смотреть
В захвате пакетов на стороне сервера измерить интервал между приходом пакета запроса и уходом пакета ответа, когда тестовый аккаунт несколько раз выполняет одно и то же действие (например, использует предмет). Если есть лог сервера, смотреть время прихода запроса, номер тика обработки и время отправки ответа
Подтверждает
Время внутри сервера в среднем около 1,5 интервала тика, максимум около 2 интервалов, и от RTT оно не зависит
Опровергает
Если время внутри сервера около половины интервала тика, ожидание тика только одно. Если оно скачет и бывает дольше интервала тика, смотреть превышение бюджета тика
Чем проверить
Инструменты инфраструктуры (игровой код не нужен)
Источников: 3
Peeking into VALORANT's NetcodeRiot Games Пришедший ввод ждёт границы тика до одного тика, и ещё один кадр уходит на применение и отправку. Чем выше тикрейт, тем меньше задержка
ID sy-strict-check · Основной ответственный Команда разработки · Разработка сервера
Если сервер слишком строго проверяет скорость перемещения, кулдауны и дальность, он отклоняет даже нормальный ввод, пришедший пачкой из-за джиттера.
Почему Жёсткие критерии вроде «расстояние, доступное за один тик» или «допуск по кулдауну 0 ms» → Следствие Если из-за джиттера две команды приходят в одном тике, это засчитывается как нарушение правил → На экране Откидывание назад, умение отклоняется, хотя кулдаун прошёл
Основной ответственный Команда разработки · Разработка сервера
Команда разработки: задачи
Проверять по накопленному лимиту (token bucket), давать запас на пинг и джиттер.
На графике
Случайные всплески · число отказов серверной проверки и коррекций позиции
Где смотреть
Писать в лог сервера для каждого отказа проверки и коррекции позиции причину, число команд этого игрока, пришедших в том тике, и интервал прихода после предыдущей команды
Подтверждает
Отказы и коррекции приходятся на моменты, когда в одном тике пришли 2 команды и больше, а суммарное перемещение и число применений за несколько секунд укладываются в правила
Опровергает
Если и в сумме за несколько секунд правила превышены, возможно, это реальное превышение скорости или чит. Если отказы приходятся на одного провайдера и вечернее время, смотреть причину «Ложные срабатывания проверок у абонентов одного провайдера»
Чем проверить
Нужны логи и метрики игрового сервера или клиента
Источников: 2
Source SDK 2013: player.cppValve Бюджет обработки команд, который копится каждый тик (максимум sv_maxusrcmdprocessticks, 24 тика), позволяет принять команды, пришедшие пачкой. В комментарии разработчиков сказано, что при более строгом ограничении микрофризы получали и обычные игроки
ID sy-host · Основной ответственный Команда разработки · Разработка сервера · Совместно Команда разработки · Разработка клиента, Команда инфраструктуры · Серверная инфраструктура
Если сервером служит ПК одного из игроков, его подключение и производительность ПК определяют ощущения всех.
Почему Сервером служит ПК хоста (P2P, listen-сервер) → Следствие Медленное подключение или ПК хоста сказывается на всех, а у самого хоста пинг 0 → На экране Преимущество только у хоста, когда хост выходит, у всех фриз или дисконнект
Основной ответственный Команда разработки · Разработка сервера · Совместно Команда разработки · Разработка клиента, Команда инфраструктуры · Серверная инфраструктура
Команда разработки: задачи
Сервер: перейти на выделенный сервер, который проверяет действия, а до этого при матчмейкинге выбирать хостом игрока с хорошим подключением и ПК. Клиент: поддерживать миграцию хоста, при матчмейкинге измерять и отправлять пинг до других участников, скорость отдачи и производительность ПК.
Команда инфраструктуры: задачи
Выделить серверное оборудование или инстансы под выделенные серверы, размещать их ближе к регионам, где много игроков.
На графике
Высоко только у некоторых · число жалоб на лаги и дисконнектов по хостам
Где смотреть
Писать в лог матча скорость отдачи хоста, RTT каждого участника до хоста, время кадра на ПК хоста и момент выхода хоста, группировать жалобы на лаги и дисконнекты по хостам. Игроки тоже могут проверить: сыграть тем же составом, сменив только хоста
Подтверждает
Лаги и дисконнекты сосредоточены в комнатах одного хоста, когда у него низкая скорость отдачи или долгий кадр, хуже становится всем участникам сразу, а без миграции хоста в момент его выхода у всех дисконнект
Опровергает
Если независимо от хоста плохо только участникам из одного региона, проблема в подключении или маршруте. При выделенных серверах причина не эта
Чем проверить
Нужны логи и метрики игрового сервера или клиента
Источников: 3
Networking Overview for Unreal EngineEpic Games Хост listen-сервера получает преимущество перед другими клиентами и несёт большую нагрузку, потому что одновременно работает сервером и рендерит
ID sy-optimistic-reject · Основной ответственный Команда разработки · Разработка клиента · Совместно Команда разработки · Разработка сервера
Если сервер потом не засчитывает удар или умение, которые экран игрока уже показал, результат, который игрок точно видел, отменяется.
Почему Эффект удара и анимация умения проигрываются до подтверждения сервера (опережающий фидбек) → Следствие Сервер заново проверяет дальность, позицию цели, кулдаун и ресурсы и отклоняет действие → На экране Кровь брызнула, а урона нет; анимация умения проиграна, а эффекта нет; запустился только кулдаун
Основной ответственный Команда разработки · Разработка клиента · Совместно Команда разработки · Разработка сервера
Команда разработки: задачи
Клиент: по результату сервера показывать только то, что требует подтверждения (цифры урона, смерть, награды), частые причины отказа проверять заранее, при отказе возвращать кулдаун и ресурсы и показывать причину. Сервер: давать запас на пинг при проверке дальности и позиции цели, отправлять причину в ответе с отказом, собирать долю отказов по умениям в метрики.
Цифры для ориентира
Отказ приходит с опозданием на пинг плюс ожидание тика после нажатия. При пинге 150 ms игрок около 0,2 с считает, что попал.
На графике
Высоко только у некоторых · доля отказов сервера по умениям (по диапазонам пинга)
Где смотреть
Собирать на сервере долю отказов по умениям и причины отказов (дальность, позиция цели, кулдаун, ресурсы) в разбивке по диапазонам RTT игроков. На клиенте записывать, сколько раз действия с опережающим фидбеком были отклонены
Подтверждает
Отказы сосредоточены на отдельных умениях и причинах «дальность» и «позиция цели», и с ростом пинга доля отказов растёт
Опровергает
Если причина отказа кулдаун или ресурсы и от пинга это не зависит, проверить, не расходятся ли значения данных (кулдаун, стоимость) у клиента и сервера. Если отказов нет, а анимация начинается только после ответа сервера, это причина «Отклик только после ответа сервера (модель запрос-ответ)»
Чем проверить
Нужны логи и метрики игрового сервера или клиента
Подробнее
Опережающий фидбек лучше всего скрывает пинг. Но чем сильнее расходятся данные, по которым решают клиент и сервер (позиция противника, оставшиеся ресурсы), тем чаще отказы. Если собирать долю отказов по умениям в метрики, места, где проверки расходятся, легко найти.
Источников: 2
Using Gameplay Abilities in Unreal EngineEpic Games Способности Local Predicted сразу выполняются на клиенте, но окончательно решает сервер, и он может отменить результат
ID sy-path-mismatch · Основной ответственный Команда разработки · Разработка сервера · Совместно Команда разработки · Разработка клиента
Если стороны обмениваются только командой «иди сюда», а путь каждая сторона рассчитывает сама, то даже при небольшом расхождении персонаж или монстр идёт другим путём, а потом его утягивает на правильное место.
Почему При перемещении кликом и преследовании монстром отправляется только точка назначения, а путь клиент рассчитывает сам → Следствие Из-за различий в данных ландшафта, столкновений с другими персонажами или порядка расчёта объект идёт не тем путём, что на сервере → На экране Монстр проходит сквозь стену и вдруг перескакивает на другое место, персонаж после клика как бы скользит и меняет направление
Основной ответственный Команда разработки · Разработка сервера · Совместно Команда разработки · Разработка клиента
Команда разработки: задачи
Сервер: отправлять вместе с целью промежуточные точки пути (вейпоинты), периодически синхронизировать позицию. Клиент: плавно сводить расхождение, использовать те же данные ландшафта, что и сервер.
На графике
Случайные всплески · число и расстояние коррекций позиции по объектам
Где смотреть
Записывать для каждого объекта разницу между позицией от сервера и позицией, рассчитанной клиентом, и отмечать на карте точки, где происходили коррекции. Если периодически сравнивать контрольные суммы результатов расчёта пути или позиций с обеих сторон, можно найти момент, когда началось расхождение
Подтверждает
Коррекции сосредоточены на определённом рельефе (пороги, узкие проходы, склоны) или в людных местах и повторяются в тех же точках даже у игроков с нормальными сетевыми метриками
Опровергает
Если коррекции бывают где угодно, но только в моменты всплесков потерь и джиттера, проблема в подключении. Если один монстр одновременно дёргается на экранах нескольких игроков, проверить, не находится ли управление монстром у тормозящего клиента
Чем проверить
Нужны логи и метрики игрового сервера или клиента
Подробнее
Это одна из причин, почему игры с перемещением кликом и таб-таргетом малочувствительны к пингу. Однако одинаковый результат у обеих сторон не гарантирован, поэтому обязательно нужен механизм, который время от времени синхронизирует позицию. Результаты вычислений с плавающей точкой могут немного отличаться в зависимости от типа CPU, компилятора и его настроек оптимизации (в том числе между debug- и release-сборками). В схемах вроде lockstep и роллбэка, где стороны обмениваются только вводом и считают, что результаты расчёта у них совпадают, эти мелкие различия накапливаются, и состояние игры на двух экранах может разойтись (desync).
Источников: 6
Deterministic LockstepGaffer On Games Даже если на одной машине расчёт детерминирован, на другом компиляторе, ОС или CPU результаты с плавающей точкой могут отличаться
State SynchronizationGaffer On Games Если отправлять вместе с вводом и состояние, стороны можно синхронизировать и без полного детерминизма
Peeking into VALORANT's NetcodeRiot Games При потерях пакетов или когда два персонажа пытаются встать в одну точку, симуляции сервера и клиента расходятся, и нужна коррекция
Floating Point DeterminismGaffer On Games Даже один и тот же код с плавающей точкой может давать разные результаты в зависимости от компилятора, архитектуры CPU и сборки (debug или release). Известен случай, когда CPU AMD и Intel выдавали немного разные значения трансцендентных функций
/fp (Specify floating-point behavior)Microsoft /fp:fast может менять порядок операций с плавающей точкой или объединять их, и результат будет отличаться от других настроек /fp, а операции, объединённые в FMA, тоже могут давать результат, отличный от раздельного умножения и сложения
ID sy-low-send-rate · Основной ответственный Команда разработки · Разработка сервера · Совместно Команда разработки · Разработка клиента
Если сервер отправляет обновления позиций (снапшоты) всего несколько раз в секунду, буфер интерполяции приходится делать соответственно длинным, и другие персонажи видны в более далёком прошлом.
Почему Ради экономии трафика обновления позиций отправляются всего 5–10 раз в секунду → Следствие Для плавной картинки буфер нужен в 2 раза длиннее интервала между пакетами (200–400 ms), а если сделать его коротким, потеря одного пакета уже даёт фриз → На экране Смена направления у противника видна поздно и расходится с проверкой попадания. При коротком буфере микрофризы, при потерях телепортация
Основной ответственный Команда разработки · Разработка сервера · Совместно Команда разработки · Разработка клиента
Команда разработки: задачи
Сервер: близкие объекты и тех, кто в бою, обновлять часто, а дальние редко, отправлять только изменения (дельта-сжатие), чтобы уменьшить размер пакета и поднять частоту. Клиент: автоматически подстраивать длину буфера интерполяции под интервал между пакетами.
Цифры для ориентира
При 10 обновлениях в секунду интервал между пакетами 100 ms, буфер 200 ms. Если добавить 75 ms задержки в одну сторону при пинге 150 ms, противник виден примерно на 0,3 с в прошлом.
На графике
Высоко с самого начала · интервалы прихода пакетов по клиентам, длина буфера интерполяции
Где смотреть
В захвате пакетов на стороне сервера отфильтровать только поток к одному игроку и смотреть в I/O Graphs Wireshark число пакетов в секунду и интервалы. Если есть игровые логи, смотреть вместе интервалы обновлений по объектам и запас буфера интерполяции на клиенте (сколько времени осталось до следующего снапшота)
Подтверждает
Обновления позиций всегда редкие, 5–10 в секунду (интервал 100–200 ms), буфер интерполяции больше 200 ms или его запас часто падает до 0
Опровергает
Если обновления уходят часто, а скачут только интервалы прихода, причина в джиттере и потерях. Если в толпе редко приходят только дальние объекты, это бюджет отправки и приоритеты для каждого соединения
Snapshot InterpolationGaffer On Games При 10 пакетах в секунду, чтобы пережить две потери подряд, нужна задержка 350 ms, при 30 пакетах в секунду она сокращается до 150 ms
State SynchronizationGaffer On Games Накопление приоритета: важные объекты отправляются чаще, а остальные по очереди в пределах лимита пропускной способности
8.8. The “I/O Graphs” WindowWireshark Строит график числа пакетов и байтов, подходящих под фильтр отображения, по интервалам времени
ID pt-slow-burst · Основной ответственный Команда разработки · Разработка сервера · Совместно Внешние стороны · Внешние стороны
Ввод игрока с плохим подключением приходит на сервер неравномерно, пачками. Если сервер в каждом тике применяет всё, что успело прийти, другие видят, как этот персонаж замирает, а потом делает сразу несколько шагов.
Почему Команды перемещения тормозящего игрока приходят неравномерно: в одном тике 0, в другом по 2–3 → Следствие Сервер применяет их разом в тике получения, и позиция персонажа меняется ступеньками → На экране На экранах других игроков только этот персонаж замирает, а потом разом проскакивает вперёд. Остальное в порядке
Странно выглядит один персонаж, Один регион или провайдер
Когда
Всегда, В движении и при смене локации
Ответственные
Основной ответственный Команда разработки · Разработка сервера · Совместно Внешние стороны · Внешние стороны
Команда разработки: задачи
Применять команды равномерно через буфер ввода на игрока, применять их с исходными интервалами по порядковым номерам ввода. Одного увеличения буфера интерполяции на чужих экранах мало: на сервере сама история позиций уже ступенчатая.
Внешние стороны: задачи
Посоветовать тормозящему игроку проводное подключение и проверку Wi-Fi и роутера.
Цифры для ориентира
При джиттере 80 ms на 20-тиковом сервере (тик 50 ms) число команд за тик скачет от 0 до 3.
На графике
Высоко только у некоторых · число применённых команд за тик по игрокам, джиттер по игрокам
Где смотреть
В захвате пакетов на стороне сервера отфильтровать пакеты от игрока, на которого жалуются, посчитать, сколько их приходит за каждый интервал тика (например, 50 ms), и сравнить с другими игроками. Если есть лог сервера, смотреть по игрокам число применённых команд перемещения за тик и порядковые номера ввода
Подтверждает
Только пакеты этого игрока приходят пачками, то 0, то 2–3 за тик, у него высокие джиттер и потери, а пакеты других игроков приходят равномерно. Когда этот игрок переходит на кабель, становится лучше
Опровергает
Если пачками движутся сразу несколько персонажей, причина в задержке тика сервера или в подключении того, кто смотрит. Если приход и применение равномерны, а дёргается только этот персонаж, проблема в интерполяции или отображении на стороне смотрящего
Чем проверить
Инструменты инфраструктуры (игровой код не нужен)
Подробнее
В архитектуре с авторитетным сервером это нормальное поведение. Лаги одного тормозящего игрока другие видят только как «странное движение этого игрока», а на управление других игроков и движение монстров они не влияют. Однако всё, что напрямую связано с этим игроком (обмен, механики группы, проверки попаданий в PvP), тоже запаздывает.
Источников: 3
Peeking into VALORANT's NetcodeRiot Games Сервер кладёт пришедший ввод в очередь перемещений каждого игрока по порядку тиков, а если очередь пуста, заполняет её предсказанием. Коррекцию видит только этот игрок, остальные видят плавное движение
State SynchronizationGaffer On Games Даже пакеты, отправленные 60 раз в секунду, приходят пачками: 2 в одном кадре, 0 в следующем
ID pt-event-server · Основной ответственный Команда разработки · Разработка сервера · Совместно Команда разработки · Разработка клиента
На сервере, который обрабатывает и рассылает пакеты сразу по приходу, действия тормозящего игрока, пришедшие пачкой, выполняются подряд и немедленно.
Почему Запросы умений и перемещения от тормозящего игрока приходят пачкой → Следствие Сервер выполняет их по порядку сразу при получении и тут же рассылает всем → На экране Другие видят, как этот игрок применяет несколько умений в одно мгновение или движется как в ускоренной перемотке
Основной ответственный Команда разработки · Разработка сервера · Совместно Команда разработки · Разработка клиента
Команда разработки: задачи
Сервер: выполнять действия с интервалами по прикреплённому времени ввода (время принимать только в допустимых пределах) либо принимать пришедшие пачкой действия и выполнять их по очереди с минимальным интервалом (глобальный кулдаун), не проверять кулдаун только по времени прихода (нормальный ввод «съедается»). Клиент: прикреплять к действиям время ввода.
На графике
Высоко только у некоторых · интервалы выполнения действий по игрокам
Где смотреть
Писать в лог сервера по игрокам время прихода и выполнения действий и время ввода от клиента (если есть), сравнивать интервалы выполнения и ввода. Заодно смотреть интервалы прихода пакетов этого игрока в захвате пакетов на стороне сервера
Подтверждает
Интервалы ввода нормальные, а приход и выполнение на сервере сбиты в группы с промежутками в несколько ms, и эти моменты совпадают со временем жалоб других игроков на перемотку
Опровергает
Если в группы сбиты уже интервалы по времени ввода, проблема в клиенте или в макросе. Если на сервере интервалы выполнения ровные, а сбитыми они выглядят только на чужих экранах, причина в подключении того, кто смотрит
Deterministic LockstepGaffer On Games Если применять ввод сразу по приходу, даже при отправке с частотой 60 Hz интервалы неравномерны и результат скачет
ID pt-input-buffer · Основной ответственный Команда разработки · Разработка сервера · Совместно Команда разработки · Разработка клиента
Если сервер немного накапливает ввод каждого игрока и берёт по одной команде за тик, на чужих экранах движение плавное, но момент, когда действие самого игрока подтверждается сервером, сдвигается на столько же.
Почему Сервер накапливает ввод тормозящего игрока в буфере и применяет по одной команде за тик → Следствие Маленький буфер часто пустеет, и персонаж встаёт на месте или сервер двигает его, угадывая по последнему вводу, а большой буфер задерживает подтверждение ввода самого игрока → На экране С маленьким буфером другие видят замирания, с большим результат умений самого игрока появляется поздно (задержка ввода)
Основной ответственный Команда разработки · Разработка сервера · Совместно Команда разработки · Разработка клиента
Команда разработки: задачи
Сервер: автоматически подстраивать размер буфера под состояние подключения каждого игрока, при отставании брать по две команды и догонять, клиентам игроков, у которых буфер часто пустеет, давать команду отправлять ввод раньше. Клиент: по команде сервера отправлять ввод немного раньше (подстройка времени клиента).
Цифры для ориентира
Зависит от игры, но обычно 1–3 тика. VALORANT на 128-тиковом сервере держит серверный буфер ещё короче, в среднем полкадра (около 4 ms). Часто используют адаптивный буфер, который увеличивается только у игроков с большим джиттером.
На графике
Высоко только у некоторых · длина буфера ввода и число опустошений по игрокам
Где смотреть
Писать на сервере для каждого игрока число команд в буфере ввода на каждом тике, число случаев, когда буфер опустел и был заполнен догадкой по последнему вводу, и время от прихода ввода до его применения
Подтверждает
У игроков с маленьким буфером много опустошений, и в эти моменты на чужих экранах они ненадолго замирают, а у игроков с большим буфером время от ввода до применения выросло на длину буфера
Опровергает
Если буфер почти не пустеет, а на чужих экранах видны микрофризы, проблема в интерполяции на стороне смотрящего. Если буфер короткий, а задержка ввода большая, причина в самом RTT или в двойном ожидании тика
Чем проверить
Нужны логи и метрики игрового сервера или клиента
Источников: 3
Peeking into VALORANT's NetcodeRiot Games Сервер сдвигает отсчёт времени клиента так, чтобы очередь ввода давала минимальную задержку, но успевала поглотить неравномерный приход. Цель серверной буферизации: в среднем полкадра
ID pt-isp-validation · Основной ответственный Команда разработки · Разработка сервера · Совместно Команда инфраструктуры · Сетевая инфраструктура
У игроков на подключениях с большим джиттером ввод приходит пачками и часто попадает под серверную проверку скорости и кулдаунов.
Почему Вечером растёт джиттер на подключениях определённого провайдера или региона → Следствие Нормальный ввод, пришедший пачкой, сервер считает превышением скорости или нарушением кулдауна → На экране Только у абонентов этого провайдера откидывание назад и отказы умений, в тяжёлых случаях сервер кикает игрока (дисконнект)
Основной ответственный Команда разработки · Разработка сервера · Совместно Команда инфраструктуры · Сетевая инфраструктура
Команда разработки: задачи
Проверять накопленный лимит за несколько секунд, смягчать критерии с учётом состояния подключения (пинг, джиттер), ввести этап предупреждения перед киком, распределять пришедший пачкой ввод по тикам через буфер ввода на игрока, чтобы ложных срабатываний изначально было меньше.
Команда инфраструктуры: задачи
Смотреть распределение потерь и джиттера по провайдерам и времени суток и делиться им с командой разработки, проверять маршрут на участке этого провайдера (mtr в обе стороны), при необходимости менять маршрут или эскалировать провайдеру.
На графике
Высоко только в определённые часы · число отказов проверки и киков по провайдерам (ASN), джиттер по провайдерам
Где смотреть
Добавить к логам отказов проверки, коррекций и киков на сервере провайдера (ASN) по IP подключения и время и посчитать по провайдерам и времени суток. Команда инфраструктуры в то же время запускает mtr в обе стороны до этого провайдера и смотрит джиттер и потери
Подтверждает
Отказы и кики сосредоточены у одного провайдера и растут вечером, в это же время у этого провайдера высокий джиттер, а суммарное перемещение за несколько секунд укладывается в правила
Опровергает
Если повторяется только у определённых аккаунтов независимо от провайдера, возможно, это реальный чит. Если растёт у всех провайдеров сразу, причина на стороне сервера: тики отстают, и команды применяются пачками (превышение бюджета тика)
Чем проверить
Нужны логи и метрики игрового сервера или клиента
Источников: 3
Source SDK 2013: player.cppValve Бюджет команд, который копится каждый тик, не даёт превышать скорость. В комментарии разработчиков сказано, что более строгое ограничение даёт микрофризы и обычным игрокам
ID pt-raid-member · Основной ответственный Команда разработки · Разработка сервера · Совместно Команда разработки · Разработка клиента
В рейдовых механиках, где все должны отреагировать в один и тот же момент, запоздалая реакция одного тормозящего игрока проваливает всю группу.
Почему Общие механики вроде «всем разом разбежаться» или «одному нажать кнопку» → Следствие Тормозящий игрок поздно видит предупреждение, и его ввод тоже приходит поздно → На экране Вайп из-за одного игрока, остальные участники чувствуют, что «виноват тот, у кого лаги»
Одна локация или канал, Странно выглядит один персонаж
Когда
При наплыве игроков, При определённом действии
Ответственные
Основной ответственный Команда разработки · Разработка сервера · Совместно Команда разработки · Разработка клиента
Команда разработки: задачи
Сервер: давать окнам механик запас на пинг, отправлять предупреждения заранее по серверному времени, проектировать так, чтобы ошибка одного не вела к вайпу. Клиент: проигрывать полученное предупреждение по серверному времени.
На графике
Высоко только у некоторых · RTT игроков, из-за которых провалилась механика
Где смотреть
Писать в лог механик на сервере игрока, из-за которого провалилась механика, время прихода его ввода, окно механики и его RTT и потери
Подтверждает
Ввод, который привёл к вайпу, почти всегда от одного и того же игрока, его RTT заметно выше среднего по группе, а ввод приходит сразу после закрытия окна
Опровергает
Если провалы равномерно распределены по участникам, проблема в слишком коротком окне (причина «Короткое окно реакции, которое съедает пинг»). Если ввод тормозящего игрока пришёл внутри окна, а механика всё равно провалена, проблема в коде проверки на сервере
ID pt-mob-control · Основной ответственный Команда разработки · Разработка сервера
В некоторых играх, чтобы снизить нагрузку на сервер, расчёт перемещения монстров поручают клиенту одного из ближайших игроков. Если у этого игрока плохое подключение, монстр странно движется на экранах у всех.
Почему Сервер поручает расчёт перемещения монстра клиенту ближайшего (или пришедшего первым) игрока → Следствие Отчёты этого игрока о результатах приходят на сервер с опозданием или пачками → На экране Только этот монстр на экранах всех вокруг замирает и телепортируется. У самого игрока, которому поручен монстр, всё нормально
Странно выглядит один персонаж, Одна локация или канал
Когда
Всегда, Изредка, случайно
Ответственные
Основной ответственный Команда разработки · Разработка сервера
Команда разработки: задачи
Передавать управление игроку с хорошим подключением (по пингу и потерям), сразу забирать управление на сервер, если отчёты прекратились, важных монстров вроде боссов рассчитывать на сервере.
На графике
Высоко только у некоторых · интервал отчётов о позиции по монстрам (по клиентам, у которых управление)
Где смотреть
Записывать на сервере для каждого монстра, у какого клиента управление, а также интервал отчётов, RTT и потери этого клиента. Интервалы прихода пакетов от этого клиента видны и в захвате пакетов на стороне сервера
Подтверждает
Управление всеми странно двигающимися монстрами у одного и того же игрока, его отчёты приходят неравномерно или прерываются, а после передачи управления другому игроку всё сразу приходит в норму
Опровергает
Если так же дёргаются и монстры, которых рассчитывает сам сервер, причина в задержке тика сервера или в подключении того, кто смотрит. Если после передачи управления рывки остаются, это расхождение расчёта пути при синхронизации команд
Чем проверить
Нужны логи и метрики игрового сервера или клиента
Подробнее
Игрок, которому поручен монстр, никаких проблем не замечает, поэтому жалобы приходят только в виде «с монстром что-то не так». Если странное поведение одного и того же монстра видят все, кроме одного игрока, сначала проверяют, у кого управление этим монстром.
Источников: 2
Authority (Netcode for GameObjects 2.5)Unity В модели распределённого авторитета каждый экземпляр игры (клиент) отвечает за часть сетевых объектов и рассчитывает их
ID pt-heavy-char · Основной ответственный Команда разработки · Разработка сервера · Совместно Команда инфраструктуры · Инфраструктура БД
У персонажа, у которого накопились тысячи предметов и писем или необычно много друзей, записей в чёрном списке и баффов, данных для загрузки при входе, сохранения и рассылки окружающим в разы больше, чем у других. Тормозит только этот персонаж, независимо от подключения.
Почему У давно прокачиваемого персонажа в инвентаре и почте скопились тысячи предметов или наград за события → Следствие При каждом входе, переходе между локациями и сохранении приходится читать и писать в БД соответствующий объём, и данные о снаряжении и баффах для рассылки окружающим тоже большие → На экране Только у этого персонажа долгая загрузка при входе и замирания при открытии инвентаря или почты. Если сервер ждёт сохранения в игровом потоке, на мгновение замирают и окружающие
Сразу после входа или техработ, При определённом действии, В движении и при смене локации
Ответственные
Основной ответственный Команда разработки · Разработка сервера · Совместно Команда инфраструктуры · Инфраструктура БД
Команда разработки: задачи
Ввести лимиты на хранение в инвентаре и почте и автоочистку старых писем, загружать данные частями по мере надобности, сохранять только изменения и вне игрового потока.
Команда инфраструктуры: задачи
Найти в логе медленных запросов повторяющиеся медленные чтения по одному и тому же персонажу и передать команде разработки, предоставить топ персонажей по числу строк предметов и писем.
Цифры для ориентира
Если один предмет занимает одну строку в БД, персонаж с 5 000 предметов при каждом входе читает 5 000 строк. Это в десятки раз больше, чем у обычного персонажа.
На графике
Высоко только у некоторых · время входа и сохранения по персонажам, число строк, читаемых из БД, по персонажам
Где смотреть
Найти в логе медленных запросов БД (MySQL slow query log, PostgreSQL log_min_duration_statement) медленные чтения и сохранения, повторяющиеся с одним и тем же ID персонажа, и выгрузить топ персонажей по числу строк в таблицах предметов и писем
Подтверждает
Медленные запросы сосредоточены на нескольких ID персонажей, у этих персонажей строк предметов и писем в десятки раз больше среднего, и при входе с другого ПК и подключения они тормозят так же
Опровергает
Если вместе тормозят и другие персонажи того же аккаунта или другие игроки, причина в серверах БД или блокировках. Если на другом ПК с этим персонажем всё нормально, причина в окружении игрока
Чем проверить
Инструменты инфраструктуры (игровой код не нужен)
Подробнее
Если тот же персонаж тормозит так же при входе с другого ПК и подключения, а другие персонажи того же аккаунта в порядке, подозревают данные персонажа. Поэтому в жалобе обязательно нужно имя персонажа.
Источников: 3
Extraneous Fetching antipatternMicrosoft Azure Если извлекать больше данных, чем нужно, растёт нагрузка на ввод-вывод и замедляются ответы
ID pt-phase · Основной ответственный Команда разработки · Разработка сервера · Совместно Команда разработки · Разработка клиента
Если два персонажа находятся в разных каналах или инстансах или в разных «фазах», где набор видимых NPC зависит от прогресса квеста, они видят разные миры.
Почему Второй персонаж попал в другой канал или находится на другом этапе квеста → Следствие Этому персонажу сервер этот NPC не отправляет (это нормально) → На экране NPC нет только у одного из них. Похоже на баг, но так задумано
Основной ответственный Команда разработки · Разработка сервера · Совместно Команда разработки · Разработка клиента
Команда разработки: задачи
Сервер: отправлять клиенту данные о канале и фазе, добавить в чек-лист QA пункт «проверить канал и этап квеста обоих персонажей». Клиент: показывать на экране канал и фазу.
На графике
Высоко только у некоторых · число окружающих объектов по клиентам, канал и фаза
Где смотреть
Сравнить в игре номера каналов обоих персонажей и этап нужного квеста, выровнять канал и этап и посмотреть снова. Если есть лог отправки объектов на сервере, проверить, по какой причине (канал, фаза) этот NPC не отправлялся этому персонажу
Подтверждает
Каналы или этапы квеста у двух персонажей разные, и после выравнивания NPC видно
Опровергает
Если канал и этап одинаковые, а NPC нет только у одного, смотреть причины: отбрасывание уведомлений о появлении во время загрузки, потеря данных о появлении из-за наплыва сразу после входа, сбой порядка регистрации в зоне видимости
Чем проверить
Проверка на стороне игрока
Подробнее
Стоит проверить и то, хранится ли прогресс квестов на уровне аккаунта или персонажа. Если это два персонажа одного аккаунта, прогресс одного может менять фазу другого.
Источников: 2
Actor Relevancy in Unreal EngineEpic Games Сервер реплицирует для каждого соединения только релевантные (relevant) акторы, а нерелевантные не отправляет
ID pt-loading-drop · Основной ответственный Команда разработки · Разработка клиента · Совместно Команда разработки · Разработка сервера
Сразу после входа в зону сервер отправляет уведомления о появлении NPC вокруг, а клиент ещё загружает карту и отбрасывает эти уведомления.
Почему Сразу после обработки входа сервер рассылает уведомления о появлении окружающих объектов → Следствие Клиент ещё загружается, обработчика сообщений пока нет, и уведомления отбрасываются → На экране Сервер считает их отправленными и повторно не шлёт. Пока игрок не выйдет из зоны видимости и не вернётся, NPC не видно
Сразу после входа или техработ, В движении и при смене локации
Ответственные
Основной ответственный Команда разработки · Разработка клиента · Совместно Команда разработки · Разработка сервера
Команда разработки: задачи
Клиент: по окончании загрузки отправлять сигнал «готов» или хранить пакеты, пришедшие во время загрузки, и обрабатывать их позже. Сервер: отправлять данные об окружении только после сигнала «готов».
Цифры для ориентира
Если на одном ПК два клиента загружаются одновременно или загружающийся клиент находится в фоновом окне, они делят CPU и диск, обработка ограничивается, и загрузка этого клиента может стать в разы дольше. Тот же баг проявляется и тогда, когда сервер начинает быстрее обрабатывать вход.
На графике
Высоко только у некоторых · время загрузки по клиентам, число сообщений, отброшенных во время загрузки
Где смотреть
Сравнить число и типы сообщений, которые клиент получил и отбросил во время загрузки, и время окончания загрузки со временем отправки уведомлений о появлении на сервере. Легко воспроизвести, если на одном ПК загружать два клиента одновременно или держать загружающийся клиент в фоновом окне
Подтверждает
Сервер отправил уведомления о появлении невидимых NPC, они пришли до окончания загрузки, и в это время выросло число отброшенных сообщений. Бывает только у клиента с более долгой загрузкой
Опровергает
Если уведомления пришли после окончания загрузки, а NPC всё равно не видно, причина в потере опорного снапшота или путанице из-за повторного использования ID объектов. Если сервер вообще не отправлял уведомление об этом NPC, причина в сбое порядка регистрации в зоне видимости или в разных каналах и фазах
Actor Relevancy in Unreal EngineEpic Games Актор, утративший релевантность, удаляется на клиенте, а когда снова становится релевантным, реплицируется заново
ID pt-aoi-race · Основной ответственный Команда разработки · Разработка сервера
Если момент регистрации персонажа в сетке видимости совпадает с моментом, когда NPC переходит в другую ячейку, уведомление о появлении этого NPC может потеряться.
Почему Обработка входа, смены канала или телепорта совпадает по времени с перемещением NPC → Следствие Этот NPC выпадает из расчёта «объектов, которые стали видны» → На экране Не видно только нескольких определённых NPC, или остаётся NPC, который уже ушёл
Основной ответственный Команда разработки · Разработка сервера
Команда разработки: задачи
Обновлять зону видимости в одном потоке и в одном порядке, периодически заново сверять весь «список видимых».
На графике
Случайные всплески · число расхождений между списком видимых на сервере и списком объектов на клиенте
Где смотреть
Писать на сервере с номером тика регистрацию в сетке видимости, переходы объектов между ячейками и отправку уведомлений о появлении и исчезновении, периодически сравнивать «список видимых» на сервере со списком на клиенте
Подтверждает
Пропавший NPC сменил ячейку в том же тике, когда обрабатывался вход или телепорт персонажа, и записи об отправке уведомления о появлении этого NPC нет
Опровергает
Если уведомление о появлении отправлено, но клиент его не получил или отбросил, проблема в доставке (потеря данных о появлении из-за наплыва сразу после входа, отбрасывание уведомлений о появлении во время загрузки). Если всегда пропадают одни и те же NPC, причина в фазах или разных настройках отображения
Чем проверить
Нужны логи и метрики игрового сервера или клиента
Источников: 2
Replication Graph in Unreal EngineEpic Games В MMORPG и подобных играх мир делится сеткой, у каждой ячейки свой список акторов, и данные отправляются по ячейке, где находится клиент
Actor Relevancy in Unreal EngineEpic Games Релевантность определяется для каждого соединения, и актор, утративший релевантность, удаляется на клиенте
ID pt-baseline · Основной ответственный Команда разработки · Разработка сервера · Совместно Команда разработки · Разработка клиента
Если сервер отправляет «только то, что изменилось с прошлого раза», то при потере первой полной посылки (опорного снапшота) последующие изменения применить невозможно.
Почему Пакет с полными данными объекта (опорный снапшот) теряется или отбрасывается до обработки → Следствие Клиенту не к чему применять последующие изменения, и он их игнорирует → На экране Объект не виден или внезапно появляется спустя долгое время
Основной ответственный Команда разработки · Разработка сервера · Совместно Команда разработки · Разработка клиента
Команда разработки: задачи
Сервер: обязательно повторять отправку опорного снапшота, пока не придёт подтверждение (ACK), формировать изменения только относительно опорного снапшота, получение которого клиент подтвердил. Клиент: отправлять подтверждение (ACK) опорного снапшота только после его фактического применения, при получении изменений для неизвестного объекта запрашивать у сервера данные заново.
На графике
Случайные всплески · число полученных изменений для неизвестных объектов
Где смотреть
Сопоставить число отброшенных клиентом изменений без опорного снапшота и ID объектов со временем, когда сервер отправил опорный снапшот этого объекта и когда получил ACK. Воспроизвести в среде разработки, добавив потери (loss в tc netem, доля потерь пакетов в эмуляции сети Unreal)
Подтверждает
Для невидимого объекта сервер отправил опорный снапшот, ACK не получил, но продолжал слать только изменения, а клиент эти изменения отбрасывал
Опровергает
Если опорный снапшот подтверждён ACK и применён на клиенте, а объекта всё равно не видно, причина в потере уведомления об исчезновении или путанице из-за повторного использования ID объектов
Чем проверить
Нужны логи и метрики игрового сервера или клиента
Источников: 4
Snapshot CompressionGaffer On Games Изменения нужно формировать только относительно опорного состояния (baseline), получение которого подтвердила другая сторона (ack), а начальное состояние отправлять отдельно
Quake III Arena source: code/server/sv_snapshot.cid Software Дельта-сжатие выполняется относительно снапшота, подтверждённого клиентом, а если опорный снапшот слишком старый, отправляется полный снапшот
tc-netem(8) — Linux manual pageiproute2 Инструмент для тестирования, который добавляет к исходящим пакетам задержку и джиттер (delay TIME JITTER) и потери (loss random PERCENT), имитируя реальную сеть
Using Network Emulation in Unreal EngineEpic Games Тестирование с минимальной и максимальной задержкой и долей потерь пакетов на сервере и клиенте, в консоли задаётся, например, как NetEmulation.PktLag
ID pt-ghost · Основной ответственный Команда разработки · Разработка сервера · Совместно Команда разработки · Разработка клиента
И наоборот, если пропущено уведомление «исчез», уже убитые или ушедшие NPC и игроки остаются только на экране этого игрока.
Почему Уведомления о смерти, уходе или выходе из зоны видимости теряются или приходят не по порядку → Следствие Клиент считает, что объект всё ещё на месте → На экране Монстр не реагирует на удары, на месте стоит игрок, который уже вышел из игры
Основной ответственный Команда разработки · Разработка сервера · Совместно Команда разработки · Разработка клиента
Команда разработки: задачи
Сервер: периодически отправлять «список видимых сейчас». Клиент: удалять объекты, которых нет в списке, скрывать объекты, которые должны двигаться, но долго не обновлялись.
На графике
Случайные всплески · число объектов, оставшихся только на клиенте
Где смотреть
Сравнить «список видимых сейчас» от сервера со списком объектов на клиенте, посчитать объекты, которые есть только на клиенте, и сопоставить по ID объекта логи отправки и получения уведомлений об исчезновении
Подтверждает
Сервер отправил уведомление об исчезновении фантомного объекта, а записи о получении на клиенте нет, или исчезновение пришло раньше появления, и порядок перепутан
Опровергает
Если объект остался и в списке видимых на сервере, сервер пропустил его удаление. Если это случилось сразу после появления нового объекта с тем же ID, это путаница из-за повторного использования ID объектов
ID pt-spawn-burst · Основной ответственный Команда разработки · Разработка сервера · Совместно Команда разработки · Разработка клиента
В момент входа в зону сервер разом отправляет данные о появлении десятков и сотен окружающих объектов. Если отправлять их по ненадёжному каналу доставки (unreliable) или если буфер приёма переполнится, пока клиент занят загрузкой и не читает сокет, часть данных пропадает и повторно не приходит.
Почему Сразу после входа данные о появлении приходят плотной пачкой за короткое время → Следствие Клиент во время загрузки поздно читает сокет, и буфер приёма ОС переполняется, или большой UDP-пакет фрагментируется, и при потере одного фрагмента пропадает целиком. По ненадёжному каналу доставки повторной отправки нет → На экране Только в клиенте с медленной загрузкой не хватает нескольких NPC. Если выйти из зоны видимости и вернуться, они видны
Сразу после входа или техработ, В движении и при смене локации
Ответственные
Основной ответственный Команда разработки · Разработка сервера · Совместно Команда разработки · Разработка клиента
Команда разработки: задачи
Сервер: уведомления о появлении и исчезновении отправлять только по надёжному каналу с гарантированной повторной передачей, начальные данные отправлять частями. Клиент: принимать данные в отдельном от загрузки потоке, увеличить буфер приёма.
Цифры для ориентира
Стандартный размер буфера приёма UDP на ПК зависит от ОС, но обычно составляет от десятков до сотен KB. Если данных о входе в людный город больше, буфер переполняется, даже если загрузка лишь ненадолго мешает читать сокет.
На графике
Всплеск сразу после входа или техработ · объём приёма сразу после входа, число пропущенных уведомлений о появлении
Где смотреть
Сравнить число уведомлений о появлении, отправленных сервером сразу после входа, с числом полученных клиентом и посмотреть, по какому каналу (надёжному или ненадёжному) они шли. В захвате пакетов на стороне сервера смотреть объём, ушедший этому игроку сразу после входа, и фрагментированные пакеты (фильтр Wireshark ip.flags.mf == 1 || ip.frag_offset > 0)
Подтверждает
Получено меньше, чем отправлено, пропуски собраны на участке плотной пачки сразу после входа, а отправка шла по ненадёжному каналу или большие пакеты фрагментированы. Чаще бывает в клиенте с медленной загрузкой
Опровергает
Если отправлено и получено одинаково, а NPC не видно, данные отброшены после получения (отбрасывание уведомлений о появлении во время загрузки) или проблема в расчёте зоны видимости. Если пропуски бывают в любое время, независимо от входа, это потери на линии связи
UDP vs. TCPGaffer On Games UDP не гарантирует ни доставку, ни порядок, поэтому потерянные пакеты нужно обнаруживать и отправлять повторно самостоятельно
ID pt-id-reuse · Основной ответственный Команда разработки · Разработка сервера · Совместно Команда разработки · Разработка клиента
Если при возрождении убитого NPC сервер снова использует тот же ID объекта, клиент, пропустивший за это время уведомление об исчезновении, принимает новый NPC за старый.
Почему NPC умирает и появляется снова с тем же ID объекта → Следствие Клиент, пропустивший уведомление об исчезновении, считает объект «уже известным» и игнорирует уведомление о появлении или оставляет объект мёртвым → На экране NPC нет только на одном экране или он лежит убитым, иногда выглядит как другой NPC
Основной ответственный Команда разработки · Разработка сервера · Совместно Команда разработки · Разработка клиента
Команда разработки: задачи
Сервер: добавлять к ID объекта номер поколения, чтобы различать повторное использование. Клиент: получив уведомление о появлении для уже известного ID, удалять старый объект и создавать новый.
На графике
Случайные всплески · число уведомлений о появлении для уже известных ID
Где смотреть
Писать на сервере время создания и удаления по каждому ID объекта (и номер поколения, если он есть), считать, сколько раз клиент получал уведомление о появлении для уже известного ID и сколько удалений с повторным созданием при обновлении зоны видимости прошли как «без изменений»
Подтверждает
ID невидимого или лежащего NPC совпадает с ID NPC, который только что умер, и за это время клиент не получил уведомление об исчезновении или сервер не отправил ни уведомление об исчезновении, ни уведомление о появлении
Опровергает
Если у ID есть номер поколения и он участвует в сравнении, причина не эта. Если ID не переиспользован, а объекта всё равно не видно, причина в потере уведомления о появлении
Чем проверить
Нужны логи и метрики игрового сервера или клиента
Подробнее
Это бывает и на стороне сервера. Если сравнивать список объектов в зоне видимости только по ID, NPC, который между двумя обновлениями зоны видимости умер и возродился с тем же ID, считается «без изменений», и не отправляется ни уведомление об исчезновении, ни уведомление о появлении. Если обновления зоны видимости у разных игроков происходят в разные моменты, проблема бывает только у клиентов, чьё обновление пришлось на этот момент.
Источников: 2
Entity struct (Entities 1.3)Unity Entity состоит из Index и номера поколения (Version), что позволяет понять, действителен ли ещё переиспользованный Index
ID pt-port-collision · Основной ответственный Команда разработки · Разработка клиента · Совместно Команда разработки · Разработка сервера
Если клиент рассчитан на конкретный локальный порт, второй клиент на том же ПК не может занять порт или делит пакеты с первым.
Почему Два клиента пытаются открыть один и тот же локальный UDP-порт (принудительно делят его через опцию повторного использования) → Следствие ОС передаёт входящие пакеты только одному из сокетов или не гарантирует, какой из них получит пакет. Роутер и сервер тоже видят оба клиента под одним адресом → На экране Один клиент не получает пакеты мира: не видно NPC и других игроков, или случается дисконнект
Основной ответственный Команда разработки · Разработка клиента · Совместно Команда разработки · Разработка сервера
Команда разработки: задачи
Клиент: поручить выбор локального порта ОС (bind на порт 0). Сервер: различать соединения по сессионному токену, выданному каждому соединению.
На графике
Высоко только у некоторых · число принятых пакетов по клиентам
Где смотреть
На ПК игрока с двумя запущенными клиентами выполнить в командной строке netstat -ano -p udp и посмотреть, какие локальные UDP-порты открыл каждый игровой процесс (PID). На стороне сервера проверить, приходят ли две сессии с одного публичного IP и одного порта
Подтверждает
Два игровых процесса привязаны к одному локальному порту, или на сервере две сессии видны с одного IP и порта. С одним запущенным клиентом всё нормально
Опровергает
Если клиенты используют разные локальные порты, а с одним из них всё равно что-то не так, причина в ошибке разделения сессий по IP или устройству либо в ограничении на несколько клиентов
Чем проверить
Проверка на стороне игрока
Источников: 3
Using SO_REUSEADDR and SO_EXCLUSIVEADDRUSEMicrosoft При повторном bind на тот же порт с SO_REUSEADDR второй сокет перехватывает порт, и неизвестно, какой сокет получит пакет
bind function (winsock.h)Microsoft При bind на порт 0 выделяется уникальный порт из динамического диапазона (49152–65535)
netstatMicrosoft -a показывает порты TCP и UDP, -n выводит адреса в числовом виде, -o показывает ID процесса (PID), -p udp оставляет только UDP
ID pt-session-key · Основной ответственный Команда разработки · Разработка сервера · Совместно Команда разработки · Разработка клиента
Если сервер или промежуточный сервер различает соединения по IP или ID устройства, два клиента на одном ПК (с одним публичным IP) считаются одним игроком.
Почему Таблица сессий строится по IP или по IP + ID устройства → Следствие Данные второго клиента перезаписывают первую сессию или смешиваются с ней → На экране В одном клиенте не видно NPC, а в другом случается дисконнект или приходят чужие данные
Один из клиентов на одном ПК, Все в одном доме, Один регион или провайдер
Когда
Сразу после входа или техработ
Ответственные
Основной ответственный Команда разработки · Разработка сервера · Совместно Команда разработки · Разработка клиента
Команда разработки: задачи
Сервер: и на сервере, и на промежуточных серверах различать соединения по уникальному сессионному токену; исправить обязательно, потому что та же проблема бывает у нескольких игроков из одного дома (за NAT роутера) и у абонентов мобильных сетей, где оператор выдаёт один IP многим абонентам (CGNAT). Клиент: использовать отдельный сессионный токен для каждого запущенного клиента.
На графике
Высоко только у некоторых · число одновременных сессий с одного публичного IP, число перезаписей сессий
Где смотреть
Писать в логи сервера и промежуточного сервера ключ поиска сессии, сессионный токен, IP и порт клиента и смотреть, менялась ли существующая сессия в момент второго подключения с того же IP. Воспроизводится, если запустить по очереди два клиента на одном ПК
Подтверждает
В момент подключения второго клиента меняются адрес или данные персонажа в первой сессии, и такие же дисконнекты видны у других игроков за тем же роутером или мобильным подключением (CGNAT)
Опровергает
Если две сессии с одного IP держатся раздельно с разными токенами, причина не эта. Если два процесса используют один локальный порт, это конфликт фиксированного UDP-порта
ID pt-multiclient · Основной ответственный Команда разработки · Разработка клиента · Совместно Команда разработки · Разработка сервера
Если модуль защиты или политика сервера ограничивает число клиентов на одном ПК, второй клиент не запускается или не подключается, либо у первого случается дисконнект. Некоторые игры блокируют только функции дополнительного клиента.
Почему Модуль защиты обнаруживает повторный запуск, или сервер ограничивает дополнительные подключения с одного устройства → Следствие Второй запуск или подключение отклоняется, либо один из клиентов отключается. Изредка блокируется только часть функций дополнительного клиента → На экране Ошибка входа или дисконнект у одного клиента. В играх, которые блокируют только функции, у одного клиента не видно NPC или магазина
Основной ответственный Команда разработки · Разработка клиента · Совместно Команда разработки · Разработка сервера
Команда разработки: задачи
Клиент: если ограничивать, то с понятным сообщением, сделать в модуле защиты исключение для QA. Сервер: в ограничении подключений с одного устройства тоже сделать исключение для QA.
На графике
Высоко только у некоторых · число отказов в подключении и обрывов по причинам (повторное подключение)
Где смотреть
Посмотреть сообщение при запуске второго клиента и сообщение об обрыве у первого. Проверить, пишутся ли в логи отказов и киков на сервере коды причин вроде «повторное подключение» или «то же устройство»
Подтверждает
В момент второго запуска или подключения появляется сообщение об отказе или первый клиент отключается с причиной «повторное подключение», а с одним клиентом проблем нет
Опровергает
Если оба клиента подключаются без отказов и обрывов, а NPC не видно только в одном, причина в конфликте фиксированного UDP-порта, ошибке разделения сессий по IP или устройству, в загрузке или отображении
Чем проверить
Проверка на стороне игрока
Источников: 1
CreateMutexW function (synchapi.h)Microsoft Если именованный мьютекс уже существует, возвращается ERROR_ALREADY_EXISTS, что используют для обнаружения повторного запуска и ограничения одним экземпляром
ID pt-background · Основной ответственный Команда разработки · Разработка клиента · Совместно Внешние стороны · Внешние стороны
Для клиента в фоновом окне игра, движок и ОС снижают частоту кадров и объём обработки. Полученные пакеты не успевают обрабатываться, копятся и переполняют буфер.
Почему Ограничение кадров в фоне в настройках игры или графического драйвера (например, в драйвере NVIDIA задаётся от 20 до 200 в секунду), энергосбережение, настройка движка останавливаться в фоне. ОС тоже отдаёт приоритет по CPU и GPU окну на переднем плане → Следствие За кадр обрабатывается меньше пакетов, очередь растёт, а при переполнении буфера приёма пакеты отбрасываются → На экране Когда окно выводят на передний план, всё появляется разом, или некоторые NPC так и не появляются
Основной ответственный Команда разработки · Разработка клиента · Совместно Внешние стороны · Внешние стороны
Команда разработки: задачи
Продолжать приём сетевых данных в отдельном от игрового цикла потоке, гарантировать минимальный объём обработки и в фоне, включить в движке выполнение в фоне (в Unity это runInBackground).
Внешние стороны: задачи
Посоветовать игрокам отключить ограничение кадров в фоне в графическом драйвере и режим энергосбережения ПК.
Цифры для ориентира
В Unity при выключенном runInBackground игровой цикл останавливается в момент, когда окно теряет фокус. Если приём идёт только в этом цикле, всё это время пакеты вообще не обрабатываются.
На графике
Провал, затем пачка · интервал между кадрами клиента, число обработанных пакетов за кадр
Где смотреть
На одном ПК держать одно окно на переднем плане, а другое на заднем, менять их местами и сравнивать. Измерить в PresentMon интервал между кадрами обоих процессов, а если есть игровые логи, смотреть состояние фокуса окна и число обработанных пакетов за кадр
Подтверждает
Только в фоновом окне интервал между кадрами сильно растёт (при ограничении в драйвере выходит на плато на интервале, соответствующем заданной частоте кадров) или обработка останавливается, а если поменять окна местами, проблема переходит к другому клиенту
Опровергает
Если то же самое бывает и в окне на переднем плане, фоновые ограничения ни при чём. Если независимо от положения окна сбоит всегда один и тот же клиент, причина в разных настройках отображения или в несовпадении версий
Чем проверить
Проверка на стороне игрока
Источников: 4
Application.runInBackgroundUnity runInBackground по умолчанию false, и в этом случае приложение в фоне ставится на паузу
ID pt-asset-lock · Основной ответственный Команда разработки · Разработка клиента
Если два клиента одновременно пишут в одну папку кэша или блокируют файлы, один из них не может загрузить модели и текстуры NPC.
Почему Два клиента одновременно пишут файлы кэша и патчей в одной папке установки → Следствие Не удаётся заблокировать файл или читается наполовину записанный файл, и загрузка срывается → На экране Табличка с именем видна, а модели персонажа нет, или NPC прозрачный
Сразу после входа или техработ, В движении и при смене локации
Ответственные
Основной ответственный Команда разработки · Разработка клиента
Команда разработки: задачи
Сделать отдельную папку кэша для каждого клиента, повторять попытку при неудачной блокировке файла, при неудачной загрузке показывать хотя бы модель по умолчанию.
На графике
Высоко только у некоторых · число неудачных загрузок ассетов по клиентам
Где смотреть
На ПК игрока отфильтровать в Process Monitor только пути к папкам установки и кэша игры и смотреть результаты открытия и записи файлов обоими игровыми процессами. Если есть лог клиента, искать неудачные загрузки ассетов и код ошибки открытия файла (ERROR_SHARING_VIOLATION)
Подтверждает
Открытие файла невидимой модели завершилось нарушением общего доступа или ошибкой блокировки, и в это же время другой клиент писал в этот файл. С одним клиентом или с раздельными папками установки и кэша проблема пропадает
Опровергает
Если та же модель не видна и с одним запущенным клиентом, причина в повреждении файла или несовпадении версии клиента или данных. Если файлы открываются нормально, а объект не рисуется, это нехватка памяти или VRAM
Чем проверить
Проверка на стороне игрока
Источников: 2
Creating and Opening FilesMicrosoft Файл, открытый без режима общего доступа, другой процесс открыть не может, возникает ERROR_SHARING_VIOLATION
Process MonitorMicrosoft Записывает в реальном времени активность файловой системы, реестра и процессов, позволяет фильтровать по любому полю, включая путь
ID pt-vram · Основной ответственный Команда разработки · Разработка клиента · Совместно Внешние стороны · Внешние стороны
Когда два клиента делят видеопамять, для новых моделей и текстур не остаётся места, и часть объектов не рисуется.
Почему Два клиента делят VRAM и RAM. Кроме того, ОС может в первую очередь урезать квоту видеопамяти фонового окна → Следствие Движок не может загрузить новые модели и текстуры или постоянно выгружает и загружает их снова → На экране NPC появляются с опозданием, размыты или не видны, микрофризы
В движении и при смене локации, При наплыве игроков
Ответственные
Основной ответственный Команда разработки · Разработка клиента · Совместно Внешние стороны · Внешние стороны
Команда разработки: задачи
Автоматически подстраивать качество под бюджет памяти, при неудачной загрузке показывать замещающую модель.
Внешние стороны: задачи
Игрокам, которые запускают два клиента одновременно, посоветовать снизить качество графики или включить режим для слабых ПК, сообщить рекомендуемые требования к VRAM и RAM.
На графике
Упор в лимит (плато) · использование выделенной памяти GPU по процессам
Где смотреть
На ПК игрока добавить на вкладке «Подробности» Диспетчера задач столбец выделенной памяти GPU и сравнить суммарное использование двух клиентов с объёмом VRAM видеокарты. В игре записывать бюджет (Budget) и текущее использование (CurrentUsage), которые сообщает QueryVideoMemoryInfo в DXGI
Подтверждает
Суммарное использование двух клиентов выходит на плато около объёма VRAM, а неудачные загрузки моделей и текстур приходятся на моменты, когда текущее использование превышает бюджет. При снижении качества или с одним клиентом проблема пропадает
Опровергает
Если VRAM хватает, а объекты не видны, причина в конфликте одновременного доступа к файлам кэша и ассетов или в разных настройках отображения
Чем проверить
Проверка на стороне игрока
Источников: 3
Residency (Direct3D 12)Microsoft Бюджет видеопамяти может сильно уменьшиться при переключении на другое приложение, а при превышении бюджета возможны подвисания или сбои при создании ресурсов. Если приложение не на переднем плане, даже зарезервированный объём не гарантирован
GPUs in the task managerMicrosoft Если добавить столбцы на вкладке «Подробности» Диспетчера задач, видно использование выделенной и общей памяти GPU по процессам. Выделенная память GPU означает VRAM видеокарты
DXGI_QUERY_VIDEO_MEMORY_INFO structure (dxgi1_4.h)Microsoft Budget (бюджет видеопамяти, заданный ОС) и CurrentUsage (текущее использование приложением). Если использование превышает бюджет, возможны рывки
ID pt-display-option · Основной ответственный Команда разработки · Разработка клиента
Если у двух клиентов различаются настройки вроде лимита отображаемых персонажей, скрытия табличек с именами и моделей NPC или режима для слабых ПК, они показывают разное.
Почему Только в одном клиенте включён «лимит числа отображаемых персонажей» или режим для слабых ПК → Следствие Дальние или низкоприоритетные NPC не рисуются (это нормально) → На экране NPC нет только в одном клиенте
Основной ответственный Команда разработки · Разработка клиента
Команда разработки: задачи
Показывать, что объект скрыт настройками, разделить файлы настроек по клиентам, чтобы они не смешивались.
На графике
Высоко только у некоторых · число отрисованных на экране объектов по клиентам
Где смотреть
Сравнить у двух клиентов лимит отображаемых персонажей, скрытие табличек с именами и моделей и режим для слабых ПК, выставить в одном клиенте те же значения, что в другом. Проверить также, не пишут ли клиенты в один общий файл настроек, перезаписывая изменения друг друга
Подтверждает
При одинаковых настройках экраны совпадают, а невидимые NPC оказываются дальними объектами за пределами лимита отображения или объектами с низким приоритетом
Опровергает
Если и при одинаковых настройках NPC нет только в одном клиенте, причина в разных каналах и фазах или в потере уведомлений о появлении
ID pt-version · Основной ответственный Команда разработки · Разработка клиента · Совместно Команда разработки · Разработка сервера
Если второй клиент установлен отдельно или не до конца пропатчен, он не знает новых ID NPC от сервера и молча их игнорирует.
Почему Установка в другой папке или клиент, запущенный во время патча → Следствие Получив неизвестный ID NPC или модели, клиент пропускает его → На экране В одном клиенте не видно только недавно добавленных NPC
Основной ответственный Команда разработки · Разработка клиента · Совместно Команда разработки · Разработка сервера
Команда разработки: задачи
Клиент: отправлять при подключении версию данных, при получении неизвестного ID писать лог и показывать замену. Сервер: проверять версию данных при подключении и при несовпадении отказывать в подключении и предлагать обновиться.
На графике
Высоко только у некоторых · число полученных неизвестных ID по версиям клиента
Где смотреть
Сравнить пути к исполняемым файлам двух клиентов и версии клиента и данных, которые видны на экране и в логах. В игре записывать версию данных, отправленную при подключении, и сколько раз неизвестные ID NPC и моделей были получены и пропущены
Подтверждает
У двух клиентов разные версии или папки установки, невидимые NPC добавлены последним патчем, а в полностью обновлённой установке они видны
Опровергает
Если версии и папки установки одинаковые, а NPC нет только в одном клиенте, причина в разных каналах и фазах, загрузке или доставке
ID pt-priority · Основной ответственный Команда разработки · Разработка сервера · Совместно Команда разработки · Разработка клиента
Если сервер ограничивает объём отправки для каждого соединения и отправляет сначала ближние объекты, соединение с низким лимитом получает дальних NPC поздно или не получает вовсе.
Почему В людных местах сервер отправляет данные в порядке важности в пределах лимита отправки для каждого соединения → Следствие Для соединения с заниженной оценкой пропускной способности (например, у фонового окна, которое поздно подтверждает приём) объекты из конца очереди постоянно откладываются → На экране Дальние NPC появляются поздно или не появляются только в одном клиенте
Один из клиентов на одном ПК, Одна локация или канал
Когда
При наплыве игроков
Ответственные
Основной ответственный Команда разработки · Разработка сервера · Совместно Команда разработки · Разработка клиента
Команда разработки: задачи
Сервер: повышать приоритет отложенных объектов со временем (защита от starvation), гарантировать минимальную частоту обновления. Клиент: вовремя отправлять подтверждения приёма и в фоне, чтобы оценка пропускной способности не занижалась.
На графике
Растёт вслед за онлайном и нагрузкой · число отложенных объектов по соединениям, объём отправки по соединениям
Где смотреть
Писать на сервере для каждого соединения число отправленных байтов за тик, лимит отправки (оценку пропускной способности), число отложенных и неотправленных объектов и время с последней отправки каждого объекта. В Unreal в Networking Insights видны размеры пакетов по соединениям и реплицируемые объекты внутри них
Подтверждает
Невидимый NPC долго откладывался в этом соединении, лимит этого соединения ниже, чем у других, и чем больше людей вокруг, тем больше отложенных объектов
Опровергает
Если отложенных объектов нет и этот NPC отправлен вовремя, проблема на этапах после отправки (буфер приёма, загрузка, настройки отображения). Если все соединения упираются в лимит, это проблема общего объёма отправки или архитектуры зоны видимости на сервере
Чем проверить
Нужны логи и метрики игрового сервера или клиента
Источников: 3
Actor Priority in Unreal EngineEpic Games Когда пропускная способность исчерпана, акторы для репликации выбираются по приоритету (расстояние, направление взгляда, время с последней репликации). Не все акторы реплицируются каждый раз
State SynchronizationGaffer On Games Накопление приоритета: объект, не попавший в текущий пакет, первым попадает в следующий, а лимит пропускной способности подстраивается в реальном времени
Networking Insights in Unreal EngineEpic Games Показывает размеры пакетов, отправленных и полученных по каждому соединению, и реплицируемые объекты и свойства внутри них
ID pt-clock-hold · Основной ответственный Команда разработки · Разработка клиента
Если клиент неверно оценивает серверное время, только что пришедшие данные объекта он откладывает как «ещё из будущего» или отбрасывает как «слишком старые».
Почему Оценка серверного времени у одного клиента сильно сбита (измерение во время загрузки, выход из режима сна) → Следствие Время, на которое ведётся интерполяция, не совпадает со временем в данных объекта → На экране Объект появляется с опозданием или стоит неподвижно
Основной ответственный Команда разработки · Разработка клиента
Команда разработки: задачи
Периодически заново синхронизировать время и при большом расхождении сразу сбрасывать оценку, не использовать значения, измеренные во время загрузки или сразу после выхода из сна.
На графике
Высоко только у некоторых · ошибка оценки серверного времени по клиентам
Где смотреть
Записывать на клиенте оценку серверного времени, RTT, моменты повторной синхронизации времени и число случаев, когда данные объекта были отложены или отброшены. Воспроизводить сразу после загрузки или выхода из сна
Подтверждает
Только у проблемного клиента ошибка оценки превышает порог сброса (в Unity hardResetThresholdSec, по умолчанию 0,2 с), есть записи о данных объекта, отложенных как будущие или отброшенных как прошлые, и после повторной синхронизации времени всё сразу нормализуется
Опровергает
Если ошибка оценки мала, а объекты появляются поздно, причина в бюджете отправки и приоритетах для каждого соединения или в загрузке
Чем проверить
Нужны логи и метрики игрового сервера или клиента
Источников: 2
NetworkTimeSystem class (Netcode for GameObjects 2.5)Unity Если расхождение времени превышает hardResetThresholdSec (по умолчанию 0,2 с), время выравнивается принудительно, а в обычном режиме понемногу ускоряется или замедляется через adjustmentRatio
ID rt-wireless · Основной ответственный Внешние стороны · Внешние стороны · Совместно Команда инфраструктуры · Серверная инфраструктура, Команда разработки · Разработка сервера, Команда разработки · Разработка клиента
Wi-Fi и мобильная сеть несколько раз повторяют передачу на беспроводном участке, а если и это не помогает, выбрасывают пакет. Выброшенный пакет TCP отправит повторно только спустя заметное время.
Почему Слабый сигнал или сильные помехи, передача на беспроводном участке срывается раз за разом → Следствие Если превышен лимит повторов беспроводного оборудования (обычно от нескольких до десяти с лишним раз), пакет выбрасывается → На экране Фриз на всё время ожидания повторной передачи TCP, следующие пакеты ждут в буфере приёма, затем перемотка
Основной ответственный Внешние стороны · Внешние стороны · Совместно Команда инфраструктуры · Серверная инфраструктура, Команда разработки · Разработка сервера, Команда разработки · Разработка клиента
Команда разработки: задачи
Сервер: включить TCP_NODELAY (при включённом Nagle у RACK нет следующих пакетов, по которым он определяет потерю), пока соединение ждёт повторной передачи, отправлять только самое свежее обновление состояния, без накопления старых (объём, который копится в ядре, ограничить через TCP_NOTSENT_LOWAT). Клиент: включить TCP_NODELAY (потери на пути ввода игрока к серверу восстанавливает ОС клиента), при серии потерь или скачке пинга показывать на экране состояние сети.
Команда инфраструктуры: задачи
Ускорить восстановление потерь с помощью RACK-TLP (предотвратить потери на беспроводном участке сервер не может, он может только быстрее их восстанавливать), проверить, что не изменены значения по умолчанию современных Linux net.ipv4.tcp_recovery=1 (RACK) и net.ipv4.tcp_early_retrans=3 (TLP).
Внешние стороны: задачи
Посоветовать игроку кабельное подключение, диапазоны 5 GHz или 6 GHz, другое место для роутера или другой радиоканал.
Цифры для ориентира
При потерях 1% на беспроводном участке пропадает 1 игровой пакет из 100. Если за 1 с приходит 10 пакетов, короткий фриз случается примерно раз в 10 с. Без RACK-TLP каждый такой фриз длится RTO (пинг + 200 ms и больше).
На графике
Высоко только у некоторых · доля повторных передач по соединениям, RTT (пинг) по соединениям
Где смотреть
С ПК игрока по несколько сотен раз пинговать адрес роутера (шлюза) и игровой сервер и сравнить потери и разброс задержки, затем переключиться на кабель или мобильный интернет и измерить снова. На сервере посмотреть в ss -ti retrans и rtt (среднее/разброс) соединения этого игрока
Подтверждает
Уже в ping до роутера видны потери или скачущая задержка, а на кабеле они исчезают. На сервере большие retrans и разброс RTT только у соединения этого игрока
Опровергает
Если до роутера всё чисто, а потери начинаются дальше, причина у провайдера или на маршруте («Переполнение очереди в узком месте (потери от перегрузки)», «Смена маршрута и неисправный путь ECMP»). Если ухудшение одновременно у многих игроков одного провайдера, начинать с участка провайдера
Чем проверить
Проверка на стороне игрока
Подробнее
Повторы в беспроводном оборудовании создают джиттер (каждый повтор добавляет несколько ms), а потерей становится только пакет, превысивший лимит повторов. Поэтому по мере ухудшения радиосвязи симптомы нарастают в таком порядке: «джиттер → редкие фризы → частые фризы». В момент перехода между точками доступа (AP), то есть при роуминге, пакеты могут теряться подряд от десятков ms до нескольких секунд. В мобильной сети участок до базовой станции сам многократно повторяет передачу, поэтому проблема там чаще проявляется скачками задержки на сотни ms. Потерь при этом немного.
net/wireless/core.cLinux kernel Лимит повторов по умолчанию в беспроводном стеке Linux: 7 для коротких кадров, 4 для длинных (dot11ShortRetryLimit, dot11LongRetryLimit)
Wi-Fi roaming support in Apple devicesApple При переходе на другую AP данные нельзя отправлять, пока не завершится аутентификация на новой AP, а в среде 802.1X это может занять несколько секунд
IP SysctlLinux kernel tcp_recovery по умолчанию 0x1 (RACK), tcp_early_retrans по умолчанию 3 (TLP включён), TCP_NOTSENT_LOWAT и tcp_notsent_lowat ограничивают объём ещё не отправленных данных
tcp(7) — Linux manual pageLinux man-pages TCP_NODELAY отключает алгоритм Нейгла, и даже мелкие данные отправляются сразу
ID rt-queue-drop · Основной ответственный Команда инфраструктуры · Сетевая инфраструктура · Совместно Внешние стороны · Внешние стороны, Команда разработки · Разработка клиента
Когда заполняется очередь в самом узком месте (в роутере, на стыке провайдеров, на линии связи ЦОД), новые пакеты выбрасываются.
Почему Видео, загрузки и трафик других пользователей забивают узкое место → Следствие Пока очередь заполнена, новые пакеты выбрасываются подряд (tail drop). Даже не выброшенные пакеты ждут в конце забитой очереди → На экране Разом пропадает несколько пакетов: долгий фриз, потом перемотка, чаще по вечерам
Все в одном доме, Один регион или провайдер, Весь сервер
Когда
Вечерний пик, При наплыве игроков
Ответственные
Основной ответственный Команда инфраструктуры · Сетевая инфраструктура · Совместно Внешние стороны · Внешние стороны, Команда разработки · Разработка клиента
Команда разработки: задачи
При серии потерь или скачке пинга показывать на экране состояние сети (с подсказкой, что через это же подключение, возможно, идёт большая загрузка).
Команда инфраструктуры: задачи
Обеспечить запас пропускной способности на линиях связи ЦОД, проверять счётчики отбрасываний в очереди (output drops) на наших линиях и портах коммутаторов, если забит участок провайдера, обходить его через другие линии или пиринг.
Внешние стороны: задачи
Посоветовать игрокам SQM на роутере (fq_codel, CAKE) и ECN (скорость снижается раньше, чем очередь переполнится), попросить провайдера расширить узкое место.
Цифры для ориентира
В момент переполнения очереди в течение десятков ms разом пропадает значительная часть входящих пакетов. Пакеты теряются подряд, легко теряется и повторная передача, поэтому дело часто доходит до RTO.
На графике
Высоко только в определённые часы · доля повторных передач, RTT (пинг)
Где смотреть
Разбить долю повторных передач на сервере (прирост TcpRetransSegs ÷ TcpOutSegs по nstat, запускаемому раз в минуту) и RTT соединений по регионам, провайдерам и времени суток и смотреть вместе с выходными отбрасываниями (ifOutDiscards) на наших линиях и портах коммутаторов. Запустить mtr в проблемный регион в час пик и в спокойное время и сравнить
Подтверждает
Доля повторных передач растёт только в вечерний пик, и перед потерями сначала растёт RTT (так выглядит заполнение очереди). В mtr только в час пик начиная с какого-то участка и до конца растут и потери, и задержка
Опровергает
Если перед потерями RTT не растёт, это «Отбрасывание избытка полисером». Если потери примерно одинаковы в любое время суток, это «Физические ошибки (неисправные кабели, оптические модули и разъёмы)» или «Смена маршрута и неисправный путь ECMP»
RFC 2863: The Interfaces Group MIBIETF ifOutDiscards: число исходящих пакетов, отброшенных без отправки, хотя ошибок не обнаружено (например, чтобы освободить место в буфере)
An Internet-Wide Analysis of Traffic PolicingGoogle Различие: при переполнении очереди до потерь сначала растут время ожидания и RTT, а полисинг отбрасывает избыток без роста RTT (SIGCOMM 2016)
ID rt-burst · Основной ответственный Команда разработки · Разработка сервера · Совместно Команда инфраструктуры · Серверная инфраструктура, Команда инфраструктуры · Сетевая инфраструктура
Когда сервер каждый тик разом выплёскивает обновления для тысяч игроков, маленький буфер коммутатора или мгновенный лимит облака переполняется меньше чем за 1 ms, и часть пакетов выбрасывается.
Почему В начале тика пакеты для всех игроков отправляются разом → Следствие Мгновенно переполняется буфер порта коммутатора, где сходится трафик нескольких серверов (от сотен KB до нескольких MB на порт), или лимит облачного инстанса (средняя загрузка при этом низкая) → На экране Телепортация и короткие фризы сразу у многих игроков, по средним метрикам причину не видно
Основной ответственный Команда разработки · Разработка сервера · Совместно Команда инфраструктуры · Серверная инфраструктура, Команда инфраструктуры · Сетевая инфраструктура
Команда разработки: задачи
Распределять отправку одного тика по всему тику (наплыв тысяч соединений в начале тика пейсинг по соединениям почти не сглаживает), разносить момент начала тика по серверам, для соединений с большими объёмами ограничивать скорость через SO_MAX_PACING_RATE.
Команда инфраструктуры: задачи
Серверы и ОС: ограничить общую скорость отправки сервера (шейпер в ОС сервера, tc в Linux), выплески одного соединения выравнивать пейсингом (очередь fq в Linux, BBR). Сеть: коммутаторы с большими буферами, проверять счётчики выходных отбрасываний на портах коммутаторов с коротким интервалом (по средней загрузке их не видно).
Цифры для ориентира
Порт 10 Gbps за 1 ms отправляет около 1,25 MB. Если тики нескольких серверов совпадают и их трафик сходится в один порт, буфер заполняется мгновенно.
На графике
Растёт вслед за онлайном и нагрузкой · выходные отбрасывания на портах коммутатора, доля повторных передач
Где смотреть
С интервалом в несколько секунд собирать выходные отбрасывания (ifOutDiscards) на порту коммутатора, к которому подключён сервер, и на порту уровнем выше, в облаке смотреть bw_out_allowance_exceeded и pps_allowance_exceeded в ethtool -S. Собрать повторные передачи за то же время через bcc tcpretrans и сопоставить
Подтверждает
Средняя загрузка по минутам низкая, но растут выходные отбрасывания или превышения allowance, и их число растёт вместе с онлайном и числом игроков в одном месте. Повторные передачи возникают в один и тот же момент на многих соединениях этого сервера и не привязаны к диапазонам IP определённых игроков (провайдер, регион)
Опровергает
Если на том же порту растут и ошибки CRC и ошибки приёма, это «Физические ошибки (неисправные кабели, оптические модули и разъёмы)». Если на принимающем сервере растут счётчики отбрасываний NIC или softnet dropped, это «Отбрасывание пакетов на принимающем сервере»
Чем проверить
Инструменты инфраструктуры (игровой код не нужен)
Подробнее
Пейсинг работает для каждого соединения отдельно. Наплыв, когда тысячи соединений в начале тика отправляют по одному-два пакета, пейсинг по соединениям почти не сглаживает, и игровому серверу приходится самому распределять моменты отправки. Зато когда одно соединение отправляет большой объём, NIC нарезает десятки KB данных на пакеты и отправляет их подряд (TSO), и такие выплески пейсинг распределяет хорошо.
tc-fq(8) — Linux manual pageiproute2 Очередь fq делает пейсинг для каждого сокета (соединения), SO_MAX_PACING_RATE задаёт максимальную скорость соединения
net/ipv4/tcp_bbr.cLinux kernel BBR задаёт pacing_rate по оценке пропускной способности узкого места
IP SysctlLinux kernel TCP подбирает размер кадра TSO под скорость потока (максимум 64 KB, tcp_min_tso_segs)
RFC 2863: The Interfaces Group MIBIETF ifOutDiscards: число исходящих пакетов, отброшенных без отправки, хотя ошибок не обнаружено (например, чтобы освободить место в буфере)
ID rt-policer · Основной ответственный Команда инфраструктуры · Сетевая инфраструктура · Совместно Команда инфраструктуры · Серверная инфраструктура, Команда разработки · Разработка сервера
Тарифы провайдеров, лимиты облачных инстансов и оборудование защиты от DDoS могут сразу отбрасывать пакеты сверх заданной скорости, не ставя их в очередь.
Почему Мгновенный объём передачи превышает разрешённую скорость или разрешённый всплеск (burst) → Следствие Пакеты сверх лимита отбрасываются сразу, без очереди (полисинг) → На экране В моменты больших всплесков пропадает сразу несколько пакетов: фриз, потом перемотка. Средняя скорость при этом ниже лимита
Весь сервер, Один регион или провайдер, Только у меня
Когда
При наплыве игроков, Вечерний пик
Ответственные
Основной ответственный Команда инфраструктуры · Сетевая инфраструктура · Совместно Команда инфраструктуры · Серверная инфраструктура, Команда разработки · Разработка сервера
Команда разработки: задачи
Распределять объём, который выплёскивается каждый тик, по всему тику, чтобы мгновенный объём передачи был ниже разрешённого всплеска, при упоре в лимит пакетов в секунду объединять сообщения одного тика в один пакет.
Команда инфраструктуры: задачи
Сеть: проверить счётчики превышения полисера на оборудовании, заменить полисер шейпером, увеличить разрешённый всплеск. Серверы и ОС: проверить метрики превышения облачных лимитов (в AWS bw_out_allowance_exceeded и pps_allowance_exceeded в ethtool -S), перейти на инстанс помощнее, включить пейсинг на сервере (очередь fq в Linux).
Цифры для ориентира
Шейпер (ставит пакеты в очередь и задерживает) увеличивает задержку, полисер (сразу отбрасывает) увеличивает потери. Игровое TCP-соединение от одной потери может встать на сотни ms, поэтому при кратком превышении лимита обычно сильнее влияет полисер.
На графике
Упор в лимит (плато) · объём отправки с коротким интервалом, счётчики превышения полисера и allowance
Где смотреть
Посмотреть счётчики превышения (exceed) и отбрасываний на оборудовании с полисером, в облаке bw_out_allowance_exceeded и pps_allowance_exceeded в ethtool -S. Для соединений с потерями посмотреть RTT непосредственно перед потерей по rtt в ss -ti или по захвату пакетов
Подтверждает
Счётчики превышения растут, а объём отправки на коротком интервале плоский, будто срезан на каком-то значении. Перед потерями RTT не растёт, и несколько пакетов пропадают разом только в моменты больших всплесков
Опровергает
Если перед потерями сначала растёт RTT, это переполнение очереди («Переполнение очереди в узком месте (потери от перегрузки)», «Переполнение неглубоких буферов всплесками отправки»). Если счётчики превышения не меняются, причина другая
An Internet-Wide Analysis of Traffic PolicingGoogle У передач под полисингом доля потерь в среднем в 6 раз выше, и той же цели можно добиться пейсингом или шейпингом. Различие: полисинг отбрасывает избыток без роста RTT, а при переполнении очереди RTT растёт ещё до потерь (SIGCOMM 2016)
ID rt-physical · Основной ответственный Команда инфраструктуры · Сетевая инфраструктура · Совместно Команда инфраструктуры · Серверная инфраструктура, Внешние стороны · Внешние стороны
Повреждённый кабель, запылённый оптический разъём или выработавший ресурс оптический модуль дают битовые ошибки, и оборудование молча выбрасывает испорченные пакеты.
Почему Из-за неисправного кабеля, оптического модуля или разъёма переворачиваются биты → Следствие Оборудование отбрасывает пакеты с неверной контрольной суммой (CRC) → На экране Только у тех, чей трафик идёт по этому пути, постоянно бывают короткие фризы с перемоткой, время суток не влияет
Основной ответственный Команда инфраструктуры · Сетевая инфраструктура · Совместно Команда инфраструктуры · Серверная инфраструктура, Внешние стороны · Внешние стороны
Команда инфраструктуры: задачи
Ошибки CRC копятся на принимающей стороне того направления, где повреждаются пакеты, поэтому проверять оба конца. Сеть: проверить счётчики CRC и ошибок приёма на портах оборудования, уровень оптического сигнала (информация об оптических модулях на коммутаторе), почистить оптические разъёмы, заменить кабель или оптический модуль. Серверы и ОС: проверить rx_crc_errors в ethtool -S на сервере (название у разных драйверов немного отличается) и уровень оптического сигнала (ethtool -m), заменить кабель или NIC на стороне сервера.
Внешние стороны: задачи
Если проблема на участке в доме игрока, посоветовать заменить сетевой кабель или роутер, если на линии провайдера, попросить провайдера проверить линию.
Цифры для ориентира
Даже 0,1% потерь означает один пакет из 1 000 игровых. Если по этому пути идёт трафик десятков игроков, кто-то ловит короткий фриз каждые несколько секунд. Битовые ошибки чаще задевают большие пакеты.
На графике
Высоко только у некоторых · число ошибок CRC по портам, доля повторных передач по серверам и портам
Где смотреть
Посмотреть счётчики CRC на обоих концах линка. На сервере rx_crc_errors в ethtool -S или crc в ip -s -s link, на коммутаторе ошибки FCS порта (dot3StatsFCSErrors) и ошибки приёма (ifInErrors). Для оптического линка посмотреть уровень принимаемого оптического сигнала через ethtool -m и в информации об оптических модулях на коммутаторе
Подтверждает
Ошибки CRC на одном порту стабильно растут независимо от времени суток, и высокая доля повторных передач только у серверов и соединений, идущих через этот порт. Уровень принимаемого оптического сигнала ниже, чем на других линках того же типа
Опровергает
Если CRC не меняются, а растут только выходные отбрасывания, это переполнение очереди («Переполнение неглубоких буферов всплесками отправки», «Переполнение очереди в узком месте (потери от перегрузки)»). Если поздние коллизии на одной стороне растут вместе с CRC на другой, это «Несовпадение дуплекса»
Чем проверить
Инструменты инфраструктуры (игровой код не нужен)
Источников: 3
Interface statisticsLinux kernel rx_crc_errors: число пакетов, которые принимающий интерфейс засчитал как ошибки CRC, смотрят через ip -s -s link и ethtool -S
ethtool(8) — Linux manual pageethtool -S показывает статистику NIC и драйвера, -m показывает EEPROM оптического модуля (SFP+, QSFP) и данные оптической диагностики
ID rt-duplex · Основной ответственный Команда инфраструктуры · Сетевая инфраструктура · Совместно Команда инфраструктуры · Серверная инфраструктура
Если на одной стороне включено автосогласование, а на другой скорость и дуплекс заданы жёстко, одна сторона работает в полудуплексе и под нагрузкой каждый раз теряет пакеты из-за коллизий.
Почему Скорость и дуплекс жёстко заданы только на одной стороне → Следствие Одна сторона работает в полном дуплексе, другая в полудуплексе, возникают коллизии и поздние коллизии → На экране Обычно всё нормально, но при росте трафика у всех, чей трафик идёт через это устройство, фриз, потом перемотка
Основной ответственный Команда инфраструктуры · Сетевая инфраструктура · Совместно Команда инфраструктуры · Серверная инфраструктура
Команда инфраструктуры: задачи
На обеих сторонах включить автосогласование или на обеих задать одинаковые значения. Сеть: проверить скорость и дуплекс в состоянии порта коммутатора, по счётчикам порта проверить, растут ли поздние коллизии на полудуплексной стороне и ошибки CRC и слишком короткие кадры (runt) на полнодуплексной. Серверы и ОС: проверить скорость и дуплекс через ethtool.
Цифры для ориентира
Для 1 Gbps по меди автосогласование обязательно, а на 10 Gbps и выше полудуплекса нет вообще. Поэтому сейчас проблема встречается в основном на старом оборудовании 100 Mbps и медленнее, на портах управления и на некоторых стыках линий связи.
На графике
Растёт вслед за онлайном и нагрузкой · поздние коллизии и ошибки CRC на порту, доля повторных передач
Где смотреть
Посмотреть фактические скорость и дуплекс на обеих сторонах линка. На сервере ethtool, запущенный только с именем интерфейса, на коммутаторе состояние порта или dot3StatsDuplexStatus по SNMP. Заодно посмотреть поздние коллизии (на сервере tx_window_errors, на коммутаторе dot3StatsLateCollisions) и ошибки CRC
Подтверждает
Одна сторона показывает полудуплекс, другая полный дуплекс. При каждом росте трафика на полудуплексной стороне растут поздние коллизии, а на полнодуплексной ошибки CRC
Опровергает
Если скорость и дуплекс на обеих сторонах совпадают, а растут только CRC, это «Физические ошибки (неисправные кабели, оптические модули и разъёмы)». На линках 10 Gbps и выше полудуплекса нет, поэтому для них эта причина исключается
IEEE P802.3ba ObjectivesIEEE 40- и 100-гигабитный Ethernet тоже поддерживают только полный дуплекс
Interface statisticsLinux kernel tx_window_errors: число передач, сорвавшихся из-за поздних коллизий (late collision), rx_crc_errors: число пакетов, принятых с ошибкой CRC
ethtool(8) — Linux manual pageethtool speed, duplex и autoneg в ethtool -s задают скорость, дуплекс и автосогласование, а с одним только именем интерфейса ethtool показывает текущие настройки
ID rt-host-drop · Основной ответственный Команда инфраструктуры · Серверная инфраструктура
Пакеты дошли до сервера, но выбрасываются: переполнен кольцевой буфер NIC (буфер, где ненадолго лежат пришедшие пакеты) или загружено до предела процессорное ядро, на котором ОС обрабатывает приём.
Почему Резкий наплыв игроков, все прерывания на одном ядре CPU, CPU steal на виртуальной машине, перегрузка виртуального коммутатора → Следствие Отбрасывание в кольцевом буфере (rx_missed_errors и др., название зависит от драйвера) или в очереди приёма ядра (softnet dropped) → На экране Когда игроков много, на всём сервере одновременно задержка ввода и короткие фризы
Основной ответственный Команда инфраструктуры · Серверная инфраструктура
Команда инфраструктуры: задачи
Добавить в мониторинг счётчики отбрасываний вроде rx_missed_errors из ethtool -S и dropped из /proc/net/softnet_stat, увеличить кольцевой буфер (ethtool -G), распределить RSS и прерывания по нескольким ядрам, разнести игровые потоки и ядра обработки приёма, держать запас CPU, на виртуальной машине проверить CPU steal и нагрузку виртуального коммутатора.
Цифры для ориентира
Пакеты, которые сервер получил и выбросил, повторно отправляет клиент. Поэтому в метриках повторных передач сервера проблема почти не видна и сначала проявляется в счётчиках отбрасываний вроде rx_missed_errors в ethtool -S (название зависит от драйвера) и в dropped из /proc/net/softnet_stat.
На графике
Упор в лимит (плато) · загрузка softirq по ядрам, счётчики отбрасываний NIC
Где смотреть
Посмотреть счётчики отбрасываний в ethtool -S (rx_missed_errors и др., у mlx5 rx_out_of_buffer и rx_discards_phy), missed в ip -s -s link, 2-й столбец (dropped) и 3-й столбец (time_squeeze) в /proc/net/softnet_stat, а через mpstat -P ALL посмотреть %soft (обработка программных прерываний) по ядрам. На виртуальной машине смотреть и %steal
Подтверждает
В часы наплыва игроков растут счётчики отбрасываний или softnet dropped, а %soft на ядре, обрабатывающем приём, упирается почти в 100% и выше не поднимается. На всех соединениях этого сервера одновременно запаздывает ввод
Опровергает
Если счётчики отбрасываний на сервере не меняются, а повторные передачи сосредоточены на соединениях определённого региона или провайдера, это потери на маршруте. Когда на маршруте теряются пакеты, отправленные сервером, растёт TcpRetransSegs в nstat на сервере, а эти счётчики не меняются
Чем проверить
Инструменты инфраструктуры (игровой код не нужен)
Источников: 10
Interface statisticsLinux kernel rx_missed_errors: число пакетов, которые хост не смог принять из-за нехватки буферов (в /proc/net/dev входит в drop), смотрят через ip -s -s link
Ethtool countersLinux kernel rx_out_of_buffer (нет буфера в очереди приёма) и rx_discards_phy (отброшено из-за нехватки буфера порта) драйвера mlx5
net/core/net-procfs.cLinux kernel /proc/net/softnet_stat: по строке на CPU, значения шестнадцатеричные, 2-й столбец dropped, 3-й столбец time_squeeze
Documentation for /proc/sys/net/Linux kernel netdev_max_backlog: лимит очереди приёма, куда складываются пакеты, если они приходят быстрее, чем ядро успевает их обрабатывать
proc_stat(5) — Linux manual pageLinux man-pages steal в /proc/stat: время, когда CPU использовала другая ОС в виртуализированной среде
mpstat(1) — Linux manual pagesysstat mpstat -P ALL показывает загрузку по ядрам, %soft означает время обработки программных прерываний, %steal означает время ожидания, пока гипервизор обслуживал другой виртуальный CPU
net/ipv4/proc.cLinux kernel TcpRetransSegs в выводе nstat (RetransSegs в разделе Tcp)
ID rt-stateful-fw · Основной ответственный Команда инфраструктуры · Сетевая инфраструктура · Совместно Команда инфраструктуры · Серверная инфраструктура, Команда разработки · Разработка сервера, Команда разработки · Разработка клиента
Файрвол или conntrack в Linux (функция, которая записывает проходящие соединения в таблицу) выбрасывает пакеты, если таблица заполнена или состояние соединения кажется ему неверным.
Почему Таблица отслеживания соединений заполнена (table full), или пакеты туда и обратно идут разными путями, и через файрвол проходит только одно направление (асимметричный маршрут) → Следствие Файрвол считает, что пакет относится к «неизвестному соединению» или несёт «номер последовательности вне окна», и отбрасывает его → На экране Когда таблица заполнена, новые подключения не проходят, а при расхождении маршрутов у игроков на этом маршруте после серии повторных передач дисконнект
При наплыве игроков, Сразу после входа или техработ, Изредка, случайно
Ответственные
Основной ответственный Команда инфраструктуры · Сетевая инфраструктура · Совместно Команда инфраструктуры · Серверная инфраструктура, Команда разработки · Разработка сервера, Команда разработки · Разработка клиента
Команда разработки: задачи
Сервер: на случай заполнения таблицы сдерживать наплыв подключений очередью на вход, переиспользовать соединения вместо повторяющихся коротких (включая вызовы между серверами), первым закрывать соединения без хартбитов. Клиент: если подключение не удалось или оборвалось, увеличивать интервал между попытками и добавлять случайный разброс (чтобы при заполненной таблице игроки не ломились обратно все разом).
Команда инфраструктуры: задачи
Сеть: увеличить таблицу отслеживания соединений на файрволе, исключить игровые порты из отслеживания соединений, настроить маршрутизацию так, чтобы трафик в обе стороны шёл через один и тот же файрвол, проверить настройки проверки окна TCP на файрволе. Серверы и ОС: увеличить таблицу в Linux (nf_conntrack_max), исключить игровые порты из отслеживания соединений (NOTRACK), проверить настройку проверки окна TCP (nf_conntrack_tcp_be_liberal), в AWS проверить ещё и conntrack_allowance_exceeded.
Цифры для ориентира
Лимит conntrack в Linux по умолчанию (nf_conntrack_max) в зависимости от объёма памяти составляет от десятков до сотен тысяч записей. Когда текущее число (nf_conntrack_count) доходит до лимита, в логе появляется «nf_conntrack: table full, dropping packet».
На графике
Упор в лимит (плато) · число записей conntrack (nf_conntrack_count), число неудачных новых подключений
Где смотреть
На серверах Linux посмотреть nf_conntrack_count и nf_conntrack_max, «nf_conntrack: table full, dropping packet» в dmesg, drop и invalid в /proc/net/stat/nf_conntrack (по строке на ядро, шестнадцатеричные значения). На файрволе посмотреть заполнение таблицы сессий и логи дропов, в AWS conntrack_allowance_exceeded в ethtool -S
Подтверждает
Число записей выходит на плато у лимита, и одновременно растут логи table full и drop или conntrack_allowance_exceeded. При асимметричном маршруте до лимита далеко, но invalid и логи дропов файрвола растут на соединениях определённого маршрута
Опровергает
Если до лимита далеко, а invalid и логи дропов не меняются, причина другая. Если в таблице есть место, но CPU или пакеты в секунду на файрволе упираются в потолок, это «Перегрузка промежуточного оборудования (файрвол, IPS, защита от DDoS)»
Чем проверить
Инструменты инфраструктуры (игровой код не нужен)
Источников: 5
Netfilter Conntrack Sysfs variablesLinux kernel nf_conntrack_max по умолчанию равен числу хеш-корзин (память÷16384, от 1 024 до 262 144), текущее число в nf_conntrack_count, nf_conntrack_tcp_be_liberal помечает как INVALID только RST вне окна
net/netfilter/nf_conntrack_core.cLinux kernel Когда таблица заполнена, пишется лог «nf_conntrack: table full, dropping packet» и пакет отбрасывается (растёт статистика drop), а пакеты, не соответствующие состоянию соединения, увеличивают статистику invalid
Amazon EC2 security group connection trackingAWS При превышении лимита отслеживаемых соединений на инстанс пакеты отбрасываются, это видно по conntrack_allowance_exceeded, рекомендация избегать асимметричных маршрутов
net/netfilter/nf_conntrack_standalone.cLinux kernel /proc/net/stat/nf_conntrack: по строке на ядро, шестнадцатеричные значения, столбцы entries, invalid, insert_failed, drop, early_drop и др.
ID rt-appliance-pps · Основной ответственный Команда инфраструктуры · Сетевая инфраструктура · Совместно Команда разработки · Разработка сервера
Файрволы, системы предотвращения вторжений (IPS) и оборудование защиты от DDoS проверяют каждый проходящий пакет. Как только поток превышает их возможности, необработанные пакеты выбрасываются.
Почему В часы пик и на событиях идёт больше сотен тысяч мелких игровых пакетов в секунду, или правила проверки слишком тяжёлые → Следствие Упор в лимит CPU или пакетов в секунду, оборудование отбрасывает пакеты. При ложном срабатывании блокируются и нормальные пакеты → На экране Фризы и телепортация одновременно на всех серверах за этим оборудованием, хуже всего при наплыве игроков
Основной ответственный Команда инфраструктуры · Сетевая инфраструктура · Совместно Команда разработки · Разработка сервера
Команда разработки: задачи
Передать команде инфраструктуры профиль игрового трафика (порты, размер пакетов, пакеты в секунду), собирать мелкие сообщения одного тика и отправлять разом, чтобы уменьшить число пакетов.
Команда инфраструктуры: задачи
Смотреть CPU, пакеты в секунду и счётчики дропов оборудования вместе с игровыми метриками, закладывать производительность оборудования из расчёта на мелкие пакеты, исключить игровые порты из тяжёлых проверок, подогнать правила защиты от DDoS под профиль игрового трафика.
Цифры для ориентира
Цифра «10 Gbps» в характеристиках оборудования часто указана для больших пакетов по 1 500 байт. Игровых пакетов размером около 100 байт при той же пропускной способности в 10 с лишним раз больше, поэтому лимит пакетов в секунду исчерпывается раньше, даже если линия связи выглядит свободной.
На графике
Упор в лимит (плато) · пакеты в секунду и загрузка CPU оборудования, число дропов на оборудовании
Где смотреть
Посмотреть счётчики CPU, пакетов в секунду и дропов на оборудовании и с одинаковым интервалом сравнить число пакетов на портах коммутаторов до и после оборудования. Наложить на тот же экран онлайн и долю повторных передач на серверах
Подтверждает
В часы пик и на событиях пакеты в секунду или CPU оборудования упираются в одно значение и выше не растут, из оборудования выходит меньше пакетов, чем входит, и одновременно растёт доля повторных передач на всех серверах за ним
Опровергает
Если число пакетов до и после оборудования совпадает и дропов на нём нет, причина другая. Если на сервере растут счётчики отбрасываний NIC или softnet dropped, это «Отбрасывание пакетов на принимающем сервере»
ID rt-mtu · Основной ответственный Команда инфраструктуры · Сетевая инфраструктура · Совместно Команда инфраструктуры · Серверная инфраструктура, Команда разработки · Разработка сервера
Если на промежуточном участке допустимый размер пакета уменьшился, а уведомление «слишком большой» (ICMP) блокируется, большие пакеты пропадают, сколько бы раз их ни отправляли повторно.
Почему На участке VPN или туннеля максимальный размер меньше, а уведомления о превышении размера блокируются файрволом → Следствие Отправитель, не зная причины, раз за разом повторно передаёт тот же большой пакет, RTO каждый раз удваивается → На экране Обычно всё нормально, но в моменты передачи больших данных (инвентарь, места скопления игроков, загрузка при входе) встают и все следующие мелкие пакеты: фриз, в итоге дисконнект или бесконечная загрузка
При определённом действии, Сразу после входа или техработ
Ответственные
Основной ответственный Команда инфраструктуры · Сетевая инфраструктура · Совместно Команда инфраструктуры · Серверная инфраструктура, Команда разработки · Разработка сервера
Команда разработки: задачи
Чтобы снизить размер на стороне сервера, задать в сокете максимальный размер сегмента (TCP_MAXSEG). Одного дробления сообщений в игровом коде недостаточно (TCP заново собирает отправляемые данные в куски размером MSS).
Команда инфраструктуры: задачи
Сеть: ограничить MSS на пограничном оборудовании (MSS clamping), разрешить ICMP о превышении размера (тип 3, код 4, fragmentation needed) на файрволах и в сетевых ACL облака. Серверы и ОС: настроить MTU пути, проверить, что ICMP о превышении размера не блокируется ни в файрволе сервера, ни в облачной группе безопасности, как последнюю страховку включить в Linux tcp_mtu_probing=1.
Цифры для ориентира
Обычно 1 500 байт, после туннеля около 1 400. Если один и тот же пакет повторно передаётся 5–6 раз, фриз длится больше 10 с.
На графике
Высоко только у некоторых · RTO и backoff по соединениям, число обрывов по регионам и провайдерам
Где смотреть
Посмотреть повторные передачи проблемного соединения в захвате пакетов на стороне сервера или через bcc tcpretrans -s (показывает номера последовательности), а через ss -ti посмотреть mss, pmtu и backoff этого соединения. С сервера отправить на адрес игрока маленький ping и ping на 1 500 байт с включённым DF (ping -M do -s 1472) и сравнить
Подтверждает
Пакеты, заполненные до MSS, с одним и тем же номером последовательности повторно передаются снова и снова с удваивающимся интервалом, а пакеты поменьше проходят. ICMP о превышении размера (фильтр Wireshark icmp.type == 3 and icmp.code == 4) не приходят, на маленький ping ответ есть, а большой ping с DF пропадает без ответа
Опровергает
Если вместе с большими пропадают и мелкие пакеты, это потери, не зависящие от размера («Переполнение очереди в узком месте (потери от перегрузки)», «Смена маршрута и неисправный путь ECMP»). Если ICMP о превышении размера приходят и pmtu в ss -ti уменьшается, поиск MTU пути работает правильно
Чем проверить
Инструменты инфраструктуры (игровой код не нужен)
Подробнее
С tcp_mtu_probing=1 чёрная дыра распознаётся только после нескольких секунд таймаутов повторной передачи (соответствует tcp_retries1=3), и лишь тогда MSS снижается до 1 024 байт. Всё это время фриз, поэтому tcp_mtu_probing оставляют последней страховкой. В первую очередь нужно ограничение MSS, которое предотвращает проблему заранее.
Источников: 15
RFC 1191: Path MTU discoveryIETF Поиск MTU пути: о слишком большом пакете сообщает ICMP «fragmentation needed and DF set» (тип 3, код 4)
IP SysctlLinux kernel tcp_mtu_probing: 0 выключено, 1 только при обнаружении чёрной дыры, 2 всегда (начальный MSS tcp_base_mss). tcp_retries1 по умолчанию 3
net/ipv4/tcp_timer.cLinux kernel Если повторные передачи по RTO идут tcp_retries1 раз подряд, это считается обнаружением чёрной дыры: включается поиск MTU и MSS снижается
iptables-extensions(8) — Linux manual pagenetfilter TCPMSS --clamp-mss-to-pmtu: обход проблемы, когда большие пакеты застревают на участке, блокирующем ICMP, через ограничение MSS в SYN
tcp(7) — Linux manual pageLinux man-pages TCP_MAXSEG: максимальный размер сегмента исходящих пакетов. Если задать его до подключения, меняется и MSS, который сообщается другой стороне
ping(8) — Linux manual pageiputils -M do включает DF и не отправляет пакеты больше известного ядру MTU пути, -s задаёт размер данных (8 байт заголовка ICMP сверх него)
ID rt-mapping · Основной ответственный Команда разработки · Разработка клиента · Совместно Команда разработки · Разработка сервера, Команда инфраструктуры · Сетевая инфраструктура, Команда инфраструктуры · Серверная инфраструктура
Если промежуточное оборудование удаляет запись неактивного соединения (запись о том, куда пересылать это соединение), следующий отправленный пакет не доходит. Повторные передачи идут, пока соединение не оборвётся, или оборудование возвращает отказ в соединении (RST), и связь рвётся сразу.
Почему Соединение, по которому какое-то время не ходят пакеты (игрок отошёл, сидит в лобби) → Следствие NAT роутера, CGNAT провайдера, файрвол, балансировщик нагрузки или облачная группа безопасности удаляют неактивную запись → На экране Как только игрок снова начинает двигаться, идут повторные передачи и затем дисконнект, или дисконнект сразу
Основной ответственный Команда разработки · Разработка клиента · Совместно Команда разработки · Разработка сервера, Команда инфраструктуры · Сетевая инфраструктура, Команда инфраструктуры · Серверная инфраструктура
Команда разработки: задачи
Клиент: слать хартбиты с интервалом не больше половины самого короткого таймаута простоя (запись в роутере игрока и в CGNAT провайдера надёжно обновляют только пакеты, исходящие изнутри, а таймауты мы изменить не можем, поэтому слать должен клиент), при обрыве автоматически переподключаться. Сервер: отвечать на хартбиты и, если их нет определённое время, первым закрывать соединение (сократить интервал TCP keepalive опциями сокета вроде TCP_KEEPIDLE, быстрее замечать обрыв через TCP_USER_TIMEOUT), продолжать сессию по токену сессии.
Команда инфраструктуры: задачи
Сеть: собрать таймауты простоя файрволов и балансировщиков на маршруте и передать команде разработки, на наших файрволах и балансировщиках при необходимости увеличить. Серверы и ОС: проверить время отслеживания соединений в облачной группе безопасности и передать команде разработки.
Цифры для ориентира
Сколько держится запись TCP, зависит от устройства: от нескольких минут до нескольких часов. Если облачная группа безопасности отслеживает соединения, у типов инстансов AWS Nitro v6 запись удаляется по умолчанию через 350 с (у остальных типов через 5 дней, см. причину «Истечение отслеживания соединений в облачной группе безопасности»). TCP keepalive в Linux по умолчанию срабатывает так: «проверить после 2 часов простоя», а это позже, чем у большинства устройств.
На графике
Массовый обрыв соединений · число обрывов, время бездействия перед обрывом
Где смотреть
Посмотреть последние минуты оборвавшихся соединений в захвате пакетов на стороне сервера, у живых соединений смотреть время простоя по lastsnd и lastrcv в ss -ti (сколько ms прошло с последней отправки и последнего приёма). Заодно смотреть TcpExtTCPAbortOnTimeout в nstat (сколько соединений брошено по истечении таймера)
Подтверждает
У каждого оборвавшегося соединения время простоя перед обрывом превысило примерно одно и то же значение (таймаут простоя устройства на маршруте, например 350 с в группе безопасности инстансов AWS Nitro v6), и с первого пакета после простоя идут одни повторные передачи без ACK, пока отправитель не прекратит попытки, или сразу возвращается RST
Опровергает
Если обрывы бывают и во время игры независимо от времени простоя, причина другая («Смена маршрута и неисправный путь ECMP», «Отбрасывание пакетов файрволом или conntrack»). Если хартбиты по соединению ходят с интервалом не больше половины самого короткого таймаута простоя, эта причина исключается
Чем проверить
Инструменты инфраструктуры (игровой код не нужен)
Источников: 8
RFC 5382: NAT Behavioral Requirements for TCPIETF Рекомендация: таймаут простоя TCP-соединения в NAT должен быть не меньше 2 часов 4 минут (с учётом того, что устройство может удалить неактивную сессию раньше)
Amazon EC2 security group connection trackingAWS Таймаут отслеживания неактивных TCP-соединений по умолчанию: 350 с у типов инстансов Nitro v6, 432 000 с (5 дней) у остальных. Рекомендация слать keepalive с интервалом меньше 5 минут
IP SysctlLinux kernel tcp_keepalive_time по умолчанию 2 часа
tcp(7) — Linux manual pageLinux man-pages TCP_KEEPIDLE (время простоя до начала keepalive), TCP_USER_TIMEOUT (сколько ждать подтверждения данных, прежде чем закрыть соединение)
RFC 5482: TCP User Timeout OptionIETF Пользовательский таймаут TCP: через сколько времени без подтверждения отправленных данных закрывать соединение
ss(8) — Linux manual pageiproute2 lastsnd и lastrcv в ss -i: время с последней отправки и последнего приёма (ms)
SNMP counterLinux kernel TcpExtTCPAbortOnTimeout: сколько TCP-соединений брошено без RST по истечении таймера
ID rt-path · Основной ответственный Команда инфраструктуры · Сетевая инфраструктура · Совместно Команда разработки · Разработка сервера, Внешние стороны · Внешние стороны
Пакеты пропадают в течение нескольких секунд, пока меняется интернет-маршрут, или постоянно на соединениях, попавших на неисправный путь среди нескольких путей ECMP.
Почему Пересчёт маршрутов BGP или неисправное оборудование либо линия связи на одном из нескольких путей (ECMP, LAG) → Следствие Временные потери во время переключения маршрута или постоянные потери только у соединений на этом пути → На экране Внезапный фриз на несколько секунд, потом перемотка, или «после перезахода лучше» (соединение попало на другой путь)
Основной ответственный Команда инфраструктуры · Сетевая инфраструктура · Совместно Команда разработки · Разработка сервера, Внешние стороны · Внешние стороны
Команда разработки: задачи
Записывать статистику повторных передач по соединениям (TCP_INFO), чтобы можно было найти IP, порт и время у пострадавших игроков, не рвать сразу соединение, вставшее на несколько секунд.
Команда инфраструктуры: задачи
Отслеживать долю повторных передач по регионам и провайдерам, проверять, меняется ли путь при перезаходе, иметь линии нескольких провайдеров, проверить пути ECMP и LAG на нашем оборудовании на неисправные линки, измерять маршрут через тот же TCP-порт, что и игра (mtr --tcp --port. Путь выбирается по адресу и порту, поэтому обычный ping может пойти другим путём и показать, что всё в порядке).
Внешние стороны: задачи
Сообщить провайдеру о неисправном пути, приложив результаты измерения маршрута через тот же TCP-порт и сравнение до и после перезахода.
На графике
Ступенька вверх с определённого момента · RTT (пинг), доля повторных передач по регионам и провайдерам
Где смотреть
Собрать повторные передачи по соединениям через bcc tcpretrans -c и выделить адреса и порты пострадавших игроков, затем запустить mtr через тот же TCP-порт, что и игра (mtr -T -P PORT), с сервера к игроку и от игрока к серверу и сравнить. Сравнить и результаты до и после перезахода
Подтверждает
С определённого момента RTT региона или провайдера меняется ступенькой и на несколько секунд сгущаются потери, или даже внутри одного провайдера постоянно повторно передают только некоторые соединения (сочетания адреса и порта), а перезаход помогает. Бывает, что обычный ping в порядке, а потери видны только в TCP mtr
Опровергает
Если в вечерний пик ухудшаются все соединения этого провайдера, это «Переполнение очереди в узком месте (потери от перегрузки)». Если плохо только у одного игрока и потери начинаются уже в ping до роутера, это «Потери на беспроводном участке»
ID rt-spurious-delay · Основной ответственный Внешние стороны · Внешние стороны · Совместно Команда инфраструктуры · Серверная инфраструктура, Команда разработки · Разработка клиента
Пакет цел и лишь ненадолго сильно задерживается. Если эта задержка дольше RTO, отправитель считает пакет потерянным и передаёт его повторно.
Почему Bufferbloat, энергосбережение Wi-Fi, переключение состояний радиомодуля в мобильной сети или пауза виртуальной машины дают мгновенную задержку в сотни ms → Следствие RTO истекает раньше, происходит повторная передача, вскоре приходит и оригинал (получатель получает дубликат) → На экране Фриз и перемотку вызывает сам скачок задержки. Ложная повторная передача почти не удлиняет фриз, она только поднимает метрики повторных передач, и её принимают за потери
Основной ответственный Внешние стороны · Внешние стороны · Совместно Команда инфраструктуры · Серверная инфраструктура, Команда разработки · Разработка клиента
Команда разработки: задачи
На клиентах с Android 10 и новее запрашивать во время игры режим Wi-Fi с низкой задержкой (блокировка Wi-Fi WIFI_MODE_FULL_LOW_LATENCY, действует, только когда экран включён и игра на переднем плане), чтобы уменьшить скачки задержки из-за энергосбережения.
Команда инфраструктуры: задачи
Избегать инстансов с burst-производительностью, не занижать сильно минимальный RTO, оставить включёнными F-RTO и временные метки (tcp_frto, tcp_timestamps), смотреть метрики повторных передач вместе с TCPSpuriousRTOs и TCPDSACKRecv из nstat, чтобы не принять их за потери.
Внешние стороны: задачи
Чтобы уменьшить сами скачки задержки, посоветовать игрокам SQM на роутере и отключение энергосбережения Wi-Fi.
Цифры для ориентира
Linux с помощью F-RTO обнаруживает ложные RTO и может отменить снижение скорости отправки. Проверяют по TCPSpuriousRTOs в nstat (сколько RTO признано ложными) и TCPDSACKRecv (сколько раз получатель сообщил «это уже получено»).
На графике
Случайные всплески · RTT (пинг), число ложных RTO
Где смотреть
Запуская nstat раз в минуту, смотреть вместе прирост TcpExtTCPTimeouts (истечения RTO), TcpExtTCPSpuriousRTOs, TcpExtTCPDSACKRecv и TcpExtTCPLostRetransmit. Если есть захват пакетов, использовать фильтр Wireshark tcp.analysis.spurious_retransmission
Подтверждает
Когда растут RTO, вместе с ними растут TcpExtTCPSpuriousRTOs или TcpExtTCPDSACKRecv, и в те же моменты RTT подскакивает до сотен ms. В захвате на стороне получателя есть и оригинал, и повторная передача
Опровергает
Если TcpExtTCPSpuriousRTOs и DSACK не меняются, а растёт TcpExtTCPLostRetransmit (потеряна и повторная передача), это реальные потери. Если RTT не скачет, а DSACK стабильно много, это «Ложные быстрые повторные передачи из-за нарушения порядка»
WifiManagerAndroid (Google) WIFI_MODE_FULL_LOW_LATENCY (API 29, Android 10): блокировка Wi-Fi с низкой задержкой, действует, только когда устройство подключено к AP, экран включён и приложение на переднем плане
net/ipv4/proc.cLinux kernel Названия счётчиков в выводе nstat: TCPTimeouts, TCPSpuriousRTOs, TCPDSACKRecv, TCPLostRetransmit
net/ipv4/tcp_timer.cLinux kernel TCPTimeouts растёт при истечении таймера повторной передачи (RTO)
ID rt-reorder · Основной ответственный Команда инфраструктуры · Сетевая инфраструктура · Совместно Команда инфраструктуры · Серверная инфраструктура
Если на нескольких путях или агрегированных линках порядок пакетов меняется, получатель дублирующими ACK сообщает «пакета не хватает», и отправитель повторно отправляет пакеты, которые не терялись.
Почему Порядок перемешивают оборудование с балансировкой по отдельным пакетам, LAG (агрегирование линков) с распределением по пакетам и моменты смены маршрута → Следствие Следующие пакеты приходят раньше, накапливаются 3 дублирующих ACK → быстрая повторная передача → На экране На редкие игровые пакеты почти не влияет. Медленнее идут крупные обновления в местах скопления игроков и загрузка патчей, иногда микрофризы
Основной ответственный Команда инфраструктуры · Сетевая инфраструктура · Совместно Команда инфраструктуры · Серверная инфраструктура
Команда инфраструктуры: задачи
Сеть: балансировка по соединениям вместо балансировки по пакетам (ECMP и LAG по хешу адресов и портов). Серверы и ОС: использовать RACK (обнаружение потерь по времени, устойчиво к нарушению порядка. Обнаружив ложную повторную передачу по DSACK, автоматически расширяет допуск на нарушение порядка), проверить степень нарушения порядка, которую Linux автоматически оценивает для каждого соединения (значение reordering в ss -ti, начальное значение tcp_reordering=3).
На графике
Высоко с самого начала · число обнаруженных нарушений порядка, число полученных DSACK
Где смотреть
Посмотреть в nstat TcpExtTCPSACKReorder и TcpExtTCPTSReorder (сколько раз обнаружено нарушение порядка) и TcpExtTCPDSACKRecv, по соединениям смотреть reordering (выводится, если не равно 3) и reord_seen в ss -ti. В захвате пакетов использовать фильтр Wireshark tcp.analysis.out_of_order
Подтверждает
Счётчики нарушения порядка и DSACK стабильно растут независимо от времени суток, а у соединений через определённый путь или оборудование значение reordering больше 3. В захвате на стороне получателя следующий пакет приходит первым, а предыдущий тоже вскоре доходит
Опровергает
Если счётчики нарушения порядка не меняются, а растёт TcpExtTCPLostRetransmit, это реальные потери. Если DSACK растёт только в моменты скачков RTT, это «Ложные повторные передачи из-за скачков задержки»
IP SysctlLinux kernel Начальное значение tcp_reordering 3 (для каждого соединения автоматически подстраивается вплоть до tcp_max_reordering), настройка RACK в tcp_recovery
misc/ss.ciproute2 ss -ti выводит reordering:значение, если reordering соединения отличается от значения по умолчанию 3, и reord_seen:число, если соединение сталкивалось с нарушением порядка
SNMP counterLinux kernel TcpExtTCPSACKReorder и TcpExtTCPTSReorder (обнаружение нарушения порядка), TcpExtTCPDSACKRecv (число полученных DSACK), TcpExtTCPLostRetransmit (повторно отправленный пакет снова потерян)
include/uapi/linux/tcp.hLinux kernel tcpi_reord_seen в tcp_info: сколько раз соединение сталкивалось с нарушением порядка
ID rt-ack-path · Основной ответственный Внешние стороны · Внешние стороны · Совместно Команда разработки · Разработка клиента
Данные дошли нормально, но если ACK «получено» задерживается или теряется в забитой очереди отдачи, отправитель считает данные потерянными и передаёт их повторно.
Почему Дома отдачу забивает выгрузка видео или облачный бэкап → Следствие ACK задерживаются в очереди роутера на сотни ms или выбрасываются при её переполнении → На экране Игровые пакеты от сервера в основном приходят вовремя. Ввод игрока стоит в той же очереди отдачи и запаздывает: задержка ввода и откидывание назад, иногда ложные повторные передачи
Основной ответственный Внешние стороны · Внешние стороны · Совместно Команда разработки · Разработка клиента
Команда разработки: задачи
При скачке пинга показывать на экране состояние сети и подсказку «Проверьте, какие программы сейчас что-то выгружают».
Внешние стороны: задачи
Посоветовать игрокам SQM на роутере, чтобы очередь отдачи была короткой, приоритет для мелких пакетов (ACK) и ограничение скорости отдачи (выгрузка видео, облачный бэкап).
Цифры для ориентира
Каждый следующий ACK подтверждает и предыдущие, поэтому потеря нескольких ACK обычно не страшна. Проблема в задержке ACK в очереди.
На графике
Высоко только у некоторых · RTT (пинг) по соединениям
Где смотреть
С ПК игрока сравнить ping до игрового сервера при включённой и выключенной выгрузке (видео, облачный бэкап). На сервере посмотреть rtt соединения этого игрока в ss -ti
Подтверждает
Только во время выгрузки ping поднимается до сотен ms и появляются задержка ввода и откидывание назад, а после остановки выгрузки всё быстро возвращается. На сервере в это время растёт и rtt этого соединения
Опровергает
Если потери и задержка появляются независимо от выгрузки, это «Потери на беспроводном участке» или причина на маршруте. Если запаздывает только направление от сервера к игроку и выгрузка ни при чём, это «Переполнение очереди в узком месте (потери от перегрузки)»
Чем проверить
Проверка на стороне игрока
Источников: 4
RFC 3449: TCP Performance Implications of Network Path AsymmetryIETF На асимметричных линиях с узкой отдачей задержка или потеря ACK снижает производительность TCP; ACK подтверждают кумулятивно, поэтому потерю части из них покрывают следующие; меры вроде приоритетного планирования ACK
Smart Queue ManagementBufferbloat.net Управление очередью и шейпинг на роутере держат очередь короткой
ID rt-rto-setting · Основной ответственный Команда инфраструктуры · Серверная инфраструктура · Совместно Команда разработки · Разработка сервера
Если слишком занизить минимальный RTO, от малейшей задержки возникают ложные повторные передачи, а значение по умолчанию (200 ms) для игры слишком велико, и каждая потеря даёт долгий фриз.
Почему Минимальный RTO сильно занижен под ЦОД, или на интернет-участке оставлено значение по умолчанию → Следствие Если мало, лавина повторных передач даже от мгновенной задержки, если много, долгое ожидание при каждой потере → На экране При значении по умолчанию каждая потеря даёт фриз на сотни ms, потом перемотку. Если слишком занизить, фризы короче, но резко растут ложные повторные передачи и линия связи загружается зря
Основной ответственный Команда инфраструктуры · Серверная инфраструктура · Совместно Команда разработки · Разработка сервера
Команда разработки: задачи
В Linux 6.15 и новее рассмотреть снижение потолка RTO для игровых соединений через TCP_RTO_MAX_MS (время до отказа от соединения тоже сокращается, поэтому вместе с этим задать время признания обрыва через TCP_USER_TIMEOUT), снижать минимальный RTO опцией сокета TCP_RTO_MIN_US (6.15 и новее) только для внутренних соединений между серверами, рассмотреть опцию сокета TCP_THIN_LINEAR_TIMEOUTS, чтобы только у игровых соединений RTO не удваивался при серии таймаутов.
Команда инфраструктуры: задачи
Снижать rto_min по маршрутам только для внутренних соединений между серверами, на интернет-участке оставить значение по умолчанию и компенсировать настройками RACK-TLP и thin stream (tcp_thin_linear_timeouts).
Цифры для ориентира
В Linux RTO = время пути туда и обратно + max(200 ms, разброс RTT×4). После каждой неудачи удваивается, максимум 120 с. В Linux 6.15 и новее этот потолок можно снизить до 1 с через TCP_RTO_MAX_MS.
На графике
Высоко с самого начала · RTO по соединениям, число ложных RTO
Где смотреть
Посмотреть настройку минимального RTO на сервере (rto_min в ip route show, в Linux 6.11 и новее sysctl net.ipv4.tcp_rto_min_us), rto и rtt в ss -ti и прирост TcpExtTCPSpuriousRTOs в nstat
Подтверждает
На сервере с заниженным минимумом rto интернет-соединений вплотную прижат к rtt, и TcpExtTCPSpuriousRTOs сильно растёт. При значении по умолчанию rto игровых соединений больше rtt на 200 ms и более, и каждая потеря даёт фриз на это время
Опровергает
Если rto соответствует расчёту по умолчанию (около rtt + 200 ms) и ложных RTO мало, но фризы необычно долгие, дело в сериях потерь или способе восстановления («Медленное восстановление потерь в thin stream», «Удаление опций TCP промежуточным оборудованием»)
IP SysctlLinux kernel tcp_rto_min_us по умолчанию 200000 (приоритет у опции маршрута rto_min и опции сокета TCP_RTO_MIN_US), tcp_rto_max_ms от 1 000 до 120 000 (по умолчанию 120 000), tcp_thin_linear_timeouts
ID rt-thin · Основной ответственный Команда разработки · Разработка сервера · Совместно Команда инфраструктуры · Серверная инфраструктура, Команда разработки · Разработка клиента
Когда мелкие пакеты отправляются редко, как в играх, RTO наступает раньше, чем соберутся «3 следующих пакета». От тех же потерь поток стоит намного дольше, чем при больших передачах.
Почему Интервал между пакетами около 100 ms, поэтому неподтверждённых пакетов (in-flight) всего несколько → Следствие Чтобы собрались 3 дублирующих ACK, нужно больше 300 ms, поэтому раньше срабатывает RTO (пинг + 200 ms), при серии потерь он удваивается → На экране От одной потери фриз около 0,3 с, если потеряна и повторная передача, фриз почти на 1 с, потом перемотка
Основной ответственный Команда разработки · Разработка сервера · Совместно Команда инфраструктуры · Серверная инфраструктура, Команда разработки · Разработка клиента
Команда разработки: задачи
Сервер: включить TCP_NODELAY (при включённом Nagle у RACK нет следующих пакетов, по которым он принимает решение), пакеты реального времени отправлять по UDP со своей схемой повторных передач. Клиент: включить TCP_NODELAY, пакеты реального времени отправлять так же, как сервер (UDP).
Команда инфраструктуры: задачи
Использовать RACK-TLP (по умолчанию в современных Linux), через tcp_thin_linear_timeouts не давать RTO удваиваться при серии таймаутов.
Цифры для ориентира
При интервале пакетов 100 ms и пинге 60 ms до быстрой повторной передачи около 360 ms (пока не придут 3 следующих пакета и не вернётся их подтверждение), а RTO около 260 ms. С RACK пакет отправляется повторно, как только возвращается подтверждение следующего пакета, примерно через 160 ms. Если интервал пакетов больше 200 ms, RACK тоже не быстрее RTO.
На графике
Провал, затем пачка · объём приёма по соединениям, число истечений RTO
Где смотреть
Сравнить прирост TcpExtTCPTimeouts (истечения RTO), TcpExtTCPFastRetrans (быстрые повторные передачи), TcpExtTCPLossProbes и TcpExtTCPLossProbeRecovery (TLP) в nstat и посмотреть rto и backoff игровых соединений в ss -ti. Также проверить значения net.ipv4.tcp_recovery, tcp_early_retrans и tcp_sack на сервере
Подтверждает
Среди повторных передач истечений RTO больше, чем быстрых повторных передач, и у игровых соединений часто backoff больше 0 (соединение переживает RTO). Во время фриза принятый объём равен 0, а после восстановления всё приходит разом
Опровергает
Если большие передачи на том же сервере стоят так же долго, проблема в самих потерях и от формы соединения не зависит. Если проблема сосредоточена на соединениях без SACK и временных меток, это «Удаление опций TCP промежуточным оборудованием»
Чем проверить
Инструменты инфраструктуры (игровой код не нужен)
Подробнее
Раньше в Linux была и опция повторной передачи по одному дублирующему ACK для thin stream (tcp_thin_dupack), но в 2017 году её удалили, и теперь эту роль выполняет RACK. Если Nagle включён (TCP_NODELAY выключен), то, пока отправитель ждёт подтверждения потерянного пакета, новые пакеты тоже не уходят. У RACK не остаётся следующих пакетов для решения, и соединение ждёт RTO.
Источников: 11
Thin-streams and TCPLinux kernel У thin stream (редкие потоки вроде игровых) быстрая повторная передача работает плохо, и восстановление зависит от длинного таймаута; критерий: меньше 4 неподтверждённых пакетов (in-flight)
RFC 8985: The RACK-TLP Loss Detection Algorithm for TCPIETF RACK определяет потерю по тому, что дошёл пакет, отправленный позже; ожидание TLP равно 2·SRTT (если неподтверждённый пакет один, добавляется запас на отложенный ACK)
net/ipv4/proc.cLinux kernel Названия счётчиков в выводе nstat: TCPTimeouts, TCPFastRetrans, TCPLossProbes, TCPLossProbeRecovery
net/ipv4/tcp_timer.cLinux kernel TCPTimeouts растёт при истечении таймера повторной передачи (RTO)
SNMP counterLinux kernel TcpExtTCPFastRetrans (повторные передачи вне состояния Loss), TcpExtTCPLossProbes (отправлен TLP), TcpExtTCPLossProbeRecovery (потеря восстановлена через TLP)
ID rt-sack-stripped · Основной ответственный Команда инфраструктуры · Сетевая инфраструктура · Совместно Команда инфраструктуры · Серверная инфраструктура
Если некоторые файрволы или ускорители удаляют или меняют опции TCP, то при потере нескольких пакетов они восстанавливаются по одному за RTT или окно (сколько можно отправить за раз) становится маленьким, и передача замедляется.
Почему «Нормализация TCP» на файрволе или старый ускоритель удаляют опции SACK, временных меток и масштабирования окна → Следствие Если потеряно несколько пакетов, они восстанавливаются по одному за RTT, окно ограничено 64 KB → На экране Каждая потеря даёт намного более долгий фриз (без SACK нельзя использовать и RACK-TLP), после которого перемотка. Большие передачи вроде патчей тоже идут медленно
Основной ответственный Команда инфраструктуры · Сетевая инфраструктура · Совместно Команда инфраструктуры · Серверная инфраструктура
Команда инфраструктуры: задачи
Сеть: отключить нормализацию TCP на этом оборудовании, проверить и рандомизацию номеров последовательности на файрволе, сравнить опции SYN по захватам пакетов на обоих концах. Серверы и ОС: проверить в ss -ti, не сосредоточены ли соединения без sack и wscale на определённом маршруте (ПК с Windows в зависимости от настроек не используют ts, поэтому отсутствие только ts может быть нормой), проверить, что net.ipv4.tcp_sack на сервере равен 1.
На графике
Высоко с самого начала · число восстановлений, начатых без SACK (TcpExtTCPRenoRecovery)
Где смотреть
Проверить в ss -ti, есть ли у каждого соединения отметки sack и wscale, и посмотреть в nstat соотношение TcpExtTCPRenoRecovery (восстановления без SACK) и TcpExtTCPSackRecovery, а также TcpExtTCPSACKDiscard (число SACK-блоков, выброшенных как несогласованные). На подозрительном маршруте захватить SYN на обоих концах и сравнить опции (tcp.options.sack_perm в Wireshark и др.)
Подтверждает
sack и wscale отсутствуют только у соединений через определённый маршрут или оборудование, и доля TcpExtTCPRenoRecovery высокая. Опция разрешения SACK, которая была в SYN на стороне отправителя, отсутствует в SYN на стороне получателя. Если причина в рандомизации номеров последовательности, опции на месте, но растёт TcpExtTCPSACKDiscard
Опровергает
Если sack нет у всех соединений, сначала проверить значение net.ipv4.tcp_sack на сервере. Если опции целы и TcpExtTCPSACKDiscard не меняется, медленное восстановление объясняется чем-то другим («Медленное восстановление потерь в thin stream»)
Чем проверить
Инструменты инфраструктуры (игровой код не нужен)
Подробнее
SACK может сломаться, даже если опции сохранились. Если рандомизация номеров последовательности на файрволе (sequence randomization) меняет номера только в заголовке и оставляет прежними номера внутри SACK, отправитель выбрасывает несогласованные SACK. Тот же результат, если в 2019 году из-за уязвимости SACK на сервере его отключили через tcp_sack=0 и забыли.
ID rt-zero-window · Основной ответственный Команда разработки · Разработка клиента · Совместно Команда разработки · Разработка сервера, Команда инфраструктуры · Серверная инфраструктура
Если программа-получатель не успевает вовремя читать сокет и буфер заполняется, отправитель останавливает передачу и шлёт только пробы нулевого окна. С линией связи это не связано.
Почему Кадр на клиенте завис или поток сервера заблокирован, и сокет не читается → Следствие Окно приёма становится 0, отправитель останавливает передачу и шлёт только пробы (интервал постепенно растёт) → На экране Фриз, потом перемотка. В захвате пакетов видно «ZeroWindow», потерь нет
Основной ответственный Команда разработки · Разработка клиента · Совместно Команда разработки · Разработка сервера, Команда инфраструктуры · Серверная инфраструктура
Команда разработки: задачи
В захвате пакетов сначала найти сторону, отправившую ZeroWindow (ту, что не успевает читать сокет), читать сетевые данные непрерывно в отдельном потоке, задать подходящий размер буфера приёма. Клиент: устранить причины зависания кадров вроде загрузки и GC. Сервер: устранить причины блокировки потока, читающего сокет.
Команда инфраструктуры: задачи
Добавить в мониторинг TcpExtTCPToZeroWindowAdv из nstat на сервере (сколько раз сервер объявил окно приёма равным 0; если растёт, проблема на стороне сервера, передать разработке сервера), предоставлять захваты пакетов на стороне сервера.
На графике
Провал, затем пачка · объём приёма по соединениям, число нулевых окон
Где смотреть
В захвате пакетов найти фильтром Wireshark tcp.analysis.zero_window сторону, объявившую окно 0. В nstat на сервере смотреть отдельно TcpExtTCPToZeroWindowAdv (сервер объявил окно 0) и TcpExtTCPWinProbe (проба отправлена в ответ на окно 0 у другой стороны), а также Recv-Q сокета на сервере (байты в ss, ещё не прочитанные программой)
Подтверждает
Во время фриза повторных передач нет, ходят только нулевые окна и пробы. Если растут TcpExtTCPToZeroWindowAdv или Recv-Q сокета на сервере, не успевает читать сервер, если растёт TcpExtTCPWinProbe, не успевает читать клиент
Опровергает
Если нулевых окон в захвате нет, а одни и те же данные отправляются повторно, причина в потерях или ложных повторных передачах
ID rt-syn · Основной ответственный Команда разработки · Разработка сервера · Совместно Команда инфраструктуры · Серверная инфраструктура, Команда инфраструктуры · Сетевая инфраструктура, Команда разработки · Разработка клиента
Если запрос на подключение теряется из-за переполнения очереди подключений (backlog) или блокировки файрволом, ОС клиента отправляет его повторно через 1 с, а затем с растущими интервалами.
Почему Сразу после техработ из-за наплыва подключений переполняется очередь подключений сервера, или файрвол либо защита от DDoS выбрасывают SYN → Следствие ОС клиента повторно отправляет SYN через 1 с, затем через заданные интервалы (в старых Linux 1 с → 2 с → 4 с) → На экране После нажатия кнопки входа задержка ровно в целые секунды (1 с, 3 с), при постоянных неудачах ошибка входа или бесконечная загрузка
Основной ответственный Команда разработки · Разработка сервера · Совместно Команда инфраструктуры · Серверная инфраструктура, Команда инфраструктуры · Сетевая инфраструктура, Команда разработки · Разработка клиента
Команда разработки: задачи
Сервер: увеличить аргумент backlog в listen (вместе с somaxconn), вовремя вызывать accept в игровом сервере, очередь на вход. Клиент: увеличивать интервал повторных попыток подключения (со случайным разбросом).
Команда инфраструктуры: задачи
Серверы и ОС: переполнение очереди подключений на сервере проверять по TcpExtListenOverflows и TcpExtListenDrops в nstat и по предупреждению «Possible SYN flooding» в логе, увеличить somaxconn (вместе с аргументом listen), включить SYN cookies. Сеть: ослабить ограничения SYN на файрволе и в защите от DDoS.
Цифры для ориентира
В Linux (включая Android) первая повторная передача SYN идёт через 1 с. Старые ядра дальше каждый раз удваивают интервал и отправляют повторно на 1, 3, 7, 15 с …, а ядра 6.5 и новее отправляют SYN повторно пять раз, в моменты 1, 2, 3, 4, 5 с, и только потом удваивают интервал (7, 11, 19 с …) (tcp_syn_linear_timeouts=4). На телефонах с Android после обновления ОС часто остаётся ядро, с которым устройство вышло, поэтому даже на одной версии Android поведение может отличаться от устройства к устройству. В любом случае, если все попытки неудачны, примерно через 2 минуты попытки прекращаются. В Windows в зависимости от версии и настроек интервалы растут начиная с 1 с или 3 с, а повторов 2–4, так что отказ наступает через 20–30 с (значение для конкретного ПК видно в Max SYN Retransmissions в выводе netsh int tcp show global).
На графике
Всплеск сразу после входа или техработ · число попыток подключения, число переполнений очереди подключений
Где смотреть
На сервере посмотреть TcpExtListenOverflows и TcpExtListenDrops в nstat и предупреждение «Possible SYN flooding on port» в dmesg, через ss -lnt проверить, доходит ли Recv-Q слушающего сокета (число соединений, ждущих accept) до Send-Q (лимит backlog). По захвату на стороне сервера проверить, доходят ли SYN и отвечает ли сервер SYN-ACK
Подтверждает
Во время наплыва подключений сразу после техработ растёт TcpExtListenOverflows, а Recv-Q упирается в Send-Q. В захвате SYN от одного и того же клиента приходят повторно с интервалом в секунды, а сервер не отвечает
Опровергает
Если SYN до сервера не доходят и счётчики сервера не меняются, их выбросили файрвол или защита от DDoS перед сервером: смотреть ограничения SYN и логи дропов на этом оборудовании. Если сервер отправил SYN-ACK, а подключение всё равно медленное, теряются пакеты на обратном пути
Чем проверить
Инструменты инфраструктуры (игровой код не нужен)
Источников: 11
include/net/tcp.hLinux kernel Первый RTO TCP_TIMEOUT_INIT = 1 с (начальное значение из RFC 6298)
IP SysctlLinux kernel tcp_syn_retries по умолчанию 6, tcp_syn_linear_timeouts по умолчанию 4 (SYN RTO 1, 1, 1, 1, 1, 2, 4 …), последняя повторная передача на 67 с, отказ на 131 с, somaxconn по умолчанию 4096, tcp_syncookies по умолчанию 1
tcp: make the first N SYN RTO backoffs linearLinux kernel Коммит, сделавший начало повторных передач SYN равномерным, начиная с Linux 6.5 (значение по умолчанию 4 повторяет поведение macOS и iOS)
Android common kernelsAndroid (Google) Одновременно поддерживаются общие ядра от 5.10 до 6.18, и ядро для предыдущей платформы (например, android14-6.1) можно использовать при выпуске новых устройств на Android или при их обновлении
TcpMaxConnectRetransmissionsMicrosoft Старые значения Windows по умолчанию: 2 повторные передачи SYN, первое ожидание 3 с с удвоением, после последней ожидание ещё вдвое дольше и отказ (3+6+12=21 с)
TCP/IP connectivity issues troubleshootingMicrosoft Число повторных передач SYN зависит от ОС, смотрят его через Max SYN Retransmissions в выводе netsh int tcp show global
listen(2) — Linux manual pageLinux man-pages Аргумент backlog в listen обрезается до somaxconn (с Linux 5.4 по умолчанию 4096, раньше 128)
SNMP counterLinux kernel Когда очередь accept заполнена, SYN выбрасываются, и одновременно растут TcpExtListenOverflows и TcpExtListenDrops; счётчик TcpExtTCPSynRetrans
net/ipv4/tcp_input.cLinux kernel Сообщение в логе «Possible SYN flooding on port …»
net/ipv4/tcp_diag.cLinux kernel Для слушающего сокета Recv-Q в ss означает число соединений, ждущих accept, а Send-Q лимит backlog
Инструкции по ситуациям
Лаги после патча
Когда после определённого патча или деплоя стало больше сообщений о лагах. Подходит, если копятся жалобы вида «с этого обновления что-то не так» или если график с какого-то момента поднимается ступенькой и так и остаётся.
Точно определить время начала и собрать все изменения до и после него: Находят момент, когда пошёл первый поток сообщений о лагах, и момент, когда график поднялся ступенькой, и выписывают все изменения, выкаченные до и после них. Смотрят всё вместе: патч клиента, деплой сервера, изменения настроек, изменения схемы БД (DDL) и перезапуски, работы с сетью и файрволом, замену инфраструктуры (тип инстанса, ядро, драйверы). Если при каждом деплое ставить вертикальную линию на всех графиках с помощью аннотаций (annotation) в инструменте мониторинга, этот шаг проходит быстро. Если игровой патч и инфраструктурные работы вышли в одни и те же техработы, кандидатами остаются оба. Кого звать первым: обе команды, разработки и инфраструктуры, которые вносили изменения. (Деплой и перезапуск, Изменение производительности после обновления ОС, ядра, драйверов или прошивки, Блокировка при изменении схемы (DDL) на работающем сервисе, Замедление запроса из-за смены плана выполнения, Холодный кэш (сразу после перезапуска))
Разделить по охвату: сборка, устройство, сервер, регион: Смотрят, в каком срезе сосредоточена проблема. Если плохо только у игроков на новой сборке, первым делом подозревают клиент; если только на определённой ОС, видеокарте или устройстве, то производительность клиента или драйверы; если только на определённом сервере, канале или в зоне, то сервер; если только в определённой стране или у определённого провайдера, то сетевой маршрут; если у всех одновременно, то общие ресурсы (БД, балансировщик нагрузки, шлюз) или только что выкаченный деплой сервера. Если в клиентской телеметрии есть номер сборки, ставят рядом пинг, FPS, всплески времени кадра и число дисконнектов на старой и новой сборке. Если пинг прежний, а упал только FPS, дело скорее в производительности клиента, чем в сети. Кого звать первым: если проблема сосредоточена в сборке или устройстве, команда разработки (клиент); если на сервере или канале, то при нормальных метриках хоста команда разработки (сервер), при отклонениях команда инфраструктуры (серверы и ОС); если в стране или у провайдера, команда инфраструктуры (сеть). (Всплески времени кадра, Синхронная загрузка и компиляция шейдеров в главном потоке, Нехватка видеопамяти (VRAM), Краш клиента)
Сравнить новую и старую версии в одно и то же время: Если сравнивать только «до» и «после» деплоя, к результату примешиваются колебания по дням недели, времени суток и игровым событиям, и вывод получается размытым. По возможности новую версию сначала выкатывают на часть серверов (канарейка) и в то же самое время сравнивают с серверами на старой версии (контрольная группа): p50 и p99 времени тика, число превышений бюджета тика, CPU, память, долю ошибок. Если версия уже выкачена везде, сравнивают с тем же днём недели и тем же временем суток на прошлой неделе. Среднее по всем серверам скрывает проблемы отдельных серверов и зон, поэтому смотрят в разбивке по серверам и зонам. Кого звать первым: команда разработки (сервер). (Превышение бюджета тика, Лавина аллокаций, Утечка памяти, Взрывной рост рассылки (broadcast))
Сравнить профиль трафика до и после: Даже не зная серверного кода, по тому, что видно со стороны сети, проверяют, изменил ли патч характер трафика. Сравнивают до и после: пакеты в секунду (pps) и байты на игрока, средний и максимальный размер пакета, число соединений, размер всплеска отправки, который уходит разом на каждом тике. Если UDP-пакеты начали превышать MTU пути (обычно 1 500 байт), возникает IP-фрагментация. Потеря одного фрагмента означает потерю всего пакета, а некоторые NAT и файрволы вообще отбрасывают фрагменты. У игроков, чей путь проходит через участок с маленьким MTU (туннель, VPN), пропадают только большие пакеты. Если pps вырос, проверяют, не упёрлись ли в лимит PPS облачного инстанса или в предел производительности файрвола или оборудования защиты от DDoS. Кого звать первым: если профиль трафика изменился, команда разработки (сервер) с приложенными доказательствами; если профиль прежний, а выросли только потери и повторные передачи, команда инфраструктуры (сеть). (Патч изменил характер трафика, IP-фрагментация UDP-пакетов, Чёрная дыра MTU (большие пакеты теряются раз за разом), Превышен лимит PPS в облаке, Перегрузка промежуточного оборудования (файрвол, IPS, защита от DDoS), Переполнение неглубоких буферов всплесками отправки)
Сравнить типы и число запросов к БД до и после: Если выросла задержка БД, сначала смотрят, выросло ли вместе с ней число запросов (QPS). pg_stat_statements в PostgreSQL и сводка по digest в MySQL Performance Schema объединяют запросы, которые отличаются только значениями, в один тип и собирают по нему число выполнений и суммарное время. Поэтому если сравнить топ запросов до и после патча, видны новые запросы, запросы, число которых выросло в несколько раз (N+1), и запросы, которые читают всю таблицу без индекса (в MySQL столбец SUM_NO_INDEX_USED). Кого звать первым: если изменились QPS или вид запросов, команда разработки (сервер); если запросы те же, а выросла только задержка, команда инфраструктуры (БД: план выполнения, IOPS, блокировки). (Запрос без индекса, Наплыв входов и запросы N+1, Замедление запроса из-за смены плана выполнения, Cache stampede)
Определить слой по метрикам хоста и серверного процесса: Без доступа к коду, по тому, что видно в ОС, отделяют проблемы внутри серверного процесса от проблем хоста. Если растёт очередь приёма серверного сокета (Recv-Q), серверный процесс не успевает читать данные (остановка тика, GC, блокировки). Если один поток загружен на 100%, это узкое место в однопоточном коде. Если в GC-логе выросло время пауз, изменился характер работы с памятью. Проверяют и то, не выкатили ли сборку с повышенным уровнем логирования, из-за чего выросла запись логов. Если же выросли CPU steal, троттлинг или дропы на NIC, смотрят, что в то же время поменялось в инфраструктуре (тип инстанса, ядро, лимиты контейнеров). Кого звать первым: если признаки внутри процесса, команда разработки (сервер); если признаки на хосте, команда инфраструктуры (серверы и ОС). (Полная пауза GC на сервере, Перегрузка однопоточной локации (хотспот), Синхронная запись логов, Троттлинг CPU в контейнере (квота CFS), CPU steal (виртуальная машина), Изменение производительности после обновления ОС, ядра, драйверов или прошивки)
Подтвердить причину, вернув изменение, и записать результат: Самое вероятное изменение возвращают только на части серверов или у части игроков (роллбэк, выключение фича-флага) или ставят прежнее значение настройки и смотрят, уходит ли вместе с этим симптом. Если лучше стало только там, где изменение вернули, причина подтверждена. Сам возврат тоже может ненадолго замедлить работу из-за перезапуска и холодного кэша, поэтому, если не горит, его делают в спокойные часы. Результат записывают в отчёт об инциденте вместе с ID причины, а лимиты на размер пакетов, число запросов и время тика переносят в чек-лист перед деплоем следующего патча. Кого звать первым: команда, которая внесла изменение. (Деплой и перезапуск, Холодный кэш (сразу после перезапуска))
Запуск в новой стране или регионе
Когда сервис открывают в новой стране или добавляют новый регион или ЦОД. Подходит и для проверки перед запуском, и для разбора жалоб вида «в Корее всё нормально, лагает только у игроков из новой страны».
До запуска измерить качество маршрутов у каждого местного провайдера: Для каждого крупного провайдера (ASN) целевой страны измеряют распределение времени пути туда и обратно (RTT), джиттер и потери до площадок, которые рассматриваются для игровых серверов. Одно среднее скрывает разницу между провайдерами, поэтому смотрят медиану и 95-й перцентиль по каждому провайдеру отдельно для вечернего пика и для ночных часов. В открытой измерительной сети RIPE Atlas можно выбрать страну и ASN и запускать ping и traceroute с зондов по всему миру, а можно поднять временную ВМ в регионе-кандидате и мерить с неё. Промежуточное оборудование иногда ограничивает ответы ICMP, поэтому по возможности меряют и тем же протоколом и портом, что и игра. Если трафик только одного провайдера идёт через подозрительно далёкий город, это проблема пиринга или маршрута. Провайдеры выбирают маршрут подешевле, даже если задержка на нём больше, поэтому трафик даже до близкой точки может идти далёким обходом. Кого звать первым: команда инфраструктуры (сеть), а если маршрут на стороне провайдера, внешние стороны (провайдер, IX). (Задержка распространения (физическое расстояние), Неоптимальная маршрутизация, Перегрузка пиринга в часы пик, Аварии на подводных кабелях и международных линиях)
Сравнить замеры с пределами, на которые рассчитана игра: Измеренные RTT и джиттер сравнивают с окнами реакции в игре (время на уклонение, парирование и т. п.), пределом компенсации задержки, длиной буфера интерполяции и размером буфера ввода. Например, если окно парирования 0,2 с, то абоненты провайдеров, у которых путь туда и обратно вместе с буфером интерполяции дольше этого, опаздывают, даже если реагируют вовремя. Если подогнать игру под них, расширив компенсацию задержки, то уже у тех, в кого попадают, становится больше жалоб «в меня попали, когда я уже был за стеной». Если провайдеров за пределом много, команда инфраструктуры прорабатывает размещение региона или точек присутствия (edge PoP) ближе к игрокам, а команда разработки пересматривает значения окон, интерполяции и компенсации задержки. Ориентиры собраны в главе справочника о моделях синхронизации. Кого звать первым: команда разработки (сервер и клиент: пределы архитектуры), команда инфраструктуры (сеть: размещение регионов и PoP). (Короткое окно реакции, которое съедает пинг, Проверка попадания без компенсации задержки, Чрезмерная компенсация задержки, Буфер интерполяции отсутствует или слишком короткий)
Проверить MTU и прохождение UDP: Проверяют, проходит ли через местные сети целиком самый большой пакет игры. Отправляют ping с флагом запрета фрагментации (DF) пакетами разного размера, чтобы измерить MTU пути, и смотрят, нет ли участков с MTU меньше 1 500 байт, например PPPoE, туннелей или мобильной сети. Стандарт для датаграммных протоколов вроде UDP (RFC 8899) рекомендует для IPv4 базовый размер 1 200 байт, который проходит через большинство путей. Если максимальный пакет игры больше, вместе с командой разработки решают, уменьшать его или делить на части. Проверяют и то, не блокируют ли UDP или игровые порты и не ограничивают ли их скорость в публичном Wi-Fi, корпоративных сетях и у отдельных провайдеров, и есть ли запасной путь на случай блокировки (TCP, порт 443). Кого звать первым: команда инфраструктуры (сеть) и команда разработки (сервер: размер пакетов). (Несовпадение MTU (пропадают только большие пакеты), Чёрная дыра MTU (большие пакеты теряются раз за разом), IP-фрагментация UDP-пакетов, Ограничение UDP и DPI на уровне страны или провайдера, Ограничения публичного Wi-Fi и корпоративной сети, Ограничение скорости и управление трафиком у провайдера)
Измерить таймаут простоя NAT и CGNAT и подобрать интервал хартбита: Измеряют, через сколько местные домашние роутеры и мобильные сети (CGNAT) удаляют запись NAT для неактивного UDP-соединения. В каждом прогоне тестовое устройство отправляет на сервер один пакет, чтобы создать запись, и дальше ничего не шлёт, а сервер через заданное время (30 с, 60 с, 120 с …) отправляет пакет на устройство. Время, начиная с которого устройство перестаёт получать этот пакет, и есть таймаут простоя этой сети. Стандарт (RFC 4787) требует, чтобы запись UDP не истекала раньше чем через 2 минуты, и рекомендует по умолчанию 5 минут и больше, но значения у оборудования сильно различаются, и некоторые устройства удаляют записи раньше. Запись надёжно обновляется только пакетами, исходящими от устройства, поэтому хартбит отправляет клиент, и проверяют, что его интервал не больше половины самого короткого из значений: измеренного таймаута и таймаутов простоя балансировщика нагрузки и облачной группы безопасности. Кого звать первым: команда разработки (клиент: интервал хартбита; сервер: значения таймаутов), команда инфраструктуры (настройки балансировщика и групп безопасности). (Истечение записи в таблице NAT, Общий IP провайдера (CGNAT), Истечение записи NAT или балансировщика посреди соединения, Таймаут простоя балансировщика, Истечение отслеживания соединений в облачной группе безопасности)
Проверить внешние сервисы и оборудование безопасности на пути местных игроков: Проверяют, с нормальной ли скоростью отвечают местные сервисы входа через платформу, оплаты и подтверждения личности, правильно ли местные DNS разрешают адреса серверов авторизации и патчей и отдаёт ли CDN патчи из точки присутствия рядом с этой страной. Смотрят, не попадают ли диапазоны IP новой страны под правила блокировки по странам и ограничения скорости в защите от DDoS и файрволе, и особенно, не блокируются ли целиком диапазоны CGNAT, где один IP делят многие абоненты. Кого звать первым: команда инфраструктуры (оборудование безопасности, DNS, CDN), внешние стороны (платформы, платёжные компании, провайдеры). (Зависимость от внешних сервисов, Сбои и задержки DNS, Задержка и ложные срабатывания защиты от DDoS, Общий IP провайдера (CGNAT))
После запуска смотреть в разбивке по странам и ASN: К клиентским IP в логах подключений и логах балансировщика добавляют страну и ASN и смотрят по странам и провайдерам RTT, повторные передачи, число дисконнектов и их причины (таймаут хартбита, RST, кик сервером). Бесплатные базы вроде MaxMind GeoLite ASN переводят IP в ASN и название организации, а сами IP по местным правилам о персональных данных хранят в укрупнённом виде, до /24 или ASN. Если проблемы сосредоточены в одном ASN, первым делом смотрят маршрут этого провайдера (команда инфраструктуры, внешние стороны); если плохо во всей новой стране, то расстояние и пределы, на которые рассчитана игра (команда инфраструктуры, команда разработки); если хуже становится только вечером, то перегрузку пиринга. Если у части игроков пинг высокий постоянно, вместе с командой разработки (сервер) проверяют, не отправило ли их в далёкий регион из-за ошибки GeoIP, VPN или выбора региона по лидеру группы. Если синтетический мониторинг в норме, а плохо только у игроков, дело в окружении игрока или в клиенте. (Перегрузка пиринга в часы пик, Неоптимальная маршрутизация, Переполнение очереди в узком месте (потери от перегрузки), Ложные срабатывания проверок у абонентов одного провайдера, Ошибки матчмейкинга и выбора региона)
Проверить, как игроки из далёких регионов влияют на остальных: Когда игроков, подключающихся издалека, становится больше, дело не ограничивается тем, что лагает у них самих. Ввод игрока с плохой связью приходит пачками, на экранах остальных его персонаж движется перемоткой, а на сервере срабатывают проверки скорости и кулдаунов, и появляются откидывание назад и отклонённые умения. В групповых механиках запоздалая реакция одного медленного игрока проваливает всю группу, а в lockstep все ждут самого медленного. После запуска в новой стране смотрят, не стало ли больше жалоб от прежних игроков вида «странно выглядит один персонаж», и вместе с командой разработки решают вопрос с буфером ввода, допусками проверок и разделением матчмейкинга по регионам. Кого звать первым: команда разработки (сервер). (Игрок с плохой связью движется на чужих экранах рывками, Ложные срабатывания проверок у абонентов одного провайдера, Один тормозящий участник группы и механики босса, Ожидание самого медленного игрока в 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), и изменили приоритеты так, чтобы одна точка не могла перетянуть на себя трафик других.
Многие игры раздают файлы патчей, лаунчер и веб-страницы через 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, и готовит запасной вариант в другом регионе.
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. Картинка плавнее, но задержка от ввода до экрана может вырасти.
Список литературы
Материалов: 616, издателей: 83. Стандарты, официальная документация по ядру, ОС, облакам, движкам и БД, научные статьи, технические статьи самих разработчиков.
Microsoft 85
_WDF_TIMER_CONFIG (wdftimer.h)Microsoft Точность обычного таймера равна интервалу системного тика, по умолчанию 15,6 ms, у таймера высокого разрешения 1 ms
/fp (Specify floating-point behavior)Microsoft /fp:fast может менять порядок операций с плавающей точкой или объединять их, и результат будет отличаться от других настроек /fp, а операции, объединённые в FMA, тоже могут давать результат, отличный от раздельного умножения и сложения
About Windows Filtering PlatformMicrosoft Архитектура, в которой хуки сетевого стека Windows и движок фильтрации пропускают или блокируют пакеты. Сторонние разработчики защитных программ могут встраивать свои модули фильтрации (callout)
Acquiring high-resolution time stampsMicrosoft QueryPerformanceCounter (его использует Stopwatch): часы для измерения прошедшего времени, не синхронизируемые с внешним временем. Системное время нужно только тогда, когда требуется время UTC
ASP.NET Core Best PracticesMicrosoft Доступ к данным, ввод-вывод и долгие операции вызывать асинхронно. Синхронные блокирующие вызовы ведут к исчерпанию пула потоков и задержкам ответа
closesocket function (winsock.h)Microsoft Если включить SO_LINGER со временем 0, закрытие становится принудительным: соединение сразу сбрасывается, а неотправленные данные теряются
Collecting User-Mode DumpsMicrosoft Через отчёты об ошибках Windows (WER) можно настроить локальный сбор полных дампов и мини-дампов при падении программ пользовательского режима
CPU AnalysisMicrosoft График DPC/ISR в WPA: длительность каждого непрерывного выполнения DPC или ISR и модуль (Module), в котором находится эта функция
CreateMutexW function (synchapi.h)Microsoft Если именованный мьютекс уже существует, возвращается ERROR_ALREADY_EXISTS, что используют для обнаружения повторного запуска и ограничения одним экземпляром
Creating and Opening FilesMicrosoft Файл, открытый без режима общего доступа, другой процесс открыть не может, возникает ERROR_SHARING_VIOLATION
Customize the Windows performance power sliderMicrosoft Энергосбережение в эксперименте: режим питания Windows меняет настройки питания и CPU, жертвуя производительностью ради времени работы от батареи
Debug ThreadPool StarvationMicrosoft Если в пуле не осталось свободных потоков и новые задачи ждут, ответы замедляются. Причина в блокирующем коде, который занимает потоки. Признак исчерпания в dotnet-counters: CPU намного ниже 100%, а dotnet.thread_pool.thread.count медленно, но постоянно растёт (часто велик и dotnet.thread_pool.queue.length). Где ждут потоки, проверяют через dotnet-stack
Delivery Optimization referenceMicrosoft Загрузка обновлений Windows (оптимизация доставки) по умолчанию динамически подстраивается под доступную пропускную способность, а для фоновых и активных загрузок можно задать верхний предел пропускной способности
Direct3D 12 Return CodesMicrosoft D3D12_ERROR_DRIVER_VERSION_MISMATCH: кэш PSO, созданный другой версией драйвера, повторно использовать нельзя (после обновления драйвера нужна перекомпиляция)
DirectStorage is coming to PCMicrosoft Старые жёсткие диски читают десятки MB в секунду, NVMe SSD несколько GB в секунду, бюджет стриминга ассетов в играх прошлого поколения около 50 MB в секунду. Игры с открытым миром на ходу подгружают и выгружают дальние пейзажи
DXGI_QUERY_VIDEO_MEMORY_INFO structure (dxgi1_4.h)Microsoft Budget (бюджет видеопамяти, заданный ОС) и CurrentUsage (текущее использование приложением). Если использование превышает бюджет, возможны рывки
Guidelines for Writing DPC RoutinesMicrosoft Пока выполняется DPC, все потоки на этом ядре стоят, поэтому рекомендуется не превышать 100 µs за раз
I/O Completion PortsMicrosoft Множество асинхронных операций ввода-вывода обрабатывает заранее созданный пул потоков через IOCP, а число одновременно работающих потоков ограничивается по числу процессоров
Introduction to NDIS Selective SuspendMicrosoft Windows может переводить простаивающий сетевой адаптер в состояние пониженного энергопотребления (выборочная приостановка)
Introduction to the page fileMicrosoft Файл подкачки: файл на диске, в который из ОЗУ выгружаются изменённые и редко используемые страницы памяти
ipconfigMicrosoft Без параметров показывает для каждого адаптера адреса IPv4 и IPv6 и основной шлюз
Logging in C#Microsoft Методы логирования в .NET синхронные, поэтому при медленном хранилище рекомендуется сначала писать в быстрое хранилище, а потом переносить
Low Latency Workloads Management and OperationsMicrosoft Dropped Datagrams и Dropped Datagrams/sec из набора счётчиков Microsoft Winsock BSP: число UDP-пакетов, отброшенных потому, что они приходили быстрее, чем приложение успевало их обрабатывать, или не хватило буфера приёма сокета
Minidump FilesMicrosoft Мини-дамп содержит только полезную часть информации аварийного дампа, поэтому создаётся быстро и занимает мало места
MultitaskingMicrosoft Windows выделяет каждому потоку квант времени и по его окончании переключается на следующий поток, квант около 20 ms (зависит от ОС и CPU)
netstatMicrosoft -a показывает порты TCP и UDP, -n выводит адреса в числовом виде, -o показывает ID процесса (PID), -p udp оставляет только UDP
nslookupMicrosoft Команда для прямого запроса имени у DNS-сервера
Packet Monitor (Pktmon)Microsoft Встроенный инструмент, показывающий, где и почему отбрасываются пакеты в разных точках сетевого стека Windows
pathpingMicrosoft Некоторое время пингует каждый участок, считает долю потерь по маршрутизаторам и линкам и показывает, на каком участке возникают потери
Performance analyzer for Microsoft Defender AntivirusMicrosoft Запись через New-MpPerformanceRecording, затем Get-MpPerformanceReport показывает файлы, пути и процессы, которые сильнее всего влияют на время сканирования
pingMicrosoft /t: отправлять эхо-запросы непрерывно, пока их не остановят
Pktmon command formattingMicrosoft Встроен в Windows 10 и Windows Server 2019 (1809 и новее) как pktmon.exe
Powercfg command-line optionsMicrosoft powercfg /energy: анализирует систему и создаёт отчёт об энергопотреблении (HTML)
Priority BoostsMicrosoft Процессу активного окна (переднего плана) приоритет поднимается как минимум до уровня фоновых процессов
Process MonitorMicrosoft Записывает в реальном времени активность файловой системы, реестра и процессов, позволяет фильтровать по любому полю, включая путь
Pushing the Limits of Windows: Virtual MemoryMicrosoft В Windows при достижении предела выделения (commit limit) выделение памяти с фиксацией (commit) завершается ошибкой, что может привести к сбою приложения или системы
Quality of ServiceMicrosoft Программы, окна которых не видны и не слышны, получают Low QoS: при работе от батареи они выполняются на самой экономичной частоте CPU и на энергоэффективных ядрах
recvfrom function (winsock.h)Microsoft WSAECONNRESET на UDP-сокете означает, что на предыдущую отправку пришёл ответ ICMP Port Unreachable
Reduce latency with DXGI 1.3 swap chainsMicrosoft Present блокируется, пока очередь не освободится, и от отрисовки до показа проходит почти на кадр больше. Сократить это помогает swap chain с ожиданием (waitable swap chain)
Request schedulingMicrosoft Грейны (акторы) Orleans работают по однопоточной модели и обрабатывают запросы по одному до конца, поэтому состояние не меняется одновременно. Если грейны ждут ответа друг от друга, возможен дедлок
ResidencyMicrosoft У процесса есть бюджет видеопамяти, и при его превышении ядро ОС переносит часть кучи дискретного GPU в оперативную память ПК (это крайняя мера, поэтому рекомендуется следить за бюджетом)
Resolve-DnsNameMicrosoft -Server задаёт DNS-сервер, у которого запрашивается имя
Results for the Idle Energy Efficiency AssessmentMicrosoft Разрешение системного таймера по умолчанию 15,6 ms, процессы, изменившие его, видны в пункте «Platform Timer Resolution» отчёта об энергопотреблении
Scheduling PrioritiesMicrosoft Среди готовых к выполнению потоков кванты времени по очереди (round robin) получают потоки с наивысшим приоритетом
send function (winsock2.h)Microsoft В Winsock send тоже блокируется при нехватке места в буфере, если сокет не в неблокирующем режиме
TCP/IP connectivity issues troubleshootingMicrosoft Число повторных передач SYN зависит от ОС, смотрят его через Max SYN Retransmissions в выводе netsh int tcp show global
TCP/IP port exhaustion troubleshootingMicrosoft Динамические порты Windows по умолчанию 49152–65535, закрытое соединение по умолчанию держит порт в TIME_WAIT 4 минуты
TcpMaxConnectRetransmissionsMicrosoft Старые значения Windows по умолчанию: 2 повторные передачи SYN, первое ожидание 3 с с удвоением, после последней ожидание ещё вдвое дольше и отказ (3+6+12=21 с)
timeBeginPeriod function (timeapi.h)Microsoft До Windows 10 версии 2004 настройка глобальная, начиная с неё действует только на запросивший процесс. Windows 11 не гарантирует высокое разрешение процессам со свёрнутыми или перекрытыми окнами
Using SO_REUSEADDR and SO_EXCLUSIVEADDRUSEMicrosoft При повторном bind на тот же порт с SO_REUSEADDR второй сокет перехватывает порт, и неизвестно, какой сокет получит пакет
WDI low latency connection qualityMicrosoft Сканирование и роуминг уводят радиомодуль с рабочего радиоканала, поэтому в режиме низкой задержки время вне него и сканирование ограничиваются
Well-known EventCounters in .NETMicrosoft Monitor Lock Contention Count (monitor-lock-contention-count): сколько раз попытка захватить блокировку монитора наткнулась на конкуренцию
Windows Firewall RulesMicrosoft По умолчанию входящие соединения блокируются, поэтому приложению нужно правило-исключение. Обычно его создаёт установщик приложения
WlanSetInterface function (wlanapi.h)Microsoft API Windows, который включает и выключает фоновое сканирование (wlan_intf_opcode_background_scan_enabled) и режим потоковой передачи мультимедиа
Working SetMicrosoft Обращение к странице, которой нет в ОЗУ, вызывает ошибку страницы. Жёсткая ошибка устраняется только чтением с диска, например из файла подкачки
Xbox Series X: What’s the Deal with Latency?Microsoft Задержка ввода складывается по всему пути контроллер → консоль → HDMI → телевизор. Старые контроллеры опрашивали и отправляли ввод каждые 8 ms. Передача одного кадра по HDMI занимает 16,6 ms при 60 Hz и 8,3 ms при 120 Hz. ALLM автоматически включает игровой режим телевизора
Linux kernel 62
ABI stable symbolsLinux kernel /sys/block/(диск)/queue/rotational: показывает, вращающееся устройство или нет
CFS Bandwidth ControlLinux kernel Если квота на период израсходована, потоки стоят до следующего периода (троттлинг). Период по умолчанию 100 ms, статистика nr_throttled
Concepts overviewLinux kernel Ядро освобождает страницы страничного кэша, у которых есть копия на диске, и страницы, которые можно выгрузить в своп, а если памяти всё равно не хватает, OOM killer завершает процесс
Control Group v2Linux kernel cpu.max имеет формат «$MAX $PERIOD» (квота, период), значение по умолчанию «max 100000» (период 100 ms)
CPU Idle Time ManagementLinux kernel У каждого состояния сна есть время выхода (exit latency) и минимальное время пребывания (target residency), а глубину выбирают по ожидаемому времени простоя. В sysfs для каждого state есть latency, usage и time. Глубокие состояния ограничивают через PM QoS (/dev/cpu_dma_latency) и intel_idle.max_cstate
CPU Performance ScalingLinux kernel Через scaling_governor можно посмотреть и сменить governor. performance запрашивает самую высокую частоту из допустимого диапазона, powersave самую низкую
Documentation for /proc/sys/net/Linux kernel netdev_max_backlog: лимит очереди приёма, куда складываются пакеты, если они приходят быстрее, чем ядро успевает их обрабатывать
Documentation for /proc/sys/vm/Linux kernel min_free_kbytes: минимальный объём свободной памяти, который ядро держит в резерве (порог watermark)
drivers/idle/intel_idle.c (Linux v6.12)Linux kernel Время пробуждения серверных CPU Intel по C-state: Skylake-SP C1 2 µs, C1E 10 µs, C6 133 µs; Ice Lake C6 170 µs; Sapphire Rapids C1 1 µs, C6 290 µs
EEVDF SchedulerLinux kernel Начиная с 6.6 Linux переходит с CFS на планировщик EEVDF
Ethtool countersLinux kernel rx_out_of_buffer (нет буфера в очереди приёма) и rx_discards_phy (отброшено из-за нехватки буфера порта) драйвера mlx5
include/net/sock.h (Linux v6.18)Linux kernel Буфер сокета по умолчанию определён как 256 пакетов по 256 байт с учётом накладных расходов sk_buff (SKB_TRUESIZE(256)×256). Даже маленький кадр учитывается как sk_buff+MTU (около 208 KB: расчётное значение для x86-64)
include/uapi/linux/tcp.hLinux kernel tcpi_reord_seen в tcp_info: сколько раз соединение сталкивалось с нарушением порядка
intel_pstate CPU Performance Scaling DriverLinux kernel Алгоритм powersave в intel_pstate, в отличие от универсального governor powersave, регулирует частоту по нагрузке (похоже на schedutil и ondemand)
Interface statisticsLinux kernel rx_crc_errors: число принятых пакетов с ошибкой CRC, ошибки по видам смотреть через ip -s -s link
IP SysctlLinux kernel При tcp_mtu_probing=1 определение MTU пути для TCP обычно выключено и включается, когда обнаружена чёрная дыра ICMP
MDS - Microarchitectural Data SamplingLinux kernel Защита очищает буферы CPU при возврате из ядра в пространство пользователя и при входе в виртуальную машину. Состояние уязвимостей и защиты показывают файлы в /sys/devices/system/cpu/vulnerabilities/. На многих CPU для полной защиты нужно выключить SMT, а это в зависимости от нагрузки сильно бьёт по производительности
mm/oom_kill.c (Linux v6.12)Linux kernel Оценка рассчитывается так, чтобы самый высокий балл получал процесс, занимающий больше всего памяти (с учётом oom_score_adj). При завершении записывается «Out of memory: Killed process …»
NAPILinux kernel Большой gro_flush_timeout даёт пакетную обработку, но при низкой нагрузке добавляет задержку
net/core/net-procfs.cLinux kernel /proc/net/softnet_stat: по строке на CPU, значения шестнадцатеричные, 2-й столбец dropped, 3-й столбец time_squeeze
net/ipv4/proc.c (Linux v6.12)Linux kernel Имена счётчиков, которые показывает nstat: RcvbufErrors и SndbufErrors в группе Udp
net/ipv4/tcp_bbr.cLinux kernel BBR задаёт pacing_rate по оценке пропускной способности узкого места
net/ipv4/tcp_diag.c (Linux v6.12)Linux kernel Значения Recv-Q и Send-Q в ss: у слушающего сокета это число подключений, ждущих accept, и лимит backlog, у подключённого сокета это байты, ещё не прочитанные приложением, и отправленные байты без ACK
net/ipv4/tcp_input.c (Linux v6.12)Linux kernel В Linux RTO = сглаженный RTT + разброс RTT, а нижняя граница разброса равна tcp_rto_min (200 ms), поэтому RTO не меньше RTT+200 ms
net/ipv4/tcp_ipv4.cLinux kernel Инициализация значений по умолчанию: tcp_early_retrans 3, tcp_recovery RACK, tcp_syn_linear_timeouts 4, tcp_base_mss 1 024 (tcp_mtu_probing отдельно не задаётся, поэтому 0)
net/ipv4/tcp_output.cLinux kernel TLP в Linux планируется только для соединений с SACK
net/ipv4/tcp_recovery.cLinux kernel Запас времени RACK = min(min_RTT/4 × шаг, SRTT), повторные передачи, подтверждённые быстрее минимального RTT, не учитываются
net/ipv4/tcp_timer.c (Linux v6.12)Linux kernel При каждом срабатывании таймера повторной передачи увеличивается TCPTimeouts, backoff растёт на единицу, а RTO удваивается (до максимального значения)
net/ipv4/udp.c (Linux v6.12)Linux kernel Если очередь приёма UDP превышает размер буфера сокета, пакет сразу отбрасывается и растёт RcvbufErrors
net/netfilter/nf_conntrack_standalone.cLinux kernel /proc/net/stat/nf_conntrack: по строке на ядро, шестнадцатеричные значения, столбцы entries, invalid, insert_failed, drop, early_drop и др.
net/sched/sch_generic.c (Linux v6.12)Linux kernel Если очередь отправки зависла, watchdog ядра пишет «NETDEV WATCHDOG … transmit queue N timed out» и вызывает функцию сброса драйвера
net/wireless/core.cLinux kernel Лимит повторов по умолчанию в беспроводном стеке Linux: 7 для коротких кадров, 4 для длинных (dot11ShortRetryLimit, dot11LongRetryLimit)
Netfilter Conntrack Sysfs variablesLinux kernel Максимальное число записей в таблице conntrack в Linux (nf_conntrack_max) и время хранения записей по состояниям по умолчанию
PSI - Pressure Stall InformationLinux kernel some в /proc/pressure/memory (доля времени, когда часть задач стояла в ожидании памяти) и full (доля времени, когда стояли все задачи)
Runtime locking correctness validatorLinux kernel Если две блокировки захватываются в противоположном порядке, возникает циклическое ожидание и дедлок (lock inversion deadlock). Ядро Linux проверяет порядок захвата блокировок и предупреждает заранее
Scaling in the Linux Networking StackLinux kernel RSS (NIC распределяет пакеты по нескольким очередям приёма) и RPS (распределяет ядро ОС), настройка с отдельным прерыванием на каждую очередь и распределением по ядрам, если узкое место в обработке прерываний приёма, рекомендуется RSS
SNMP counterLinux kernel TcpExtListenOverflows: сколько раз запрос на подключение (SYN) был отброшен из-за заполненной очереди accept. Вместе с ним растёт и TcpExtListenDrops
Spectre Side ChannelsLinux kernel Для защиты буферы предсказания переходов очищаются при переключении контекста и переключении виртуальных машин, а строгие варианты защиты добавляют накладные расходы всем программам
tcp: add sysctl_tcp_rto_min_usLinux kernel Добавлен общий для сервера минимальный RTO по умолчанию tcp_rto_min_us, начиная с Linux 6.11
tcp: make the first N SYN RTO backoffs linearLinux kernel Коммит, сделавший начало повторных передач SYN равномерным, начиная с Linux 6.5 (значение по умолчанию 4 повторяет поведение macOS и iOS)
tcp: use RACK to detect lossesLinux kernel Появление RACK и tcp_recovery (Linux 4.4), сначала как дополнение к прежнему способу
The /proc FilesystemLinux kernel OOM killer выбирает процесс для завершения по оценке (badness), вычисленной по доле используемой памяти, оценку корректируют через oom_score_adj
The kernel’s command-line parametersLinux kernel mitigations=: off отключает всю защиту от уязвимостей CPU и повышает производительность, но оставляет систему уязвимой. По умолчанию auto защищает с включённым SMT, auto,nosmt при необходимости выключает SMT
Thin-streams and TCPLinux kernel TCP_THIN_LINEAR_TIMEOUTS позволяет отключить экспоненциальную задержку повтора только для соединений thin stream
Transparent Hugepage SupportLinux kernel При defrag=always, если выделить THP не удалось, процесс останавливается и тут же выполняет освобождение и уплотнение памяти. При madvise так происходит только в областях, для которых это запрошено
What is NUMA?Linux kernel Память своей ячейки быстрее и имеет большую пропускную способность, обращение к памяти другой (удалённой) ячейки медленнее
IETF 59
RFC 1191: Path MTU discoveryIETF Поиск MTU пути: о слишком большом пакете сообщает ICMP «fragmentation needed and DF set» (тип 3, код 4)
RFC 1812: Requirements for IP Version 4 RoutersIETF Маршрутизатор должен уметь ограничивать частоту сообщений об ошибках ICMP, например Time Exceeded, и может ограничивать Echo Reply (это важно учитывать при чтении mtr и ping)
RFC 2863: The Interfaces Group MIBIETF ifOutDiscards: число пакетов, которые не были отправлены и отброшены без ошибок, например чтобы освободить место в буфере
RFC 2923: TCP Problems with Path MTU DiscoveryIETF Если файрвол блокирует ICMP (Fragmentation Needed), определение MTU пути не срабатывает и постоянно пропадают только большие пакеты (чёрная дыра), а пинг и мелкий обмен работают, поэтому диагностировать трудно
RFC 3449: TCP Performance Implications of Network Path AsymmetryIETF На асимметричных линиях с узкой отдачей задержка или потеря ACK снижает производительность TCP; ACK подтверждают кумулятивно, поэтому потерю части из них покрывают следующие; меры вроде приоритетного планирования ACK
RFC 5382: NAT Behavioral Requirements for TCPIETF Рекомендация: таймаут простоя TCP-соединения в NAT должен быть не меньше 2 часов 4 минут (с учётом того, что устройство может удалить неактивную сессию раньше)
RFC 5482: TCP User Timeout OptionIETF Пользовательский таймаут TCP: через сколько времени без подтверждения отправленных данных закрывать соединение
RFC 5681: TCP Congestion ControlIETF Потеря обнаруживается по 3 дублирующим ACK и запускается быстрая повторная передача, иначе приходится ждать таймер повторной передачи
RFC 6937: Proportional Rate Reduction for TCPIETF PRR: во время восстановления объём отправки уменьшается соразмерно вновь доставленному (лимит отправки при восстановлении в симуляции)
RFC 7871: Client Subnet in DNS QueriesIETF DNS, который отвечает по-разному в зависимости от местоположения, угадывает местоположение по адресу резолвера, отправившего запрос, и если пользователь работает через центральный резолвер далеко от себя, ответ получается неподходящим. EDNS Client Subnet (необязательное расширение) передаёт часть адреса пользователя
RFC 7938: Use of BGP for Routing in Large-Scale Data CentersIETF Если полагаться только на keepalive в BGP, сходимость медленная, если сразу реагировать на падение линка и разрывать сессию, отказ обнаруживается за миллисекунды и маршруты быстро сходятся заново
RFC 7999: BLACKHOLE CommunityIETF BGP-сообщество BLACKHOLE, которым соседнему провайдеру сообщают, что трафик на определённый адрес нужно отбрасывать
RFC 8085: UDP Usage GuidelinesIETF Если потерян один фрагмент, пакет не собрать, и он теряется целиком. UDP-приложениям следует избегать IP-фрагментации
RFC 8325: Mapping Diffserv to IEEE 802.11IETF CSMA/CA в 802.11: передача только при свободном радиоканале, а если он занят, передача откладывается до его освобождения и ещё на случайный интервал (backoff)
RFC 8952: Captive Portal ArchitectureIETF Captive portal: сеть, в которой доступ ограничен, пока не выполнены условия вроде согласия с правилами или авторизации
RFC 9000: QUIC: A UDP-Based Multiplexed and Secure TransportIETF Благодаря ID соединения оно сохраняется при смене IP-адреса и порта (глава 9). Балансировщик, распределяющий только по адресу и порту, может отправить пакеты с нового адреса на другой сервер (раздел 5.2.3)
Amazon CloudWatch metrics for Amazon EBSAWS VolumeQueueLength (число запросов, ожидающих завершения), VolumeAvgWriteLatency (средняя задержка записи за 1 минуту, инстансы Nitro)
Amazon CloudWatch metrics for Amazon EC2 Auto ScalingAWS Метрики группы публикуются с шагом 1 минута, только если их включить: GroupDesiredCapacity (сколько инстансов нужно поддерживать), GroupPendingInstances (число инстансов, ещё не введённых в работу), GroupInServiceInstances (число инстансов в работе)
Amazon EBS-optimized instance typesAWS Некоторые инстансы держат максимальную производительность EBS только 30 минут раз в 24 часа, затем возвращаются к базовой
Amazon EC2 Auto Scaling lifecycle hooksAWS При масштабировании вверх и вниз инстанс переводится в режим ожидания, пока не закончатся подготовительные и завершающие работы (по умолчанию до 1 часа)
Amazon EC2 instance network bandwidthAWS «До N Gbps» у инстансов с 16 vCPU и меньше означает burst за счёт кредитов сетевого ввода-вывода (обычно 5–60 мин), когда кредиты заканчиваются, полоса возвращается к базовой
Amazon EC2 security group connection trackingAWS При превышении числа соединений, которые инстанс может отслеживать, пакеты новых соединений отбрасываются, неактивные соединения могут исчерпать таблицу отслеживания
Amazon GameLift Servers UDP ping beaconsAWS Игровой клиент измеряет задержку через UDP-эндпоинты в каждой локации хостинга и использует её для размещения и матчмейкинга. Это ближе к реальному игровому трафику, чем ICMP-пинг
Avoiding insurmountable queue backlogsAWS Amazon Builders' Library. Затор отслеживают по возрасту ожидающих сообщений. Системы реального времени обрабатывают сначала свежие данные (ближе к LIFO), а устаревшие сообщения могут выбрасывать
CloudWatch metrics for your Application Load BalancerAWS TargetResponseTime (время от выхода запроса из балансировщика до начала ответа целевого сервера), HTTPCode_Target_5XX_Count (число ответов 5xx от целевых серверов), UnHealthyHostCount (число неисправных целевых серверов)
Create a player latency policyAWS Игра размещается в локации с наименьшей средней задержкой для всех игроков, но игроки с экстремальной задержкой тоже попадают в игру. Пример политики, которая расширяет лимит пинга с 50 ms до 100 ms и 200 ms
Edit attributes for your Application Load BalancerAWS Таймаут простоя ALB по умолчанию 60 с (1–4 000 с), если соединения с клиентом и с целевым сервером всё это время молчат, балансировщик закрывает соединение
Exponential Backoff And JitterAWS Если повторять только с экспоненциальной задержкой, повторы скапливаются. Конкуренцию снижает случайный разброс (джиттер), добавленный к задержке (способ повторов в симуляции)
Failing over a Multi-AZ DB instance for Amazon RDSAWS Переключение Multi-AZ обычно занимает 60–120 секунд, после него нужно заново установить соединения, TTL кэша DNS в JVM рекомендуется не больше 60 секунд
FlexMatch rule typesAWS Правило задержки (maxLatency) смотрит задержку игрока до каждой локации, для группы по умолчанию берётся среднее по участникам (partyAggregation avg), очередь может разместить игру и в регионе, который не проходит правило задержки
Flow log recordsAWS srcaddr в записи VPC Flow Logs: для входящего трафика это IP-адрес отправителя
Health checks for Network Load Balancer target groupsAWS Health check по умолчанию раз в 30 с, после 2 неудач цель исключается, UDP-сервисы проверяются через TCP или HTTP health check, поэтому рекомендуется настроить проверку так, чтобы она отражала реальное состояние сервиса
High availability for Amazon AuroraAWS Во время сбоя чтение и запись не проходят, восстановление обычно в пределах 60 секунд (часто в пределах 30)
How Amazon Route 53 uses EDNS0 to estimate the location of a userAWS Если резолвер не поддерживает edns-client-subnet, местоположение пользователя угадывается по адресу резолвера, и ответ даётся по месту резолвера (общее для маршрутизации по географии и по задержке)
How EC2 instance stop and start worksAWS Если инстанс остановить и снова запустить, в большинстве случаев он переезжает на новый хост (кроме выделенных хостов)
Infrastructure layer attacksAWS Массированные атаки вроде UDP-отражения или SYN-флуда переполняют ёмкость сети или занимают ресурсы файрволов и балансировщиков нагрузки
Initialize Amazon EBS volumesAWS Том, созданный из снапшота, пока подтягивает блоки из S3, работает с повышенной задержкой и пониженной производительностью. Его заранее инициализируют, прочитав все блоки через dd или fio
NAT gateway basicsAWS 55 000 одновременных соединений к одной цели (IP, порт и протокол назначения) на один IPv4-адрес, предел поднимается добавлением IP до 8 (у публичного NAT-шлюза по умолчанию 2 Elastic IP, больше по запросу на повышение квоты); полоса автоматически растёт с 5 до 100 Gbps, а производительность с 1 до 10 млн пакетов в секунду, сверх этого предела пакеты отбрасываются
NAT gateway metrics and dimensionsAWS ErrorPortAllocation: сколько раз не удалось выделить исходный порт (больше 0 означает слишком много одновременных соединений), ActiveConnectionCount, IdleTimeoutCount (соединения, закрытые после 350 с простоя), PacketsDropCount
Network Load BalancersAWS Таймаут простоя NLB для TCP по умолчанию 350 с (60–6 000 с), по его истечении NLB просто перестаёт отслеживать соединение и на последующие данные отвечает RST, 120 с для UDP-потоков изменить нельзя
Obfuscating AWS resources (BP1, BP4, BP5)AWS Ставить перед origin-серверами edge-сервисы вроде CloudFront и балансировщиков нагрузки, чтобы серверы не были видны напрямую
Processor state control for Amazon EC2 Linux instancesAWS Управлять C-state и P-state из ОС можно только на некоторых типах инстансов, и их можно менять, чтобы снизить задержку. Настройки по умолчанию дают максимальную производительность и подходят для большинства задач. У Graviton частота фиксированная, и ОС ею не управляет
Renewal for domains validated by DNSAWS За 45 дней до истечения проверяется, используется ли сертификат в сервисах AWS и есть ли CNAME-запись для проверки, и сертификат обновляется автоматически. Если проверить не удалось, уведомления приходят за 30, 15, 7, 3 и 1 день до истечения
Scheduled events for Amazon EC2 instancesAWS Типы запланированных событий (system-reboot: перезагрузка с переносом на новый хост, system-maintenance: кратковременное влияние из-за обслуживания сети или питания), уведомления по почте и через AWS Health, проверка через describe-instance-status, для некоторых типов время можно сдвинуть
Standard mode for burstable performance instancesAWS Burst-инстансы тратят кредиты, чтобы работать выше базовой производительности, а когда кредиты заканчиваются, загрузка CPU снижается до базового уровня
Supported CloudWatch metricsAWS DaysToExpiry: число дней до истечения сертификата, публикуется два раза в сутки, пока сертификат не истёк
Timeouts, retries, and backoff with jitterAWS Amazon Builders' Library. Ко всем таймерам, периодическим и отложенным заданиям добавляют случайный разброс (jitter), чтобы рассеять нагрузку, которая скапливается в одно время. Пример: ежеминутные запросы с многих серверов скапливались в первые секунды каждой минуты
Troubleshoot NAT gatewaysAWS После 350 с простоя соединение истекает, и на последующую отправку возвращается RST, рекомендуется keepalive чаще 350 с, при достижении лимита соединений добавить шлюзы по зонам доступности и IP или сократить число соединений
Working with DB instance read replicasAWS Отставание репликации в эксперименте со схемой серверов: реплики для чтения обновляются асинхронно и могут отдавать старые данные
MySQL 32
Configuring Buffer Pool FlushingMySQL Когда redo-лог заполняется, резкая (sharp) контрольная точка ненадолго снижает производительность, адаптивный сброс распределяет запись равномерно
Deadlock DetectionMySQL При очень высокой конкурентности само обнаружение может замедлиться, поэтому его иногда отключают и полагаются на лимит ожидания блокировки
EXPLAIN Output FormatMySQL type ALL означает полное сканирование таблицы, обычно его устраняют добавлением индекса
General Thread StatesMySQL Waiting for table metadata lock: состояние потока, который ждёт блокировку метаданных
How MySQL Uses IndexesMySQL Без индекса БД читает всю таблицу с первой строки, и чем больше таблица, тем дороже запрос
How to Minimize and Handle DeadlocksMySQL Рекомендация держать транзакции маленькими и короткими и коммитить сразу после связанных изменений, чтобы уменьшить конфликты
InnoDB LockingMySQL Когда транзакция ставит блокировку на строку (запись индекса), другие транзакции не могут изменить эту строку и ждут
InnoDB Multi-VersioningMySQL Пока остаётся транзакция, которой могут понадобиться старые версии, update undo-лог нельзя удалить и rollback-сегмент растёт. Рекомендуется часто коммитить даже транзакции, которые только читают
InnoDB Standard Monitor and Lock Monitor OutputMySQL LATEST DETECTED DEADLOCK: две транзакции последнего дедлока, удерживаемые и ожидаемые блокировки, транзакция, для которой сделан роллбэк
InnoDB Startup Options and System VariablesMySQL При включённом обнаружении (по умолчанию) InnoDB сразу обнаруживает дедлок и делает роллбэк, innodb_lock_wait_timeout по умолчанию 50 секунд
Locks Set by Different SQL Statements in InnoDBMySQL Если подходящего индекса нет и таблица сканируется целиком, блокируются все строки, и другие пользователи не могут даже добавлять записи
Online DDL Performance and ConcurrencyMySQL Даже онлайн-DDL в конце ненадолго требует эксклюзивную блокировку метаданных. Если есть длинная транзакция, DDL её ждёт, а ожидающий запрос блокировки задерживает все последующие транзакции
Purge ConfigurationMySQL Purge очищает список undo-логов закоммиченных транзакций (history list), отставание показывает History list length в секции TRANSACTIONS вывода SHOW ENGINE INNODB STATUS
Replica Server Options and VariablesMySQL replica_parallel_workers: несколько потоков применяют транзакции параллельно (по умолчанию 4, при 0 один поток применяет их по порядку)
Saving and Restoring the Buffer Pool StateMySQL Чтобы сократить прогрев после перезапуска, при выключении сохраняется список недавно использованных страниц (по умолчанию 25%), а при запуске они читаются заново. Обе функции включены по умолчанию
Semisynchronous ReplicationMySQL При асинхронной репликации после отказа основной БД закоммиченных транзакций может не оказаться на реплике. Полусинхронная репликация сокращает этот риск, дожидаясь подтверждения получения от одной реплики, но задержка растёт
Server Status VariablesMySQL Innodb_row_lock_waits и Innodb_row_lock_time показывают число и время ожиданий блокировок строк, Innodb_row_lock_current_waits показывает, сколько запросов ждут сейчас
Server System VariablesMySQL lock_wait_timeout: лимит ожидания блокировки метаданных, по умолчанию 31 536 000 секунд (1 год)
SHOW PROCESSLIST StatementMySQL Host (адрес клиента), Command (у простаивающей сессии Sleep), Time, State
SHOW REPLICA STATUS StatementMySQL Seconds_Behind_Source: сколько прошло с момента, когда событие, которое реплика применяет сейчас, было записано на основной БД (отставание репликации)
Statement Summary TablesMySQL events_statements_summary_by_digest: по каждому шаблону запроса SUM_NO_INDEX_USED (сколько раз он выполнялся без индекса) и SUM_ROWS_EXAMINED
The Slow Query LogMySQL Запись запросов дольше long_query_time (по умолчанию 10 секунд), отдельно можно записывать и запросы, которые не используют индекс
Too many connectionsMySQL Когда все max_connections заняты, новые соединения отклоняются с ошибкой Too many connections
AI.NavMesh.pathfindingIterationsPerFrameUnity Поиск пути обрабатывает за кадр только заданное число узлов и распределяется на несколько кадров, поэтому игра идёт плавно, даже когда пути длинные или запросов сразу много
Application.runInBackgroundUnity По умолчанию false, и в фоне игра останавливается. На Android игра в фоне останавливается при любой настройке, iOS эту настройку игнорирует
Authority (Netcode for GameObjects 2.5)Unity В модели распределённого авторитета каждый экземпляр игры (клиент) отвечает за часть сетевых объектов и рассчитывает их
Entity struct (Entities 1.3)Unity Entity состоит из Index и номера поколения (Version), что позволяет понять, действителен ли ещё переиспользованный Index
Garbage collection modesUnity Инкрементальный GC включён по умолчанию и собирает мусор частями за несколько кадров. Если его выключить, главный поток стоит всё время проверки кучи, вплоть до сотен ms
Handling variation in timeUnity Maximum Allowed Timestep по умолчанию 1/3 с (0,3333333): даже если игра простояла 1 секунду, игровое время продвинется только на 0,333 с. Этот предел разрывает порочный круг, когда догоняющие шаги снова замедляют игру
Introduction to level of detailUnity Без LOD даже мелкие на экране объекты рисуются с той же детализацией, LOD снижает нагрузку на отрисовку
Introduction to prediction (Netcode for Entities 6.5)Unity Клиент и сервер предсказывают одним и тем же кодом симуляции. Если состояние расходится с серверным (ошибка предсказания), клиент возвращается назад и пересчитывает, и коррекция становится видна
Physics (Netcode for Entities 6.5)Unity Компенсация задержки: сервер берёт мир коллизий в том состоянии, которое клиент видел на этом тике, и по нему проверяет попадание
Profiler markers referenceUnity GC.Collect: время, пока код программы стоит из-за сборки мусора (от менее 1 ms до сотен ms), GC.Alloc: аллокация в управляемой куче
Shader loadingUnity При первом использовании варианта шейдера графический драйвер собирает его для GPU, и игра может заметно замереть. Собранный вариант кэшируется, и повторной остановки нет
Texture and mesh loadingUnity Синхронная загрузка читает данные и передаёт их на GPU в главном потоке за один кадр, что даёт заметную остановку. Асинхронная загрузка стримит данные на протяжении нескольких кадров
Time synchronization (Netcode for Entities 6.5)Unity Серверное время оценивается по времени пути туда и обратно, а подстройка идёт за счёт небольшого изменения скорости хода часов, без резких переводов времени
Time.timeAsDoubleUnity Версия Time.time в double: при долгой работе точнее float, поэтому в большинстве случаев рекомендуется она
Asynchronous Commit (PostgreSQL Documentation)PostgreSQL Если накапливать записи и сбрасывать их позже, производительность растёт, но при сбое могут пропасть самые последние транзакции (тот же компромисс)
Number Of Database ConnectionsPostgreSQL Когда ресурсы БД исчерпаны, рост числа соединений даже снижает производительность. И для задержки, и для пропускной способности лучше держать столько активных соединений, сколько позволяют ресурсы, а остальные запросы держать в очереди
PostgreSQL 17 Release NotesPostgreSQL Появилось представление pg_stat_checkpointer, столбцы, связанные с контрольными точками, перенесены в него из pg_stat_bgwriter
Reliability (PostgreSQL Documentation)PostgreSQL У обычных SATA-дисков и многих SSD есть кэш записи, который теряется при отключении питания, поэтому для гарантированной записи нужен кэш с батареей или защитой от потери питания
Routine Vacuuming (PostgreSQL Documentation)PostgreSQL Старые версии строк нельзя удалить, пока их может видеть другая транзакция, долго открытую транзакцию нужно завершить или закрыть её сессию
WAL Configuration (PostgreSQL Documentation)PostgreSQL Контрольная точка выполняется по умолчанию каждые 5 минут или каждый 1 GB WAL (max_wal_size) и стоит дорого, потому что записывает все грязные страницы. checkpoint_completion_target растягивает запись, чтобы избежать всплеска ввода-вывода. Если интервал между контрольными точками короче checkpoint_warning, в лог пишется предупреждение с советом увеличить max_wal_size
A Multifaceted Look at Starlink Performance (WWW 2024)ACM Starlink каждые 15 с одновременно по всему миру перераспределяет маршруты, на этих границах колеблются задержка и пропускная способность и бывают обрывы короче 1 с (переключение между спутниками тут ни при чём), задержка на участке терминал ↔ спутник ↔ наземная станция около 40 ms
Capacity of Ad Hoc Wireless Networks (MobiCom 2001)ACM При многократной ретрансляции по 802.11 узел не может передавать, пока принимает, а соседние участки мешают друг другу, поэтому пропускная способность цепочки ретрансляторов теоретически падает до 1/3 (в моделировании примерно до 1/7)
Data Center TCP (DCTCP) (SIGCOMM 2010)ACM У типовых коммутаторов неглубокие буферы (48 портов делят 4 MB, один порт может занять около 700 KB), если несколько потоков на короткое время сходятся в один порт, возникают потери
Electri-Fi Your Data: Measuring and Combining Power-Line Communications with WiFi (IMC 2015)ACM Серийное оборудование для передачи по электросети (IEEE 1901, HomePlug AV) использует CSMA/CA, как Wi-Fi, и из-за кратковременной неравномерности доступа джиттер может расти. Качество связи меняется из-за помех от бытовой техники и её включения и выключения (в масштабе от минут до часов)
The Internet at the Speed of Light (HotNets 2014)ACM Реальный путь через маршрутизаторы по медиане примерно в 1,5 раза длиннее прямого оптоволоконного пути, бывают случаи, когда пакет между двумя близкими точками идёт через другую сторону земного шара (hairpinning)
The QUIC Transport Protocol: Design and Internet-Scale Deployment (SIGCOMM 2017)ACM 2016 год: 4,4% клиентов не могли использовать QUIC поверх UDP (блокировка UDP или QUIC либо малый MTU пути, в основном за корпоративными файрволами, блокировка целым провайдером не наблюдалась), 0,3% находились в сетях, похожих на ограничение скорости UDP (рост потерь в часы пик, после обращений к провайдерам доля снизилась с 1% в 2015 году), случай с файрволом, который после изменения 1 бита заголовка пропускал только первые несколько пакетов и блокировал остальные, из-за чего не срабатывала логика перехода на TCP
AActor::SetLifeSpanEpic Games Если задать актору время жизни, по его истечении актор уничтожается автоматически
Actor Priority in Unreal EngineEpic Games Когда пропускной способности не хватает, акторы реплицируются не все и не каждый раз: приоритет определяется по расстоянию до наблюдателя и времени с последней репликации
Actor Relevancy in Unreal EngineEpic Games Сервер реплицирует для каждого соединения только релевантные (relevant) акторы, а нерелевантные не отправляет
Actor Ticking in Unreal EngineEpic Games Если отдельно не задать интервал, акторы и компоненты выполняют тик раз в кадр, а когда он не нужен, тик можно отключить
Detailed Actor Replication Flow in Unreal EngineEpic Games NetUpdateFrequency задаёт частоту обновления для каждого актора. Акторы отправляются по приоритету, а когда соединение забито, остальные откладываются до следующего тика
Introduction to Iris in Unreal EngineEpic Games Реплицируемое состояние хранится в одной квантованной копии, что сокращает дорогую работу, а её результат используют сразу несколько подключений
Networking Insights in Unreal EngineEpic Games Показывает размеры пакетов, отправленных и полученных по каждому соединению, и реплицируемые объекты и свойства внутри них
Networking Overview for Unreal EngineEpic Games Хост listen-сервера получает преимущество перед другими клиентами и несёт большую нагрузку, потому что одновременно работает сервером и рендерит
PSO Precaching for Unreal EngineEpic Games С включённым r.PSOPrecache.Validation команда stat PSOPrecache показывает статистику пропущенных PSO, а в лог пишется «PSO PRECACHING MISS». Создание PSO во время игры дольше 20 ms (порог по умолчанию) считается рывком (hitch)
Replication Graph in Unreal EngineEpic Games В играх с большим числом игроков и реплицируемых объектов (MMORPG и т. п.) объекты группируют по местоположению и отправляют только нужные, иначе CPU сервера становится узким местом
Stat Commands in Unreal EngineEpic Games stat GC (статистика сборки мусора), stat Hitches (пишет в лог кадры дольше t.HitchFrameTimeThreshold)
Texture Streaming Overview for Unreal EngineEpic Games Стример повышает и понижает разрешение текстур (мип-уровни) в зависимости от положения камеры. Большая часть расчётов идёт в асинхронных рабочих потоках, а первыми загружаются мип-уровни, видимые на экране
Using Gameplay Abilities in Unreal EngineEpic Games Local Predicted выполняется сразу при нажатии, а окончательно решает сервер. В Server Initiated предсказания нет, и тот, кто применяет способность, видит задержку
Using Network Emulation in Unreal EngineEpic Games Тестирование с минимальной и максимальной задержкой и долей потерь пакетов на сервере и клиенте, в консоли задаётся, например, как NetEmulation.PktLag
Using the Anti-Cheat InterfacesEpic Games Если сервер не получает сообщения античита от клиента за заданное время (RegisterTimeout), он кикает игрока по таймауту аутентификации (частая причина: клиент завис на загрузке). Если проблема в недавнем обновлении модуля, возвращаются к предыдущей версии модуля
Android (Google) 17
Android common kernelsAndroid (Google) Одновременно поддерживаются общие ядра от 5.10 до 6.18, и ядро для предыдущей платформы (например, android14-6.1) можно использовать при выпуске новых устройств на Android или при их обновлении
ApplicationExitInfoAndroid (Google) REASON_LOW_MEMORY: процесс приложения завершён системным low memory killer (устройства без поддержки сообщают REASON_SIGNALED и SIGKILL)
Cached apps freezerAndroid (Google) Android 14 и новее замораживает процесс приложения, перешедший в кэшированное состояние, через 10 секунд. После заморозки все потоки стоят
CrashesAndroid (Google) Краш: неожиданное завершение приложения из-за необработанного исключения или сигнала (SIGSEGV и т. п.), статистика собирается в Android vitals в Play Console
Frame Pacing libraryAndroid (Google) На экране 60 Hz при отсутствии нового кадра снова показывается предыдущий. Пример игры на 30 FPS, у которой время кадра скачет: 49, 16, 33 ms
Memory allocation among processesAndroid (Google) Android держится за счёт сжатия памяти в zRAM, а когда памяти не хватает, low memory killer завершает процессы. Если завершено приложение на переднем плане, это выглядит как краш
Network security configurationAndroid (Google) При закреплении сертификата нужно добавить резервный ключ на случай смены ключа или CA, иначе соединения не будут проходить до обновления приложения
Optimize network accessAndroid (Google) Задержка смены состояния радиомодуля и время tail зависят от технологии (3G, LTE, 5G) и настроек оператора. Пример для 3G: из экономичного состояния в полную мощность около 1,5 с, из режима ожидания в полную мощность больше 2 с
Read network stateAndroid (Google) При смене сети по умолчанию новые соединения идут через новую сеть, а соединения через прежнюю в итоге принудительно рвутся. Смену отслеживают через registerDefaultNetworkCallback
Security with network protocolsAndroid (Google) Если сервер отдаёт цепочку без промежуточного сертификата, Android-приложение получает SSLHandshakeException, а браузер на ПК может подставить сохранённый промежуточный сертификат и обойтись без ошибки. Цепочку, которую отдаёт сервер, проверяют через openssl s_client
Slow renderingAndroid (Google) Для 60 FPS кадр нужно отрисовать за 16 ms. Если не успеть, кадр пропускается и картинка дёргается (jank)
Slow Sessions (games only)Android (Google) Android vitals считает кадр игры медленным, если он длиннее 50 ms (20 FPS) или 34 ms (30 FPS)
TelephonyDisplayInfoAndroid (Google) OVERRIDE_NETWORK_TYPE_NR_NSA: индикатор сети, когда устройство подключено к LTE и может установить или уже установило двойное подключение (EN-DC) к 5G (NR)
Thermal APIAndroid (Google) Устройство держит высокую производительность ограниченное время, затем из-за нагрева включается троттлинг. Рекомендуется заранее снижать нагрузку по тепловому состоянию
Wi-Fi low-latency modeAndroid (Google) В режиме низкой задержки энергосбережение Wi-Fi отключается, а оптимизация сканирования и роуминга зависит от реализации у производителя устройства
WifiManagerAndroid (Google) WIFI_MODE_FULL_LOW_LATENCY (API 29, Android 10): блокировка Wi-Fi с низкой задержкой, действует, только когда устройство подключено к AP, экран включён и приложение на переднем плане
Window.setPreferMinimalPostProcessingAndroid (Google) Окно, для которого важна задержка (например, игра), запрашивает у дисплея минимальную обработку изображения. При подключении по HDMI отправляются сигналы ALLM и Game Content Type, и телевизор переходит в режим низкой задержки
connect(2) — Linux manual pageLinux man-pages EADDRNOTAVAIL: соединение не открыть, потому что заняты все порты из диапазона эфемерных портов
core(5) — Linux manual pageLinux man-pages RLIMIT_CORE задаёт предел размера core-файла, coredump_filter выбирает, какие области памяти включать, core dump можно передать по конвейеру в программу и обработать отдельно
epoll(7) — Linux manual pageLinux man-pages Механизм уведомлений о событиях ввода-вывода, который масштабируется на одновременное наблюдение за множеством fd
fsync(2) — Linux manual pageLinux man-pages fsync сбрасывает изменённые данные на диск (включая кэш диска) и блокирует вызов, пока устройство не сообщит о завершении
getrlimit(2) — Linux manual pageLinux man-pages RLIMIT_NOFILE: лимит числа fd, которые может открыть процесс, при превышении EMFILE
listen(2) — Linux manual pageLinux man-pages Backlog в listen, превышающий somaxconn, молча урезается. somaxconn по умолчанию 4 096 (с версии 5.4, раньше 128). При заполненной очереди запрос можно проигнорировать и положиться на повтор со стороны клиента
mallopt(3) — Linux manual pageLinux man-pages Чтобы потоки меньше конкурировали, malloc в glibc создаёт арены, число которых может доходить до кратного числу CPU, и чем больше арен, тем больше потребление памяти (ограничивается M_ARENA_MAX, задаётся и переменной окружения MALLOC_ARENA_MAX)
proc_stat(5) — Linux manual pageLinux man-pages steal: время, отнятое в виртуализированной среде на выполнение других операционных систем
send(2) — Linux manual pageLinux man-pages Если в буфере отправки нет места, send() блокируется, а в неблокирующем режиме сразу возвращает EAGAIN
socket(7) — Linux manual pageLinux man-pages SO_RCVBUF задаёт максимальный размер буфера приёма сокета, значение по умолчанию берётся из rmem_default, максимум из rmem_max (Android тоже работает на ядре Linux)
tcp(7) — Linux manual pageLinux man-pages После 7 200 с простоя 9 проб с интервалом 75 с (ещё около 11 минут). Действует только на сокеты с включённым SO_KEEPALIVE. Опции TCP_KEEPIDLE и TCP_USER_TIMEOUT
Azure network round-trip latency statisticsMicrosoft Azure Медианы измеренного времени туда и обратно от Сеула (Korea Central): Токио 30 ms, Сингапур 68 ms, запад США 124–136 ms, Европа 234–244 ms
Bulkhead PatternMicrosoft Azure Если для каждого вызываемого сервиса держать отдельный пул соединений и потоков, сбой одного сервиса блокирует только его пул
Chatty I/O antipatternMicrosoft Azure Множество мелких запросов ввода-вывода накапливает задержку и сильно ухудшает отзывчивость. Рекомендуется объединять их в более крупные и редкие запросы
Circuit Breaker PatternMicrosoft Azure Запросы, которые висят до таймаута, держат потоки и соединения с БД, и из-за этого отказывают даже не связанные функции. Если за заданное время накопилось слишком много неудач, вызовы сразу отклоняются
Configure load balancer TCP reset and idle timeoutMicrosoft Azure Таймаут простоя Azure Load Balancer по умолчанию 4 мин (4–100 мин), после него сохранение сессии не гарантируется, отправка TCP reset включается отдельно
Disk metricsMicrosoft Azure Data Disk Used Burst IO Credits Percentage и другие метрики использования burst-кредитов дисков и ВМ (интервал 5 минут)
Extraneous Fetching antipatternMicrosoft Azure Если извлекать больше данных, чем нужно, растёт нагрузка на ввод-вывод и замедляются ответы
Maintenance and updatesMicrosoft Azure Обслуживание без перезагрузки почти всегда останавливает VM меньше чем на 10 с, изредка (для обычных размеров не чаще раза в 18 месяцев) примерно на 30 с, живая миграция обычно не дольше 5 с, после остановки часы синхронизируются автоматически, долгие TCP-соединения могут рваться, а данные, отправленные остановленной VM, другая сторона повторяет с экспоненциальным backoff, и восстановление затягивается, health check балансировщика примерно за 10 с признаёт VM неисправной, проверка по Microsoft.Compute/virtualMachines/liveMigration/action в журнале действий и по VmAvailabilityMetric, которая на время остановки падает до 0, время применения выбирается через Maintenance Configuration
Managed disk burstingMicrosoft Azure Premium SSD P20 и меньше используют burst на основе кредитов, при полном запасе кредитов максимальная скорость burst держится 30 минут
Metrics and alerts for Azure NAT GatewayMicrosoft Azure Если SNAT Connection Count с фильтром по состоянию Failed больше 0, вероятно исчерпание портов SNAT, Dropped Packets
Scheduled Events for Linux VMs in AzureMicrosoft Azure О Freeze (остановка на несколько секунд, CPU и сеть могут замереть) предупреждают минимум за 15 мин, при отказе оборудования хоста восстановление начинается сразу, без периода уведомления
Source Network Address Translation (SNAT) with Azure NAT GatewayMicrosoft Azure 64 512 портов SNAT на один публичный IP (не больше 16 IP), каждому соединению к одной цели нужен отдельный порт, закрытый порт проходит период охлаждения перед повторным использованием для той же цели
Oracle 9
Available CollectorsOracle ZGC немного жертвует пропускной способностью ради максимальной паузы меньше 1 ms, пауза не зависит от размера кучи
Garbage Collector ImplementationOracle Когда заполняется область Young, выполняется minor GC, часть выживших объектов переносится в область Old, а когда заполняется Old, собирается вся куча (намного дольше, чем minor). -Xlog:gc пишет по строке на каждый GC
Garbage-First (G1) Garbage CollectorOracle Целевая пауза G1 по умолчанию 200 ms (MaxGCPauseMillis). Если во время сборки кончается память, G1 переходит к Full GC с полной остановкой и сжатием всей кучи
Garbage-First Garbage Collector TuningOracle По умолчанию (GCTimeRatio=12) G1 подбирает размер кучи так, чтобы GC занимал не больше примерно 8% времени. Full GC из-за слишком заполненной кучи ищут в логе по строкам Pause Full (G1 Compaction Pause)
The java CommandOracle Таблица замены старых параметров GC-лога на -Xlog: -XX:+PrintGCDetails соответствует -Xlog:gc*
The Parallel CollectorOracle Parallel GC выдаёт OutOfMemoryError, если тратит на GC больше 98% всего времени и освобождает меньше 2% кучи
The Z Garbage CollectorOracle ZGC выполняет дорогую работу конкурентно и не останавливается дольше 1 ms, но если сборка не успевает освобождать память, приложение может встать в ожидании GC (конкурентный режим в эксперименте с GC)
Troubleshoot Memory LeaksOracle Если программа работает всё медленнее, стоит подозревать утечку, в итоге память кончается и процесс аварийно завершается. Главный материал для анализа утечки: дамп кучи
Redis 9
Diagnosing latency issuesRedis Запросы по очереди обрабатывает один поток, и медленная команда блокирует всё за ней, SCAN вместо KEYS, fork по измерениям на физических серверах и современных ВМ занимает около 9–13 ms на 1 GB, THP из-за копирования после fork резко увеличивает задержки и память, массовое истечение ключей в одну секунду вызывает остановку
INFORedis keyspace_hits и keyspace_misses (число успешных и неуспешных поисков ключа), expired_keys (число истёкших ключей), uptime_in_seconds (время с момента запуска)
KEYSRedis В боевой среде использовать с крайней осторожностью, на большой базе может убить производительность (на бюджетном ноутбуке 40 ms на 1 000 000 ключей)
Redis CLIRedis --bigkeys: просматривает пространство ключей и находит большие ключи
Redis latency monitoringRedis latency-monitor-threshold по умолчанию 0 (выключен), LATENCY LATEST и LATENCY DOCTOR, запись задержек по событиям вроде fork и expire-cycle
Redis persistenceRedis Если делать снапшоты RDB раз в несколько минут, при аварийном завершении нужно быть готовым потерять данные за последние несколько минут
SLOWLOGRedis Журнал медленных команд записывает команды дольше slowlog-log-slower-than, время выполнения не включает ввод-вывод при обмене с клиентом
UNLINKRedis Асинхронное удаление: ключ сразу отсоединяется, а память освобождается в другом потоке
Cloudflare 1.1.1.1 Incident on July 14, 2025Cloudflare Публичный DNS-резолвер не работал 62 минуты, и для пользователей, которые не могли разрешать имена, практически все интернет-сервисы стали недоступны
How "expensive" is crypto anyway?Cloudflare Замеры BoringSSL: AES-128-GCM около 3,7 GB в секунду (сильно зависит от размера записи). Одно ядро в секунду выполняет 1 120 подписей RSA 2048, 18 477 подписей ECDSA P-256 и 9 394 обмена P-256 ECDHE. На edge-серверах Cloudflare TLS-библиотека расходует около 1,8% CPU
How to receive a million packets per secondCloudflare Замеры, в которых при одной очереди приёма на одно ядро это ядро упиралось примерно в 350–430 тыс. пакетов в секунду, случай, когда NIC хешировал UDP только по IP-адресам и весь трафик шёл в одну очередь
Maximum transmission unit and maximum segment sizeCloudflare Входящий трафик после очистки доставляется через GRE-туннель (MTU 1 476), исходящие ответы идут сразу в интернет (DSR), TCP MSS рекомендуется ограничить до 1 436, иначе большие пакеты отбрасываются или фрагментируются
Q1 2024 Internet disruption summaryCloudflare Обрыв кабелей у Западной Африки (14 марта) устранили через 3–6 недель, всё это время трафик переводили на другие кабели
Q2 2024 Internet disruption summaryCloudflare Кабели в Красном море, повреждённые в феврале 2024 года, в июле всё ещё ремонтировались (зона конфликта), обрыв EASSy и Seacom в мае устранили за 19 дней
Why does one NGINX worker take all the load?Cloudflare SO_REUSEPORT делит подключения по очередям воркеров простым хешем, поэтому если один воркер застрял, встают все подключения в его очереди
Gaffer On Games 7
Deterministic LockstepGaffer On Games Кадр n можно рассчитать, только когда пришёл весь ввод, поэтому при опоздании игра ждёт. Если буфер задержки воспроизведения, поглощающий джиттер, мал, бывают замирания
Floating Point DeterminismGaffer On Games Даже один и тот же код с плавающей точкой может давать разные результаты в зависимости от компилятора, архитектуры CPU и сборки (debug или release). Известен случай, когда CPU AMD и Intel выдавали немного разные значения трансцендентных функций
Snapshot CompressionGaffer On Games Изменения нужно формировать только относительно опорного состояния (baseline), получение которого подтвердила другая сторона (ack), а начальное состояние отправлять отдельно
Snapshot InterpolationGaffer On Games Если рисовать снапшоты сразу по приходу, из-за джиттера картинка дёргается, а если ненадолго накапливать их в буфере интерполяции, движение плавное
State SynchronizationGaffer On Games Если отправлять вместе с вводом и состояние, стороны можно синхронизировать и без полного детерминизма
UDP vs. TCPGaffer On Games UDP не гарантирует ни доставку, ни порядок, поэтому потерянные пакеты нужно обнаруживать и отправлять повторно самостоятельно
IP addresses and portsGoogle Cloud На один NAT IP по 64 512 портов для TCP и для UDP, минимум портов на VM по умолчанию 64 (статическое выделение) и 32 (динамическое), число зарезервированных за VM портов ограничивает число одновременных соединений к одной цели, порт закрытого соединения нельзя использовать на время TIME_WAIT
Live migration process during maintenance eventsGoogle Cloud Остановка при живой миграции обычно намного короче 1 с, за время остановки системные часы прыгают вперёд до 5 с, во время переноса ненадолго падает производительность диска, CPU, памяти и сети, VM без живой миграции при обслуживании выключаются (bare metal её не поддерживает)
Logs and metricsGoogle Cloud dropped_sent_packets_count с reason OUT_OF_RESOURCES: пакеты, отброшенные из-за нехватки NAT IP или портов
MTU considerations | Cloud VPNGoogle Cloud MTU шлюза Cloud VPN 1 460 байт, MTU полезной нагрузки туннеля IPv4 1 406 байт (после туннеля около 1 400)
Query metadata server for maintenance event noticesGoogle Cloud Значение метаданных maintenance-event меняется за 60 с до живой миграции (если VM настроена на живую миграцию и после прошлого обслуживания это значение хотя бы раз запрашивали)
ss(8) — Linux manual pageiproute2 timer:(on,…) в выводе -o означает таймер повторной передачи, backoff в выводе -i показывает, сколько раз ожидание перед повтором удваивалось
tc-fq(8) — Linux manual pageiproute2 Очередь fq делает пейсинг для каждого сокета (соединения), SO_MAX_PACING_RATE задаёт максимальную скорость соединения
tc-netem(8) — Linux manual pageiproute2 Инструмент для тестирования, который добавляет к исходящим пакетам задержку и джиттер (delay TIME JITTER) и потери (loss random PERCENT), имитируя реальную сеть
Apple 6
Extending your app’s background execution timeApple При уходе в фон на applicationDidEnterBackground даётся 5 секунд, затем приложение приостанавливается. Если нужно больше, время запрашивают через beginBackgroundTask (остаток виден в backgroundTimeRemaining)
Identifying high-memory use with jetsam event reportsApple Если нехватка памяти не проходит, iOS принудительно завершает приложения (jetsam). Приложение, превысившее свой лимит памяти, становится кандидатом на завершение
thermalStateApple Текущий уровень нагрева, который сообщает iOS. При повышении уровня приложение должно сокращать потребление ресурсов
Wi-Fi roaming support in Apple devicesApple При переходе на другую AP данные нельзя отправлять, пока не завершится аутентификация на новой AP, а в среде 802.1X это может занять несколько секунд
Bufferbloat.net 6
CakeBufferbloat.net CAKE: SQM для роутеров, объединяющий шейпер и управление очередью семейства fq_codel
IntroductionBufferbloat.net Если роутер или другое сетевое оборудование копит слишком много данных, задержка резко растёт (bufferbloat)
Setting up SQM for CeroWrt 3.10Bufferbloat.net Скорость в SQM нужно снизить до 95% от измеренной (или до 85% от заявленной провайдером), чтобы узкое место переместилось из оборудования провайдера внутрь роутера, иначе эффекта не будет
Smart Queue ManagementBufferbloat.net SQM: подход, сочетающий планирование по потокам, управление длиной очереди (AQM) и шейпинг
Tests for BufferbloatBufferbloat.net Если держать пинг запущенным, загрузить подключение тестом скорости и пинг вырастет, это bufferbloat
What Can I Do About Bufferbloat?Bufferbloat.net Использовать роутер с поддержкой SQM вроде cake или fq_codel и подбирать скорость SQM, измеряя задержку под нагрузкой
Google 6
An Internet-Wide Analysis of Traffic PolicingGoogle Различие: при переполнении очереди до потерь сначала растут время ожидания и RTT, а полисинг отбрасывает избыток без роста RTT (SIGCOMM 2016)
Load Balancing in the DatacenterGoogle При простом round robin загрузка CPU между задачами расходится до 2 раз, взвешенное распределение, при котором бэкенд передаёт свою нагрузку в ответах и health check, состояние lame duck, в котором бэкенд просит больше не присылать ему запросы
The Tail at ScaleGoogle Редкие длинные задержки (хвостовая задержка) с ростом масштаба определяют общее впечатление от сервиса
Microsoft SQL Server 6
Deadlocks guideMicrosoft SQL Server Интервал проверки на дедлок по умолчанию 5 секунд, при частых дедлоках он сокращается до 100 ms. Сессия system_health, включённая по умолчанию, собирает xml_deadlock_report, жертва получает ошибку 1205
Monitor performance by using the Query StoreMicrosoft SQL Server Изменения статистики, схемы или индексов меняют план, а кэш планов хранит только последний план. Принудительный план в хранилище запросов фиксирует хороший план, представление «Регрессированные запросы» (Regressed Queries) позволяет сравнить замедлившиеся запросы и их планы
Parameter Sensitive Plan OptimizationMicrosoft SQL Server Если данные распределены неравномерно, один закэшированный план подходит не для всех значений параметров
Query Processing Architecture GuideMicrosoft SQL Server Прослушивание параметров: план выполнения строится под значения параметров, переданные при компиляции или перекомпиляции
Transaction Locking and Row Versioning GuideMicrosoft SQL Server Если один оператор захватывает 5 000 и больше блокировок в одной таблице (или индексе), происходит эскалация блокировок, её записывает расширенное событие lock_escalation
Troubleshoot a full transaction log (SQL Server Error 9002)Microsoft SQL Server Когда журнал заполнен, БД доступна только для чтения, изменять данные нельзя. Частые причины, которые мешают очистке журнала: пропущенный бэкап журнала, отставание репликации, длинные транзакции. Что именно мешает, показывает log_reuse_wait_desc в sys.databases
Wireshark 6
7.5. TCP AnalysisWireshark TCP ZeroWindow: пакет, которым получатель объявляет окно 0 и заставляет отправителя остановить передачу
8.7. Packet LengthsWireshark Делит захваченные пакеты на диапазоны длины и показывает для каждого количество, среднее, минимум и максимум
8.8. The “I/O Graphs” WindowWireshark Строит график числа пакетов и байтов, подходящих под фильтр отображения, по интервалам времени
.NET runtime metrics.NET Начиная с .NET 9 dotnet.monitor.lock_contentions: сколько раз с запуска процесса попытка захватить блокировку монитора наткнулась на конкуренцию
Background garbage collection.NET Фоновый GC применяется только к сборке поколения 2, а сборка поколений 0 и 1 (GC переднего плана) останавливает все управляемые потоки
Debug a memory leak in .NET.NET Даже при наличии GC постоянные ссылки на ненужные объекты дают утечку, падение производительности и OutOfMemoryException. Проверка тренда памяти и анализ дампов
dotnet-counters diagnostic tool.NET В .NET 9 и новее метрики публикуются через System.Runtime (dotnet.gc.pause.time и др.), в .NET 8 и ниже через старые EventCounter (% Time in GC since last GC и др.)
Efficient Querying.NET Ленивая загрузка в ORM порождает проблему N+1, когда на каждый элемент уходит ещё один запрос, и сильно снижает производительность. Рекомендуется загружать данные одним разом (eager loading)
JEP 271: Unified GC LoggingOpenJDK Начиная с JDK 9 GC-лог переведён на единое журналирование (-Xlog). -Xlog:gc, как прежний -XX:+PrintGC, пишет по строке на каждый GC
JEP 439: Generational ZGCOpenJDK Паузы ZGC не дольше 1 ms и не зависят от размера кучи, паузы G1 от единиц ms до нескольких секунд. Если аллокации опережают освобождение памяти, возможна остановка аллокаций (allocation stall)
systemd.service(5) — Linux manual pagesystemd Restart=on-failure автоматически перезапускает сервис при аварийном завершении, завершении по сигналу (в том числе с core dump) и срабатывании watchdog. Рекомендуется для долгоживущих сервисов
systemd.timer(5) — Linux manual pagesystemd RandomizedDelaySec сдвигает запуск планового задания на случайное время и уменьшает скопление нагрузки
ITU 4
ITU-T G.114: One-way transmission timeITU Значение для планирования: задержка распространения по оптоволокну 5 µs/km (около 200 000 km в секунду, 10 ms туда и обратно на 1 000 km)
Teletraffic Engineering Handbook (ITU-D Study Group 2 Question 16/2)ITU Среднее ожидание M/M/1 W = A·s/(1−A): при утилизации 50%, 80% и 90% в 1, 4 и 9 раз больше времени обработки. При той же утилизации ожидание короче, когда воркеров (серверов) больше и поступление равномернее
sysstat 4
iostat(1) — Linux manual pagesysstat -x: w_await (среднее время обработки запроса на запись, включая ожидание в очереди), aqu-sz (средняя длина очереди, прежнее название avgqu-sz)
mpstat(1) — Linux manual pagesysstat %soft: доля времени CPU на обработку программных прерываний, с -P ALL по каждому ядру
Source SDK 2013: player.cppValve Бюджет обработки команд, который копится каждый тик (максимум sv_maxusrcmdprocessticks, 24 тика), позволяет принять команды, пришедшие пачкой. В комментарии разработчиков сказано, что при более строгом ограничении микрофризы получали и обычные игроки
Steam Overlay (Steamworks Documentation)Valve Оверлей Steam автоматически подключается через хуки к играм, запущенным из Steam, и из-за такого способа может выявлять ошибки работы с памятью в том, как игра использует API рендеринга, что приводит к крашам
AMD FSR Frame GenerationAMD Для генерации кадров рекомендуется исходная частота от 60 FPS (ниже 30 FPS её следует избегать). AMD Radeon Anti-Lag 2 согласует работу CPU и GPU и снижает системную задержку
HED-GP Technical Retrospective: What a HED-acheCCP Games При перегрузке EVE Online замедляет игровое время через Time Dilation, нижний предел 10% (в 10 раз медленнее). В обычном режиме CPU узла ниже 80%
Introducing Time Dilation (TiDi)CCP Games Архитектура, где при перегрузке сервера игровые часы замедляются (Time Dilation) и всё течёт медленнее
Time Dilation – How’s That Going?CCP Games Time Dilation в EVE Online действует на весь узел, поэтому замедляются и далёкие звёздные системы на том же узле. Крупные сражения обрабатывают на усиленных узлах, где размещены только 4 системы
chrony 3
chrony – Frequently Asked Questionschrony Рекомендуется разрешать шаговую коррекцию лишь несколько раз сразу после запуска, например makestep 1 3. Виртуальная машина, которую остановили и возобновили, может проснуться с неверным временем
chrony.conf(5)chrony logchange: если часы скорректированы больше чем на это значение (по умолчанию 1 с), запись попадает в syslog
chronyc(1)chrony System time (разница между временем NTP и системными часами), Last offset (смещение, оценённое при последней коррекции), Ref time (момент, когда учтено последнее измерение источника времени) из chronyc tracking
Go 3
A Guide to the Go Garbage CollectorGo GC в Go работает в основном конкурентно, полные остановки короткие. При большом объёме аллокаций горутины берут на себя часть работы GC (assist), и появляются задержки
runtime packageGo GODEBUG=gctrace=1: по строке на каждый GC, время по wall clock для каждой фазы, размер кучи в начале и в конце GC и целевой размер кучи
IEEE 3
Amdahl's Law in the Multicore EraIEEE Статья в IEEE Computer 2008 (авторская версия). Если доля работы, которую нельзя распараллелить, равна 1−f, то сколько ядер ни добавляй, ускорение не превысит 1/(1−f) (закон Амдала)
Liveness, Readiness, and Startup ProbesKubernetes Дедлок, при котором приложение работает, но не может продвинуться, ловят liveness-проверкой и перезапускают контейнер
CUDA C++ Best Practices GuideNVIDIA Пропускная способность видеопамяти (V100: 898 GB/s) намного выше, чем у PCIe x16 3-го поколения (16 GB/s), поэтому рекомендуется сокращать обмен с оперативной памятью ПК
NVIDIA DLSSNVIDIA DLSS Frame Generation рассчитана на работу вместе с NVIDIA Reflex (функцией низкой задержки), чтобы отзывчивость сохранялась
perf 3
perf-stat(1) — Linux manual pageperf С -p считает аппаратные события работающего процесса и показывает insn per cycle, -d добавляет события кэша данных L1 и LLC
perf-top(1) — Linux manual pageperf В реальном времени показывает долю CPU работающего процесса (-p) или потока (-t) по функциям (символам)
perf-trace(1) — Linux manual pageperf -p трассирует системные вызовы работающего процесса, --duration показывает только вызовы дольше заданного числа ms
Riot Games 3
Peeking into VALORANT's NetcodeRiot Games Если опоздавшие или потерянные данные восполняются догадкой и она неверна, картинка расходится с сервером, и персонаж при коррекции скачет или будто скользит
Peeking into VALORANT's NetcodeRiot Games Сервер отматывает время назад к состоянию игры, которое видел игрок в момент выстрела, и проверяет попадание. Клиент вместе с выстрелом отправляет время симуляции, которое он видел
VALORANT's 128-Tick ServersRiot Games 128-тиковый сервер должен укладываться в 7,8125 ms на кадр. Время серверного кадра измеряют по подсистемам и делят бюджет между ними
RIPE NCC 3
BGPlay (RIPEstat Data API)RIPE NCC Показывает маршруты BGP для диапазона адресов (префикса) на начало периода, обновления BGP, замеченные за этот период, и сведения об AS на пути
Probe Selection (RIPE Atlas REST API)RIPE NCC Зонды для измерений RIPE Atlas выбирают по стране, региону, ASN или диапазону адресов и запускают с них ping и traceroute
RIPE Atlas documentationRIPE NCC Публичный инструмент синтетического мониторинга, запускающий ping и traceroute с точек измерения по всему миру
APNIC 2
BGP updates in 2024APNIC Среднесуточное время, за которое нестабильный маршрут снова стабилизируется: 25–35 с (IPv4), 40–50 с (IPv6)
IPv6 Performance – RevisitedAPNIC Сравнение времени туда и обратно по IPv6 и IPv4 у одних и тех же пользователей с двойным стеком: сети доступа иногда обрабатывают пакеты IPv6 совсем иначе, и внутри одного провайдера появляются группы, где IPv6 медленнее на 15 ms, 25 ms и 75 ms
Istio 2
Istio Standard MetricsIstio istio_request_duration_milliseconds (распределение времени обработки запросов HTTP и gRPC), метка reporter различает прокси отправителя (source) и получателя (destination)
Performance and ScalabilityIstio В режиме sidecar запрос проходит по очереди через sidecar-прокси отправителя и получателя. Чем больше функций, тем длиннее путь обработки внутри прокси, а сбор телеметрии увеличивает ожидание следующего запроса
Let's Encrypt 2
Decreasing Certificate Lifetimes to 45 DaysLet's Encrypt Стандартный срок действия сокращается до 64 дней с февраля 2027 года и до 45 дней с февраля 2028 года. Обновления с фиксированным интервалом 60 дней станет недостаточно, рекомендуется обновлять примерно на 2/3 срока действия
FAQLet's Encrypt Стандартный срок действия сертификата 90 дней, рекомендуется обновлять каждые 60 дней
Geolocation accuracyMaxMind На уровне страны около 99,8%, на уровне города в США (в пределах 50 km) около 66%. С VPN определяется местоположение VPN-сервера вместо конечного пользователя, а IP мобильных сетей используются на большой территории, поэтому точное место не определить. Базу нужно постоянно обновлять, можно запросить исправление
numactl 2
numactl(8) — Linux manual pagenumactl --cpunodebind и --membind привязывают CPU и память процесса к определённому узлу NUMA
numastat(8) — Linux manual pagenumactl Счётчики numa_miss (память выделена не на том узле, где её запрашивали) и other_node (на этом узле выделил память процесс, работающий на другом узле), с -p показывает память процесса по узлам
OpenSSL 2
openssl-s_clientOpenSSL -showcerts: показывает сертификаты в том порядке, в каком их отправил сервер (это не проверенная цепочка)
openssl-x509OpenSSL -enddate: выводит дату истечения сертификата (notAfter), -checkend: проверяет, истечёт ли сертификат в течение заданного числа секунд
SK텔레콤 2
SKT, 고객 선택권과 혜택 강화한 신규 5G 요금제 출시SK텔레콤 Примеры ограничения скорости на тарифах 5G после исчерпания базового трафика: до 400 kbps, 1 Mbps, 3 Mbps
SKT, 요금제 개편SK텔레콤 После исчерпания включённого трафика интернет продолжает работать на скорости до 400 kbps (услуга «Спокойный интернет для всех»)
Solidigm 2
D3-S4520 SSDSolidigm Серверный SATA SSD: случайное чтение и запись блоками 4 KB до 92K/48K IOPS
Solidigm™ D7-P5520 and D7-P5620 Product BriefSolidigm Задержка серверного NVMe SSD на уровне 99,99% (four-nines latency) 130 µs: основание для оценки, что одно чтение с SSD занимает около 100 µs
Response to Congestion (as of Dec. 11)Square Enix Когда в очереди логического дата-центра больше 17 000 человек, новые места не выдаются, чтобы сервер авторизации не упал (Error 2002). При обрыве во время ожидания лобби-сервер ждёт от десятков секунд до 1 минуты: успевший переподключиться игрок продолжает с того же места, остальные попадают в конец очереди
Scaling Memcache at Facebook (NSDI '13)USENIX Когда инвалидируется часто используемый ключ, множество чтений устремляется в БД (thundering herd). Это предотвращают арендой (lease, обновляет только один клиент) и выдачей старого значения, кластер с пустым кэшем прогревают отдельно
util-linux 2
ionice(1) — Linux manual pageutil-linux Задания класса idle получают доступ к диску, только когда им не пользуются другие программы
lsblk(8) — Linux manual pageutil-linux -o выбирает выводимые столбцы, среди столбцов топологии устройства есть ROTA (вращающееся ли устройство)
Amazon Builders' Library 1
Using load shedding to avoid overloadAmazon Builders' Library Отсечение нагрузки (load shedding): лишние запросы отклоняются рано, чтобы сервер продолжал обрабатывать те, с которыми справляется
Apache Software Foundation 1
Asynchronous loggersApache Software Foundation Асинхронное логирование сглаживает короткие всплески очередью, но если вывод долго остаётся медленным, очередь заполняется, и скорость падает до скорости самого медленного вывода, либо логи отбрасываются по заданной политике (Discard)
coreutils 1
df(1) — Linux manual pagecoreutils Занятое место по файловым системам, -i показывает использование inode вместо блоков
Envoy 1
What is EnvoyEnvoy Envoy работает отдельным процессом рядом с каждым сервером приложений, и приложение обменивается данными через Envoy на localhost
GGPO Rollback Networking SDKGGPO Ввод соперника предсказывается, игра идёт вперёд, а если реальный ввод другой, всё пересчитывается от момента расхождения до текущего
GNU Project 1
Threads (Debugging with GDB)GNU Project thread apply all выполняет одну команду для всех потоков (bt: вывод стека вызовов)
HDMI Licensing Administrator 1
Auto Low Latency Mode (ALLM)HDMI Licensing Administrator ALLM позволяет устройству автоматически переключать дисплей в режим низкой задержки (обычно его называют игровым режимом). В этом режиме телевизор отключает часть обработки изображения, чтобы уменьшить задержку
id Software 1
Quake III Arena source: code/server/sv_snapshot.cid Software Дельта-сжатие выполняется относительно снапшота, подтверждённого клиентом, а если опорный снапшот слишком старый, отправляется полный снапшот
iputils 1
ping(8) — Linux manual pageiputils -M do ставит флаг DF и не отправляет пакеты больше MTU пути, -s задаёт размер данных (по умолчанию 56 байт плюс 8 байт заголовка ICMP)
IRTF 1
RFC 9505: A Survey of Worldwide Censorship TechniquesIRTF Оборудование инспекции в сети может выбирать потоки TCP и UDP по адресам, портам и протоколу и блокировать их (для QUIC наблюдалась блокировка UDP-эндпоинтов), блокировка всего, кроме разрешённых протоколов, ведёт к избыточной блокировке, применяется и ограничение скорости для определённого трафика
jemalloc 1
jemalloc memory allocatorjemalloc Универсальная реализация malloc, рассчитанная на защиту от фрагментации и масштабирование при параллельной работе
Juniper Networks 1
Flow-Based SessionsJuniper Networks Офисный файрвол в эксперименте: таймаут сессии файрвола SRX по умолчанию TCP 1 800 с (30 минут), UDP 60 с
Lua.org 1
Lua 5.4 Reference ManualLua.org Инкрементальный режим разбивает сборку на мелкие шаги и вставляет их между участками выполнения программы (если шаг сделать большим, получится полная остановка), major-сборка в поколенческом режиме обходит все объекты с полной остановкой, collectgarbage("count") возвращает общий объём памяти, занятой Lua (в KB)
ntpd - Network Time Protocol (NTP) daemonNetwork Time Foundation Если расхождение превышает порог шага 128 ms, часы переводятся разом, если меньше, корректируются плавно. Скорость 0,5 ms в секунду, поэтому на 1 секунду уходит 2 000 с (около 33 минут)
OpenWrt 1
SQM (Smart Queue Management)OpenWrt Скорости приёма и отдачи указывать на уровне 90% от измеренных, дисциплина очереди рекомендуется cake (на слабом CPU fq_codel)
procps-ng 1
vmstat(8) — Linux manual pageprocps-ng Поля cs (число переключений контекста в секунду) и r (число выполняемых или ожидающих выполнения процессов)
Red Hat 1
Chapter 2. Getting started with TuneDRed Hat Профиль latency-performance отключает энергосбережение, ставит governor performance и через PM QoS разрешает только неглубокие C-state. Текущий профиль показывает tuned-adm active
Seagate 1
Exos X18 Data SheetSeagate Случайное чтение блоками 4K на серверном HDD 7 200 rpm: 170 IOPS (QD16)
Starlink 1
Improving Starlink’s LatencyStarlink Медиана в часы пик в США 48,5 ms → 33 ms, самый медленный 1% (p99) больше 150 ms → меньше 65 ms (2024 год), распространение на одном спутниковом участке 1,8–3,6 ms, обход по лазерным линиям связи добавляет задержку, расстояние от наземной станции до точки выхода в интернет (PoP) тоже влияет на задержку
VLDB Endowment 1
Optimal Probabilistic Cache Stampede PreventionVLDB Endowment Когда истекает популярный элемент, его одновременно пересоздают многие запросы (cache stampede). Это предотвращают вероятностным досрочным обновлением до истечения
과학기술정보통신부 1
5G 통신서비스 품질평가 결과 발표과학기술정보통신부 По данным на 2020 год 5G в Корее предоставляется по схеме NSA, а переход на SA только планируется