Иногда инфраструктура перестает справляться ещё до того, как игра выходит к первым пользователям. Так произошло с The Firstborn — многопользовательской мобильной deck-builder RPG. В этой игре исход боя определяется не нажатием кнопок, а тем, как игрок собирает колоду, комбинирует расовые и классовые способности, прокачивает героев и строит долгосрочную стратегию. В игре десять рас, три класса, пять альянсов и несколько сотен уникальных активных и пассивных эффектов. Бой 6×6 может развернуться тысячами разных способов.

Игра The Firstborn
Игра The Firstborn

Но сама боевая система — только часть проекта. The Firstborn строится вокруг социального взаимодействия между игроками. В игре есть система контрактов, в которой пользователи соревнуются за ценные награды; кланы с общей прокачкой; свободный рынок, где игроки торгуют предметами друг с другом; крафты со скрытыми рецептами; охота на мировых боссов, где десятки людей одновременно сражаются с одним противником. Это создаёт формат живой MMO-экономики, что добавляет нагрузки на серверную часть.

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

Проблема

Изначально проект работал на обычной виртуальной машине Selectel с четырьмя vCPU, восемью гигабайтами RAM и HDD. Этого хватало только на самые лёгкие внутренние тесты. При попытках провести нагрузочные испытания сервер начинал работать нестабильно и иногда просто падал. Это делало разработку и проверку новых функций невозможными.

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

Почему нельзя было просто выбрать сервера в разных странах

Вся игровая экономика The Firstborn, включая кланы, рынок, контракты и мировых боссов, опирается на единую централизованную базу данных. Геораспределенная структура в данном случае невозможна: она привела бы к конфликтам транзакций, рассинхронизации состояния игры и некорректной работе всей боевой системы. Однако это не означает, что игра работает на одном сервере. Централизована только база. Сам backend распределён, работает под балансировщиком, использует микросервисную архитектуру, CDN для ассетов и может масштабироваться горизонтально — добавлением новых рабочих нод рядом с основной инфраструктурой.

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

Как нашли оптимальное решение

Мы протестировали десятки серверов через CloudSell и проверили их в реальных условиях. Измеряли задержки из разных стран, пропускную способность диска, устойчивость под нагрузкой и стоимость владения. В итоге лучшей точкой неожиданно стал Хельсинки. Через Финляндию проходят крупные международные каналы, и она оказалась оптимальной для связности сразу с несколькими регионами. Пинг из Европы и Азии оказался стабильным, а из России — в районе 40–50 миллисекунд. Этого более чем достаточно для deck-builder проекта, где основная нагрузка лежит на серверном просчёте боевой логики.

Мы отказались от виртуалки и развернули выделенный сервер в Hetzner на базе Intel Core i9-9900K с 128 ГБ памяти и NVMe-диском на 1 ТБ. Стоимость аналогичного сервера в Selectel почти в четыре раза выше, при том что он предлагает только половину объёма ОЗУ.

Переход на NVMe дал огромный прирост к скорости работы базы данных и контейнеров. CI/CD теперь работает автоматически, а деплой выполняется значительно быстрее. Новая инфраструктура стабильно выдерживает нагрузку до пятисот запросов в секунду на самую тяжёлую игровую операцию — запуск боя. Мы смогли проводить полноценные нагрузочные тесты даже до появления живых игроков, чего прежний сервер попросту не позволял.

Время просчёта боя сократилось с двух с половиной секунд до одной. Это заметно улучшило отклик игры: игрок практически сразу получает результат своего выбора колоды и стратегии. Производительность диска выросла на порядок, деплой стал быстрее, а стоимость инфраструктуры снизилась в четыре–пять раз по сравнению с размещением аналогичного оборудования в России. Пинг по миру стабилизировался, а основные сервисы начали работать предсказуемо и без резких скачков нагрузки.

Опыт показал, что для MMO-экономики и сложной deck-builder системы не всегда нужен дорогой распределённый кластер. Достаточно правильно выбрать точку размещения базы данных и построить вокруг неё горизонтально масштабируемый backend. В нашем случае это позволило не только ускорить серверную часть в два с половиной раза, но и сократить расходы на инфраструктуру в несколько раз. CloudSell значительно упростил процесс подбора и тестирования серверов, что сэкономило команде недели работы и позволило сосредоточиться на разработке игры.

Комментарии (15)


  1. kolya7k
    14.12.2025 09:12

    У вас явно какая-то проблема с алгоритмами. В описанных вами задачах такой сервер как вы выбрали должен был считать бой за 0.01 секунду и меньше, а не за 1.

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

    500 запросов в секунду на бой с временем ответа в 1 секунду… У вас там либо 500 ядер на сервер либо просчет боя сделан максимально криво либо вы что-то напутали или наврали в тексте :)


    1. tarasov_cloudsell Автор
      14.12.2025 09:12

      Тут, кажется, просто возникло недопонимание. Сам просчёт боя действительно занимает доли секунды. Около секунды это end-to-end время: чтение состояния из БД, формирование довольно большого JSON-лога боя и отправка его клиенту, по которому рисуется анимация.

      500 RPS это не 500 потоков, висящих по секунде, а реальная нагрузка, которую сервер держит при асинхронной обработке. Про «500 ядер» речи, конечно, не идёт.

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


      1. kolya7k
        14.12.2025 09:12

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

        «Чтение состояние из БД» - не должно быть на каждый бой. У вас 128GB RAM, сделайте нормальное кэширование без вытеснения.

        Формирование JSON тоже не должно быть долгим, не знаю на чем написан сервер у вас, если на C++, то рекомендую rapidjson, хотя есть и быстрее. Хотя, зачем вы вообще отправляете серверу большой лог в JSON? К вашему архитектору всё больше вопросов. Ладно protobuf, но можно и свой протокол обмена данными создать. Бинарный и эффективный.

        Я игровыми серверами занимаюсь уже больше 10 лет, какие только не делал и для шутеров с UDP и для пошаговых игр и для онлайн игр с комнатами и весь мой опыт говорит о том, что у вас что-то не так. Подозреваю, что микросервисная архитектура у вас применяется для галочки, без понимания какие проблемы она решает и как она работает, поэтому и вылезла, например, загрузка чего-то при каждой битве.

        Как вы собираетесь это всё масштабировать дальше? 1 бой - 1 секунда что бы там внутри не было сейчас. 32 ядра - 32rps по боям. 10000 онлайна которые вы прогнозируете даст, ну пусть 1/10 боёв в секунду. Это 1000rps, вам нужно 30 серверов чтобы тянуть только бои…

        Я бы не стал сейчас заморачиваться с микросервисами, вам монолита боёвка + кэширование данных игроков хватить на онлайн до 10k спокойно на текущем железе (если сделать все правильно).

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

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


        1. tarasov_cloudsell Автор
          14.12.2025 09:12

          Многие сейчас их используют просто потому что это модно :)

          Еще моднее кидаться камнями во всех, кто упомянет слово "микросервис"?))

          Важно уточнить: у нас нет сотни микросервисов. Сейчас это монолитный backend под балансировщиком, с отдельным auth-сервисом и набором инфраструктурных сервисов (PostgreSQL/Redis/S3/monitoring/WebGL). Мы сознательно не дробим игровую логику на десятки сервисов на ранней стадии, но архитектурно оставляем возможность выносить отдельные домены (бой/экономика/контракты) отдельно, если нагрузка это потребует.

          «Чтение состояние из БД» - не должно быть на каждый бой. У вас 128GB RAM, сделайте нормальное кэширование без вытеснения.

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

          Хотя, зачем вы вообще отправляете серверу большой лог в JSON? 

          Я боюсь, вы не до конца понимаете контекст. При нажатии на кнопку "Напасть", отправляется запрос с текущей колодой, на сервере просчитывается весь бой (10 раундов) и формируется JSON со всеми действиями (батл лог), который возвращается в ответе на этот же запрос на клиент, и уже по этому ответу отрисовывается анимация. Все это, включая ожидание ответа от сервера, занимает сейчас менее секунды.

          Ладно protobuf, но можно и свой протокол обмена данными создать. Бинарный и эффективный.

          Можно и движок свой с 0 написать)) Но кто это все дело поддерживать будет?
          У нас используется стандартно HTTP + gzip/br, этого вполне достаточно для такой игры.

          1 бой - 1 секунда что бы там внутри не было сейчас. 32 ядра - 32rps по боям. 10000 онлайна которые вы прогнозируете даст, ну пусть 1/10 боёв в секунду. Это 1000rps, вам нужно 30 серверов чтобы тянуть только бои…

          Сейчас 500 боев = 1 секунда, на 16 ядрах, и это мы еще в оптимизацию не погружались, там потенциал на много больше.

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

          Я в статье объяснил почему нам не подходит шардинг, и почему все должны играть на "одном сервере". Это бизнес требование.

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

          Очень надеюсь, что речь не про сервера по Countre Strike и Minecraft, мы тут все таки свою игру делаем, и работа с сервером и протоколами это лишь верхушка айсберга.

          Но спасибо за Ваши советы и рекомендации, обязательно примем к сведению.


  1. MANAB
    14.12.2025 09:12

    По факту узкое место было в БД на HDD. Слишком много самопиара и мало технической инфы для статьи о серверной оптимизации.


    1. tarasov_cloudsell Автор
      14.12.2025 09:12

      Да, узкое место было в БД на HDD, с этим никто не спорит. Именно поэтому переход на NVMe и дал такой эффект.

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


  1. iamkisly
    14.12.2025 09:12

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

    Меня смущает то что это карточная игра.. это не тот жанр который требует больших ресурсов. Что такое вы там испытывали и проверяли? Я java сервера lineage2 запускал в локалке на куда меньшей конфигурации.

    Изначально проект работал на обычной виртуальной машине Selectel с четырьмя vCPU, восемью гигабайтами RAM и HDD

    А вы могли не отбирать у деда его ноутбук из нулевых, а инвестировать немного в один единственнгый рабочий ПК в роли сервера, и несколько ip адресов? Хуанана на старых ксеонах и с дешевой памямятью вам бы на время разработки хватило на все-все-все.. заодно бы сэкономили на обогреве офиса.


    1. tarasov_cloudsell Автор
      14.12.2025 09:12

      Здесь важно, что под «карточной игрой» у всех разное понимание. У нас бой это довольно сложный серверный просчёт: сотни персонажей и способностей, баффы, дебаффы, триггеры, массовые эффекты, вероятности. Каждый бой почти уникален и формирует большой лог в JSON.

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

      Да, алгоритмы ещё будут оптимизироваться, это инди-проект, а не AAA. Сравнивать с Lineage2 не совсем корректно: другая архитектура, другое время и другие ресурсы.

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


      1. Deosis
        14.12.2025 09:12

        Почему бы не сделать бой более детерминированным? В начале боя выбирается сид и отправляется клиенту (опционально с результатами и наградами)

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


        1. tarasov_cloudsell Автор
          14.12.2025 09:12

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


          1. here-we-go-again
            14.12.2025 09:12

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


  1. winkyBrain
    14.12.2025 09:12

    Накинете доступ в ЗБТ или он исключительно платный?)


    1. tarasov_cloudsell Автор
      14.12.2025 09:12

      Напиши мне в тг @edwstone


  1. ValeriyPush
    14.12.2025 09:12

    Привет, а почему вы просто не наймете адекватных разработчиков (может, чуть дороже рынка)?

    Время просчёта боя сократилось с двух с половиной секунд до одной

    Шо, из Озона ушли?

    Паттерн Actor, Orleans.


    1. tarasov_cloudsell Автор
      14.12.2025 09:12

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