Бэкенд многопользовательской игры в реальном времени живёт в мире миллисекунд: задержка, колебания канала и короткие обрывы связи здесь ощущаются сразу, а не прячутся за ретраями.
Глава собирает в одну систему подбор матча, авторитетную симуляцию, размещение игровых сессий по регионам, доставку обновлений состояния и восстановление после разрыва соединения.
В интервью и инженерных обсуждениях этот кейс полезен тем, что быстро показывает, умеете ли вы проектировать под жёсткий бюджет задержек и не разрушать честность игрового процесса.
Бюджет задержки
Каждый лишний переход на пути от ввода до действия сразу ощущается игроком, поэтому задержку нужно раскладывать по этапам, а не держать одной общей цифрой.
Региональный матчмейкинг
Игроков нельзя бездумно смешивать глобально: регион, качество канала и допустимая разница рейтинга напрямую влияют на ощущение честной игры.
Авторитетная симуляция
Сервер должен оставаться источником истины для состояния матча, иначе отзывчивость быстро превратится в читы и расхождение между клиентами.
Восстановление сессии
Короткий обрыв связи не должен выбрасывать игрока из матча: заранее проектируйте окно переподключения, снимки состояния и быстрый досинхрон.
Источник
Gaffer On Games
Классические материалы о сетевой архитектуре многопользовательских игр и синхронизации состояния.
Игра в реальном времени — это система с жёстким бюджетом , где масштабирование и отказоустойчивость упираются в ещё одно требование: матч должен ощущаться честным. Архитектура обычно строится вокруг , регионального и устойчивости к .
Требования
Функциональные
- Подбор матча по рейтингу, региону и бюджету задержек.
- Авторитетный игровой сервер, который рассылает обновления состояния в реальном времени.
- Синхронизация перемещений и игровых событий: выстрелов, столкновений и способностей.
- Поддержка повторного подключения и восстановления сессии после коротких обрывов связи.
- Таблицы лидеров, статистика матчей и события после завершения игры.
Нефункциональные
Задержка: p95 < 80ms
Задержка от ввода до действия должна оставаться низкой и предсказуемой.
Частота тиков: 20-60 TPS
Цикл симуляции должен быть стабильным, чтобы игра ощущалась честной и ровной.
Доступность: 99.99%
Матч не должен разваливаться из-за отказа одного узла или зоны.
Честность: защита от читов и злоупотреблений
Сервер проверяет действия игроков, а клиент не считается источником истины.
Оценка масштаба
Каждый матч — это отдельный процесс симуляции с жёстким на кадр: при 60 тиках в секунду на всю симуляцию остаётся ~16.7 мс, при 128 тиках — всего 7.8 мс. Поэтому масштабирование здесь — это не «больше реплик за балансировщиком», а управление парком из десятков тысяч независимых игровых серверов.
Высокоуровневая архитектура
Архитектура игры и сценарии
Авторитетная многопользовательская модель с интерактивными путями выполненияДоступ и управляющий контур
Игровой и событийный контур
Главный принцип: цикл симуляции изолирован от медленных внешних операций. Один синхронный запрос к БД внутри тика срывает бюджет кадра для всех игроков матча, поэтому тяжёлую логику выносят в асинхронный контур вне критического пути.
Клиентское предсказание и серверное согласование
GDC 2017
Overwatch Gameplay Architecture and Netcode
Доклад Тима Форда о серверной авторитетности, предсказании и откатах в Overwatch.
При времени прохождения туда и обратно (RTT) в 60-100 мс наивная схема «нажал — отправил — подождал ответ сервера — подвинулся» делает управление ватным: игрок замечает разрыв между нажатием и движением уже при задержке около 100 мс. Поэтому клиент применяет ввод немедленно и локально, не дожидаясь сервера, — а сервер остаётся единственным источником истины и позже подтверждает или исправляет результат.
Цикл предсказания
- Клиент применяет ввод сразу к локальной симуляции и кладёт его в буфер неподтверждённых вводов с порядковым номером.
- Тот же ввод уходит на сервер, который прогоняет его через авторитетную симуляцию.
- Сервер отвечает подтверждённым состоянием и номером последнего обработанного ввода.
- Клиент сравнивает серверное состояние со своим предсказанием на тот же номер ввода.
- При расхождении клиент делает к серверному состоянию и за один кадр заново прогоняет все ещё не подтверждённые вводы из буфера (re-simulation).
Почему это стандарт для шутеров
- •Overwatch по умолчанию предсказывает всё: движение, способности и оружие — команда явно отключает предсказание только для отдельных эффектов вроде крупных видимых снарядов.
- •Предсказывать безопасно только детерминированную локальную часть состояния: собственное движение, анимации, перезарядку.
- •Результаты, которые задевают других игроков — урон, смерть, захват цели, — клиент не объявляет сам: их подтверждает только сервер.
Цена ошибки предсказания — «резиновая лента» (rubber banding): при расхождении игрока рывком возвращает в подтверждённую сервером позицию. Чем выше потери пакетов и , тем чаще откаты, поэтому качество предсказания напрямую зависит от транспорта и региональной близости сервера.
Снимки состояния, дельта-компрессия и тикрейт
Источник
Quake 3 Network Model
Разбор сетевой модели Quake 3: снимки, дельта-компрессия против последнего подтверждённого состояния.
Сервер рассылает клиентам мира с частотой тикрейта. Слать полный мир каждый тик нельзя: снимок матча на 100 сущностей занимает единицы килобайт, и при 60 тиках в секунду это сотни килобайт в секунду на каждого игрока. Классическое решение из Quake 3 — дельта-компрессия: сервер хранит историю снимков по каждому клиенту и отправляет только разницу относительно последнего снимка, который клиент подтвердил.
Как работает дельта-цикл
- Подтверждения клиента ездят в обычном входящем трафике, без отдельных запросов.
- Сервер кодирует новый снимок как разницу против последнего подтверждённого: только изменившиеся поля изменившихся сущностей.
- Если подтверждение потерялось, сервер просто считает дельту от более старого снимка — повторных передач и блокировок нет.
- Если клиент отстал слишком сильно, сервер отправляет полный снимок и цикл начинается заново — это же спасает при переподключении.
Интерполяция и экстраполяция
- •Клиент рендерит чужих игроков в прошлом: он буферизует два-три снимка и плавно интерполирует между ними. В движке Source это окно по умолчанию равно 100 мс.
- •Если очередной снимок не пришёл, клиент экстраполирует движение по последней скорости (dead reckoning) — короткая потеря пакета остаётся незаметной.
- •Долгая экстраполяция опасна: предсказанная траектория расходится с реальной, и персонажей начинает «телепортировать» при следующем снимке.
Тикрейт: бюджет кадра против стоимости
| Тикрейт | Бюджет кадра | Где встречается | Цена |
|---|---|---|---|
| 20-30 Hz | 33-50 мс | Battle royale и большие миры с 100+ игроками | Дешёвые серверы, но заметнее задержка регистрации попаданий |
| 60-64 Hz | ~16 мс | Overwatch (16 мс на командный кадр), CS2 | Баланс отзывчивости и стоимости для матчей 10-12 игроков |
| 128 Hz | 7.8 мс | Valorant, киберспортивные конфигурации | Жёсткая оптимизация: Riot уложила кадр сервера в ~2.6 мс, чтобы плотнее упаковать матчи на ядро |
Компромисс прозрачный: удвоение тикрейта почти удваивает CPU-стоимость каждого матча и трафик, но уменьшает интервал между подтверждениями и делает более гранулярной. Поэтому тикрейт выбирают от жанра: тактическому шутеру нужны 64-128 тиков, а кооперативной игре на 4 человека хватает 20-30.
Interest management: кому какую часть мира слать
Дельта-компрессия сокращает размер пакета, но не количество получателей. Если каждый из 100 игроков должен знать о каждом, сервер рассылает порядка 100 × 99 обновлений на тик — при 30 тиках это сотни тысяч записей в секунду, классическая проблема . Interest management решает её: каждый клиент подписан только на ту часть мира, которая ему действительно видна и важна.
Механика area of interest
- •Мир режется на ячейки — на равномерной сетке или quadtree, если плотность игроков сильно неравномерна.
- •Клиент подписан на свою ячейку и соседние; при движении подписки переезжают, а гистерезис на границе ячеек гасит дребезг подписаться-отписаться.
- •В снимок клиента попадают только сущности из его зоны интереса: вместо 99 игроков — ближайшие 10-20, и стоимость рассылки растёт почти линейно, а не квадратично.
- •Quake 3 делал то же самое через потенциально видимое множество (potentially visible set): сервер хранил историю снимков по каждому клиенту и сериализовал только видимое ему подмножество состояния.
Компромиссы и побочные эффекты
- •Слишком мелкие ячейки — высокий churn подписок при движении; слишком крупные — лишний трафик. Размер подбирают от скорости перемещения и дальности обзора.
- •Снайперские прицелы, миникарты и звуки выстрелов ломают простую геометрию зоны: для них нужны отдельные правила интереса с другим радиусом.
- •Бонус для честности: если позиции врагов за стеной вообще не приходят на клиент, wallhack-читам нечего показывать. Фильтрация по видимости — это и оптимизация, и защита.
Компенсация задержки: перемотка мира при проверке попаданий
Valve
Source Multiplayer Networking
Каноническое описание интерполяции, предсказания и компенсации задержки в движке Source.
Из-за интерполяции стрелок целится не в актуальное состояние мира, а в картинку из прошлого: интерполяционное окно плюс сетевой путь до сервера легко дают 100-150 мс отставания. Если сервер проверит попадание по текущим позициям, идеально наведённые выстрелы будут «проходить сквозь» цель. Поэтому соревновательные шутеры применяют компенсацию задержки по принципу favor the shooter — «правда на стороне стрелка».
Механизм перемотки
- Сервер хранит кольцевой буфер позиций и хитбоксов всех игроков за последнюю секунду.
- Получив выстрел, сервер вычисляет момент, который видел стрелок: текущее время минус сетевая задержка пакета минус интерполяционное окно клиента — формула из движка Source.
- Хитбоксы целей перематываются в это прошлое, и попадание проверяется там.
- После проверки мир возвращается в актуальное состояние, урон применяется уже в нём.
Цена favor the shooter
- •Жертва иногда получает урон уже «за укрытием»: с её точки зрения она спряталась, но в перемотанном прошлом стрелка ещё была видна.
- •Окно перемотки ограничивают сотнями миллисекунд: игрок с огромным пингом не должен стрелять в слишком далёкое прошлое, иначе компенсация превращается в эксплойт с искусственной задержкой.
- •Альтернатива favor the victim (не компенсировать) честнее для жертвы, но требует от стрелка упреждения на величину пинга — для массового продукта это хуже.
Компенсация работает только при авторитетном сервере: клиент сообщает «я выстрелил в такой-то момент», но решение о попадании, уроне и боезапасе принимает сервер, сверяя скорострельность, патроны и физическую достижимость позиции. Любая проверка, отданная клиенту, рано или поздно становится читом — от aimbot до телепортов через speedhack.
Матчмейкинг и жизненный цикл игрового сервера
Источник
Agones
Открытая платформа Google Cloud и Ubisoft для размещения и масштабирования игровых серверов поверх Kubernetes.
Подбор матча и выделение сервера — это конвейер с собственными компромиссами: чем дольше игрок ждёт, тем шире система готова трактовать «подходящий» матч и по рейтингу, и по задержке.
Путь от кнопки «Играть» до первого тика
- Клиент измеряет до региональных точек присутствия и прикладывает результаты к заявке вместе с рейтингом и режимом.
- Заявка попадает в очередь матчмейкера; допустимые окна по рейтингу и задержке расширяются по мере ожидания — это и есть управляемый компромисс между качеством матча и временем в очереди.
- Для собранной группы выбирается регион с приемлемым для большинства и запрашивается сервер из тёплого пула — аллокация занимает секунды, потому что процессы уже подняты.
- Игроки получают адрес сервера и одноразовый токен сессии; сервер сверяет токены, дожидается подключений и запускает матч.
- После матча сервер сбрасывает результаты в персистентный контур — рейтинги, статистику, экономику — и либо возвращается в пул, либо завершается, освобождая место новому.
Управление парком серверов
игровых серверов — отдельный класс инфраструктуры со своими готовыми решениями.
- •Agones — открытый проект Google Cloud и Ubisoft: ресурсы GameServer и поверх , защита подов с активными игроками от вытеснения и проверка работоспособности через лёгкий SDK.
- •Amazon GameLift — управляемый аналог: размещение по регионам, очереди аллокаций и FleetIQ для экономии на спотовых инстансах.
- •В обоих случаях ключевое отличие от веб-нагрузки: сервер с живым матчем нельзя убить при сокращении парка — он хранит состояние матча до последнего игрока.
Масштабирование под пики
парка работает не так, как у обычных веб-сервисов.
- •Метрика масштабирования — не CPU, а буфер готовых серверов: «держать N свободных процессов в каждом регионе» с прогнозом по времени суток и анонсам событий.
- •Скейлинг вниз — дренаж: узел перестаёт получать новые матчи и ждёт окончания текущих, поэтому сокращение парка занимает десятки минут.
- •Регулярный от игрового процесса отделяет зависшие серверы от занятых: молчащий процесс с матчем — это инцидент, а не кандидат на тихую замену.
Транспорт: протокол UDP, надёжностные каналы и браузерные игры
гарантирует порядок и доставку, но платит за это блокировкой очереди: потерянный пакет задерживает все последующие, пока не приедет ретрансмит, и клиент получает пачку устаревших состояний разом. Для игрового состояния свежесть важнее полноты, поэтому основной трафик идёт по , а гарантии собираются выборочно на уровне приложения.
Каналы с разными гарантиями
- •Unreliable sequenced — снимки состояния: новый пакет обесценивает старый, поэтому терпима, а устаревшие просто отбрасываются по номеру.
- •Reliable ordered — события, которые нельзя потерять: покупка предмета, начало раунда, сообщение чата. Поверх это порядковые номера, поле подтверждений и ретрансмиты только для этого канала.
- •Раздельные каналы не дают надёжному трафику блокировать быстрый: даже при снимки продолжают приходить без очереди.
Браузер: WebRTC и WebTransport
- •Браузеру сырой недоступен, поэтому браузерные игры используют WebRTC DataChannel: SCTP поверх DTLS, где режим ordered: false с maxRetransmits: 0 ведёт себя как с шифрованием. Сервер при этом выступает обычным WebRTC-пиром.
- •WebTransport поверх — более простая клиент-серверная альтернатива: ненадёжные датаграммы и потоки без взаимной блокировки, без церемоний ICE-сигналинга.
- •Прохождение для клиент-серверной модели тривиально — клиент всегда инициирует соединение; STUN и TURN нужны в основном P2P-режимам и voice-чату.
Выбор транспорта по типу трафика
| Транспорт | Гарантии | Где уместен |
|---|---|---|
| + свой надёжностный слой ✓ | Настраиваются по каналам | Игровое состояние нативных клиентов: снимки, вводы, выстрелы |
| TCP / | Надёжно, упорядоченно | Лобби, матчмейкинг, чат, магазин — всё вне игрового тика |
| WebRTC DataChannel | Настраиваемые: от -подобных до надёжных | Браузерные клиенты против выделенного сервера-пира |
| WebTransport / QUIC | Датаграммы и потоки без взаимной блокировки | Современная замена обоим браузерным вариантам по мере поддержки |
Практическое правило: по быстрому пути — только то, что обесценивается за один тик; всё остальное выносится на обычный надёжный канал. Так потеря пакетов деградирует картинку, но никогда не ломает целостность матча.
Надёжность и типичные ошибки
В продакшене для матча, защиту от перегрузки через и путь восстановления после обрыва связи закладывают заранее — иначе первый же сбой узла или всплеск нагрузки рвёт матч вместо того, чтобы деградировать его мягко.
Надёжные решения
- Региональное размещение матчей: игроков стараются сводить в пределах допустимой задержки.
- Липкая сессия для трафика игровых и постоянных соединений в рамках активного матча.
- Резервные игровые серверы и быстрый перенос матча при отказе узла.
- Снимки состояния и дельта-обновления для экономии полосы пропускания и быстрого досинхрона.
- Ограничение очередей на входе, чтобы перегрузка не ломала цикл симуляции.
Частые ошибки
- P2P-модель с клиентом как источником истины в соревновательных режимах.
- Глобальный подбор матча без региональной сегментации по задержке.
- Синхронные вызовы к БД или внешним сервисам внутри игрового тика.
- Отсутствие окна повторного подключения и механизмов досинхронизации состояния.
- Полная рассылка состояния вместо компактных дельта-пакетов.
Что хранить постоянно
- Профиль игрока и его прогресс.
- Историю матчей и ключевые телеметрические счётчики.
- Снимки MMR, результаты ранжирования и агрегаты таблиц лидеров.
- События инвентаря и игровой экономики, если в продукте есть монетизация.
- Аудиторский след для модерации и расследования читов.
На интервью важно проговорить между отзывчивостью, которую даёт , и честностью матча, которую сервер возвращает через .
Если бюджет задержек превышен, лучше ослабить ограничения подбора по региону или рейтингу, чем превращать матч в набор лагов.
Связанные главы
- UDP - разбирает транспорт, который чаще всего используют для критичного игрового трафика с минимальной задержкой.
- WebSocket - дополняет тему постоянным каналом для лобби, уведомлений и части сессионных событий.
- Chat System - даёт смежный кейс по коммуникациям в реальном времени, онлайн-статусу и масштабированию долгоживущих соединений.
- Rate Limiter - полезен для защиты игровых API от всплесков нагрузки, злоупотреблений и нечестного поведения клиентов.
- Content Delivery Network (CDN) - объясняет, как ускорять доставку ассетов и патчей и уменьшать задержку для игроков из разных регионов.
