Вернуться к статьям

Архитектура мультиплеерного сервера: authoritative vs peer‑to‑peer

14 мая 2026
11 мин чтения
AI-research draft
Архитектура мультиплеерного сервера: authoritative vs peer‑to‑peer

Как выбрать между authoritative и P2P для вашей игры: архитектуры, сетевые модели, античит, стоимость и подводные камни продакшена. Практический разбор от команды, которая это строит.

Ошибиться с сетевой архитектурой — значит переписать половину игры за 3 месяца до релиза и потерять маркетинговое окно. Эта статья нужна сейчас, потому что в 2026‑м большинство игровых жанров ожидаемо онлайн, а риск «не угадать» с мультиплеером дороже, чем когда‑либо.

Если коротко: authoritative (сервер — источник истины) выбирают для соревновательных и фритуплей проектов с экономикой и античитом. P2P (игроки синхронизируются между собой) — для коопов «на друзей», ретро/инди с фиксированной физикой и минимальным бюджетом. Дальше — конкретные архитектуры, сетевые модели, стоимость владения и то, что ломается в продакшене.

Когда какой подход разумнее

  • Если в игре есть матчмейкинг, ранки, экономика, косметика, сезонные события, внутриигровой магазин — authoritative. Античит и целостность данных важнее, чем экономия на серверах.
  • Если это кооператив до 4–8 игроков без экономики, локальные или «друзья по Стиму», физика детерминирована — P2P реальный кандидат. Особенно при желании нулевой серверной стоимости.
  • Гибриды возможны: P2P для симуляции боя + облачный релей/сервис аутентификации/статистики; или authoritative‑ядро + клиентская интерполяция и «щедрая» предсказательная логика.

Один прагматичный фильтр: если вы планируете банить читеров — это почти автоматический выбор authoritative. Если вас устраивает «домашний кооп» и вы готовы жить с редкими десинками — рассмотрите P2P.

Архитектурные паттерны

Authoritative: сервер решает все важное

Компоненты:

  • Matchmaker (PlayFab, Epic Online Services, custom на Go/Node/Rust).
  • Game server (stateful процесс): симулирует мир с фиксированным тикрейтом (30–60 тиков/с), принимает inputs от клиентов, рассылает state deltas.
  • Persistence (Postgres/MySQL) для профилей, инвентаря, матч‑результатов.
  • Gateway/Relay: UDP‑прокси, WebSocket/QUIC шлюзы (Cloudflare Spectrum, Agones + Kubernetes NodePort/Direct Server Return).
  • Античит: на стороне клиента (Easy Anti‑Cheat/BattleEye) + серверные валидации.

Поток:

  1. Клиент подключается к lobby/matchmaker, получает адрес сервера матча и токен.
  2. Устанавливается сессия (UDP/QUIC/WebSocket). Клиент шлет инкрементально нумерованные input‑пакеты.
  3. Сервер применяет входы к состоянию, симулирует, отправляет снапшоты/дельты + ack последнего обработанного инпута.
  4. Клиент делает предсказание (client‑side prediction) и ре-консилиацию по ack.

Плюсы: честность игры, гибкая телеметрия, контроль метаэкономики. Минусы: стоимость инфраструктуры, DevOps, DDoS‑поверхность.

Инструменты: Nakama (Go, authoritative расширения на Lua/Go), Photon Server/Quantum (C#), Colyseus (Node.js), custom на Rust/Go/C++, контейнеризация (Kubernetes + Agones), фронт Cloudflare/ENet/QUIC.

P2P: игроки симулируют мир сами

Варианты:

  • Lockstep (детерминированная симуляция, RTS‑классика): каждый кадр — набор команд, переход к следующему кадру только когда все получили команды текущего.
  • Rollback (GGPO‑подход для файтингов/экшенов): клиенты «угадывают» входы, при опоздании — откатывают состояние на n кадров и пересчитывают.

Сетевое:

  • STUN/TURN для NAT‑траверсала (WebRTC DataChannels или собственный UDP/ENet).
  • Релейный сервер для случаев строгих NAT (вы всё равно платите немного за трафик).
  • Хост‑пир как «квазисервер»: один из игроков объявляется авторитетом по некоторым подсистемам (спавн, лут), но без центрального дата‑хранилища.

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

Сетевые модели и синхронизация

Клиентское предсказание и согласование с сервером

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

Пример (Unity/C#):

public class PlayerNetworkController : MonoBehaviour {
    struct InputCmd { public int seq; public Vector2 move; public float ts; }
    struct State { public Vector3 pos; public Vector3 vel; public int ackSeq; }

    Queue<InputCmd> pending = new Queue<InputCmd>();
    int nextSeq = 1;
    Rigidbody rb;

    void Start() { rb = GetComponent<Rigidbody>(); }

    void Update() {
        var input = new InputCmd {
            seq = nextSeq++,
            move = new Vector2(Input.GetAxis("Horizontal"), Input.GetAxis("Vertical")),
            ts = Time.time
        };
        SendToServer(input); // UDP/QUIC/WebSocket
        pending.Enqueue(input);
        ApplyInputLocal(input); // prediction
    }

    void OnServerSnapshot(State s) {
        // жестко ставим авторитетное состояние
        rb.position = s.pos; rb.velocity = s.vel;
        // выбрасываем подтвержденные инпуты
        while (pending.Count > 0 && pending.Peek().seq <= s.ackSeq) pending.Dequeue();
        // переигрываем оставшиеся, чтобы выровнять предсказание
        foreach (var cmd in pending) ApplyInputLocal(cmd);
    }

    void ApplyInputLocal(InputCmd cmd) {
        var dir = new Vector3(cmd.move.x, 0, cmd.move.y).normalized;
        rb.AddForce(dir * 10f, ForceMode.Acceleration);
    }
}

На сервере — симуляция с фиксированным tickRate и буфер входов по seq. Клиент в идеале хранит 100–200 мс необработанных инпутов. Лирическое отступление: если хочется простоты — сделайте однопользовательскую игру; сеть добавит еще одну ось сложности.

Lockstep и детерминизм

Lockstep требует бит‑в‑бит одинаковой симуляции. Практически:

  • Фиксированная точность чисел (int/fixed‑point вместо float где возможно).
  • Фиксированный порядок итерации по коллекциям (не полагайтесь на HashMap/Dictionary порядок).
  • Одинаковое время кадра (fixed delta, не привязывать логику к Time.deltaTime).
  • Синхронизация случайности (общие seed’ы RNG).

Rollback и «перемотка» времени

Rollback держит историю N последних тиков (например, 8–12), хранит состояние (или детерминированные входы) и при приходе позднего ввода пересчитывает состояние. Важно:

  • Быстрая сериализация состояния (битовые буферы, Arena‑аллокаторы, ECS без боковых эффектов).
  • Timewarp для анимаций/частиц (визуал отдельно от логики).
  • Бюджет CPU/GPU на пересчет (особенно на консолях/мобайле).

Сравнение authoritative vs P2P

КритерийAuthoritativeP2P
ЧитероустойчивостьВысокая: сервер валидирует и симулируетНизкая/средняя: валидировать сложно
Стоимость инфраструктурыСредняя/высокая: сервера матчей, DevOpsНизкая: STUN/релей по необходимости
Задержка восприятияСкрывается предсказанием/интерполяциейМожет быть ниже локально, но десинки
Сложность реализацииВысокая: симуляция, согласование, античитВысокая: детерминизм, rollback/lockstep
Масштабируемость по CCUОтличная при оркестрации (K8s/Agones)Ограничена релеями/NAT и жанром
Размер сессии10–200+ (шардинг)Обычно 2–8, реже 16
Сохранность экономикиГарантируется на сервереРиск дублирования/эксплойтов
ОтладкаЦентральные логи/трейсыРаспределенная, сложнее воспроизводить

Масштабирование и эксплуатация

Тик‑бюджет и CPU

  • 60 тиков/с — 16.67 мс на тик, включая сетевой I/O, логику, сериализацию. На 30 тиков — 33.3 мс, запас выше, но увеличивается видимая задержка и требования к интерполяции.
  • Выделяйте бюджет на кодек: дельты по компонентам, bit‑packing, компрессия (LZ4/S2). Для мобильной сети это критично.

Оркестрация и автоскейл

  • Kubernetes + Agones для пулов игровых серверов, pre‑warm нод под прайм‑тайм.
  • Подбор региона: latency‑aware матчмейкинг. Near‑edge релеинг (Cloudflare Spectrum/Workers) для «лестницы» NAT.
  • Кеши/метаданные: Redis для матчей/серверного discovery, Postgres для долговременных профилей.

Сетевые протоколы

  • UDP + собственная надстройка (reliability, ordering) — классика. ENet — зрелая библиотека.
  • QUIC (HTTP/3) — альтернатива: встроенная надёжность/шифрование, лучше сквозь NAT/фаерволы, но добавляет накладные расходы.
  • WebRTC DataChannels — must для браузера; получаете STUN/TURN «из коробки».

Телеметрия

  • Пер‑тик метрики: «сколько инпутов потеряно», jitter, RTT, размер пакета. Старайтесь не писать «всё в Grafana» без агрегации — храните агрегаты по матчам/региону.
  • Реплеи как диагностический артефакт: на authoritative — лог входов/снапшотов; на P2P — входы + seed’ы.

Что ломается в продакшене

  • Детерминизм на разных платформах: ARM vs x86, разная реализация FPU, компиляторные оптимизации. Лечится фиксированной арифметикой и тест‑фермой «скрещенных» клиентов.
  • NAT hairpin и симметричные NAT: P2P ломается без релея. Заложите TURN/relay бюджет и health‑чек на деградацию до релея.
  • Спайки GC/аллокации: C# на сервере без пулов структур быстро ловит паузы. Используйте арену, Span/ArrayPool, ECS без боковых эффектов.
  • Дублирование пакетов и reorder: ваш протокол обязан иметь seq/ack/bitmask и адаптивный resend. Не надеяться на «повезёт».
  • Время: рассинхронизация часов устройства. Не используйте DateTime.Now для логики — только серверный тик/монотонные таймеры.
  • DDoS/abuse: UDP amplification, SYN‑флуды на гейтвей. Ставьте rate limiting на уровне edge, обрезайте «подозрительные» IP‑диапазоны, следите за уязвимостями прокси (см. наш разбор новой уязвимости Nginx).
  • Версионирование протокола: выкатили патч — половина клиентов старые. Придётся держать 2–3 версии сериализации и миграцию состояния при реконнекте.
  • Читеры: aimbot, speedhack, packet injection. Сервер валидирует скорость/ускорение, «вес» коллизий и частоту выстрелов; подозрительные паттерны — в карантин.

Деньги и сроки: сколько стоит и зачем оно вам

Сильные хотелки обычно разбиваются о бюджет. Ориентиры по рынку и опыту студий:

  • Прототип P2P коопа (2–4 игрока, WebRTC/UDP, без экономики): 4–8 недель, бюджет от $20–40k. Основной риск — детерминизм/rollback.
  • Минимальный authoritative для сессионного шутера (до 16 игроков, матчмейкинг, базовая прогрессия): 3–5 месяцев, от $80–200k. Риск — инфраструктура/античит.
  • МMO‑подсистемы (persistent мир, шардинг, инвентарь, торговля): 6+ месяцев, бюджеты считаются индивидуально.

OPEX:

  • Authoritative: при 60 тиках/с и 10–16 игроках в матче типичный серверный процесс укладывается в 0.2–0.6 vCPU и 200–500 МБ RAM. С учётом стоек/релеев/матчмейкера — ориентируйтесь на ~$0.02–0.08 за час матча по инфраструктуре в облаке при средней утилизации. Релеинг через TURN/edge увеличит трафиковую строку.
  • P2P: почти ноль без релеев; с TURN — платите за egress/GB и несколько центов за сессию. Экономия часто «съедается» сложностью QA.

Скрытые затраты:

  • QA‑матрица платформ/сетей (Wi‑Fi/4G/5G, строгий NAT, консоли). Автоматизация сетевых тестов окупается.
  • Туллинг: интеграция реплеев, профайлеров, симуляция packet loss/jitter в CI.
  • Аналитика: корреляция лагов и оттока игроков — даёт прямой эффект на удержание и монетизацию.

ROI‑логика:

  • Компетитив с монетизацией и сезонностью — платит за authoritative десятикратно через LTV и борьбу с читами.
  • Небольшой кооп без экономики — P2P позволит раньше выйти и проверить фитовость геймплея.

Практические решения по жанрам

  • Шутер/файтинг/спортивные: authoritative с агрессивной клиентской предикцией, серверной валидацией хитсканов, lag compensation (rewind по input time, храните 100–200 мс истории позиций для трассировки пуль).
  • RTS/город‑билдер: P2P lockstep или гибрид; симуляция детерминированна, сетевые пакеты — команды, не состояния.
  • Платформер/ретро‑экшен 1v1: rollback (GGPO‑подобная модель), иногда с релеем.
  • Sandbox/физика: authoritative симуляция тяжелых взаимодействий, на клиенте — «мягкие» эффекты, которые можно корректировать без боли.

Минимальный каркас authoritative‑сервера (UDP)

// Node.js + dgram (демо-скелет), в продакшене используйте ENet/QUIC и неблокирующие структуры
import dgram from 'dgram';

const TICK = 33; // 30 тиков/с
let state = new Map(); // playerId -> {x,y,vx,vy,ack}
let inputs: Array<{id:string, seq:number, dx:number, dy:number}> = [];

const srv = dgram.createSocket('udp4');

srv.on('message', (msg, rinfo) => {
  // parse: id|seq|dx|dy
  const [id, s, dx, dy] = msg.toString().split('|');
  inputs.push({ id, seq: Number(s), dx: Number(dx), dy: Number(dy) });
  // сохраняем адрес пира для обратной отправки (упрощенно)
  (state.get(id) || (state.set(id, { x:0, y:0, vx:0, vy:0, ack:0 }), state.get(id))).addr = rinfo;
});

setInterval(() => {
  // применяем входы
  const byPlayer = new Map<string, Array<any>>();
  for (const inp of inputs) {
    if (!byPlayer.has(inp.id)) byPlayer.set(inp.id, []);
    byPlayer.get(inp.id)!.push(inp);
  }
  inputs = [];

  for (const [id, arr] of byPlayer) {
    const s = state.get(id) || { x:0, y:0, vx:0, vy:0, ack:0 };
    arr.sort((a,b)=>a.seq-b.seq);
    for (const a of arr) {
      s.vx = a.dx * 5; s.vy = a.dy * 5; // простая физика
      s.x += s.vx * (TICK/1000); s.y += s.vy * (TICK/1000);
      s.ack = a.seq;
    }
    state.set(id, s);
  }

  // шлем снапшоты (упрощенно — каждому свой ack и весь список игроков)
  const snapshot = JSON.stringify([...state.entries()].map(([id, s]) => ({ id, x:s.x, y:s.y })));
  for (const [id, s] of state) {
    const payload = JSON.stringify({ you:id, ack:s.ack, snapshot });
    const addr = (s as any).addr; if (!addr) continue;
    srv.send(payload, addr.port, addr.address);
  }
}, TICK);

srv.bind(27015);

Это не продакшен, но показывает сердцевину: буфер входов, симуляция по тикам, рассылка снапшотов с ack.

Выбор сериализации и протокола данных

  • JSON удобен, но громоздок. Для продакшена — FlatBuffers, Protobuf, custom bit‑packing.
  • Схема версионируется: version в каждом пакете, fallback‑логика.
  • Передача позиций — дельты + квантование (например, 1/100 юнита, чтобы упаковать в 16 бит).

Безопасность и честность

  • Токены доступа краткоживущие (JWT с audience=matchId). Сервер проверяет iat/exp и подпись (HMAC/EdDSA).
  • Нормализация скоростей: ограничивайте максимальные векторы, отфильтровывайте «телепорты» без причины.
  • Сетевая изоляция: игровые воркеры без доступа в интернет, только через гейтвей.
  • Ротация ключей шифрования и античит‑хэндшейк на старте матча.

Организация разработки

  • Net‑sim в CI: запуск headless сервера + 4 клиентов с эмуляцией задержки/потерь (tc netem), проверка средних метрик и десинков.
  • Рекордер команд/состояний и кнопка «реплей матча» для QA.
  • Фичи под флагами/канарейками: выкатывайте новый формат снапшотов 5% игроков в регионе.

FAQ

Можно ли сделать гибрид: P2P геймплей и серверная экономика?

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

Для браузера лучше WebRTC или WebSocket?

Для реального‑тайма — WebRTC DataChannels: UDP‑семантика, низкая задержка, встроенные STUN/TURN. WebSocket — TCP, больше head‑of‑line блокировок; годится для лобби/экономики, хуже для тиков.

Есть ли смысл в QUIC для настольных игр?

Есть. QUIC лучше проходит сквозь NAT/фаерволы, имеет TLS по умолчанию. Но отдаёт управление над reliability протоколу — если нужна тонкая настройка частично‑надёжных каналов, ENet/UDP иногда удобнее.

Какой тикрейт выбирать?

30 тиков/с — хороший базовый компромисс. 60 — если геймплей быстрый (шутеры/файтинги) и вы уложились в производительность/трафик. Всегда тестируйте с реальными сетями и девайсами.

Как бороться с десинком в P2P?

Строгий детерминизм (fixed‑point), общий RNG, запись входов и периодические контрольные хеши состояния между пирами. При расхождении — мягкий ресинк или переключение на релей/хоста.

Что выбрать для коопа на 4 человека на мобилках?

Если нет экономики — P2P через WebRTC/UDP с обязательным релеем на крайний случай. Если планируете соревновательные элементы/рейтинги — сразу authoritative с UDP/QUIC и строгой валидацией.

Ключевые выводы

  • Authoritative нужен там, где важны честность, экономика и масштаб; P2P оправдан при малом бюджете и детерминированной симуляции.
  • Реальный‑тайм держится на предсказании, интерполяции и аккуратной сериализации; без этого видна вся сетка.
  • Детерминизм — главный риск P2P; античит и инфраструктура — главный риск authoritative.
  • Тик‑бюджет, оркестрация и телеметрия — операционный фундамент, без них проект не скейлится.
  • Закладывайте релей/edge‑защиту: NAT и DDoS сломают идеальную схему в первый же уикенд.

Если вы строите мультиплеерный шутер, кооп или гибридную архитектуру — мы в MTBYTE проектируем, пишем и запускаем такие серверы под Steam, мобильные, браузер и консолы. Напишите нам через /contact — обсудим требования и риски до кода.