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

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

Забегу вперед и расскажу, что сейчас DAU в наших проектах около 1,5 млн. Но так было не всегда.

Первый коммит


Первый коммит игры War Robots в git был сделан 29 июля 2013 года. И это был не бездушный initial commit, файлов прилетело огромное количество. Сколько времени было потрачено на разработку до этой даты — неизвестно, зато мы можем посмотреть на всё, что происходило после.

Коммит коммитом, но 14 апреля 2014 года произошло всеми ожидаемое «чудо» — запуск War Robots (тогда еще — Walking War Robots). Для сравнения — первые полгода DAU игры составляло около 10-15 тысяч игроков.

Итак, на чем же все это держалось.

Инфраструктура 1.0




Профиль-сервер

Начнем с простого. Профиль-сервер представлял собой множество серверов с БД (Cassandra). На этих же серверах размещались app-сервера, с которыми непосредственно общался клиент. Это были tomcat’ы, к ним клиент ходил по HTTPS.

Профиль-сервер хостил профили игроков — что у них находилось в гараже, в магазине, как экипирован робот и т.д. Забегая вперед, скажу, что с тех времен структура профиль-сервера практически не изменилась. Лишь app-сервера мы вынесли на отдельные физические машины, а БД оставили на своих. Ну и количество серверов со временем только выросло.

До запуска и продолжительное время после него, разработкой профиль-сервера занимался один-единственный человек из белгородского офиса. Только когда стало понятно, что у проекта все хорошо и он быстро растет — мы начали расширять команду, т.к. понадобилась высокая скорость разработки. Сейчас «профилем» занимаются 6-7 человек.

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

Своих серверов на момент запуска у нас не было и мы использовали Photon Cloud. Самые частые вопросы, которые я слышу после его упоминания, это «где логика?» и «как работал матчмейкинг?». Вариантов может быть множество, но сейчас речь пойдет о том, как всё было устроено в War Robots.

Матчмейкинг

Любой бой в War Robots начинается с матчмейкинга. И у нас (как и у многих других) это было построено по принципу «нужно вчера и даром».

Представьте комнату, в которой старейший клиент, как в дворовом футболе, набирал 2 команды и отправлялся с ними в бой. Флаг капитана переходил оставшемуся в комнате старейшему клиенту и история повторялась.

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

С ростом игроков схема работала все хуже и хуже. Теперь нужно было срочно придумать решение, которое работало бы уже «позавчера». Нет проблем! Запускаем клиент на ПК прямо в офисе, запрещаем ему забирать себя в бой и, вот, через десятки минут — он уже самый старый клиент в комнате! Гениально и просто.

Теперь нам нужно разделить ММ на группы. Как думаете, что мы сделали? Правильно — запустили четыре экземпляра клиента на всё той же машине в офисе. И так это работало целых полгода!

Напомню, что речь идет про первые месяцы жизни игры с реальными игроками — теми самыми 10-15 тысячами DAU.

Матч

А где же логика матча? Ответ: мастер-клиент. Первый, кто попадал в игровую комнату, становился таковым. Именно он решал, когда начнется/закончится матч; аппрувил точки спавна; определял победу/поражение команд по очкам. Более того, каждый клиент контролировал захваты маяков по-своему (в первом режиме War Robots «Превосходство» для победы необходимо уничтожить всех противников или захватить и удерживать наибольшее количество маяков, разбросанных по карте).

И вы вполне себе в одном матче могли наблюдать разные состояния маяков. Куча багов в первые месяцы и жалобы про «маяки не захватываются» — это всё из-за этого (да простят нас наши саппорты), it's by design!

Как регистрировались попадания? Это вообще отдельная и интересная тема. О ней уже рассказывали, а для общей картины лишь скажу, что в тот момент попадание регистрировал сам клиент, в которого стреляли. Просто представьте себе запись в логе боя: «Докладываю: MegaKiller3000 нанес мне 2324 урона»…

Ах да! Каждый клиент вел свой собственный лог боя! По окончанию матча он отправлял его на профиль-сервер, профиль-сервер дожидался N логов боя и принимал решение, кому чего и почему начислить. И когда профиль-сервер считал, что может решить исход боя (получил достаточно логов) — клиенту прилетал результат и тот рендерил экран со статистикой боя (известный как «посткомбат»).

А теперь представьте — не все клиенты доигрывали бой, кто-то отключался, кто-то психовал и сам закрывал игру, и с этим как-то нужно было жить. Казалось бы, что это всё вообще не может так работать. Но в 95% случаев это работало. Саппорты тех времен даже говорят, что это было терпимо.

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

Инфраструктура 2.0


В тот момент серверными решениями занимались лишь несколько разработчиков в компании. Одними из самых опытных были ребята из команды AppMetr.

Java-разработчики установили на маки Parallels + Windows + Photon Server SDK и принялись за разработку игровых серверов War Robots. Результат их труда я назвал инфраструктурой версии 2.0. Разработку вели параллельно с описанной выше историей.



Как видите, на схеме отсутствует Photon Cloud. Зато появился мастер-сервер (ура!). Он же занимался балансировкой, туда же уехал матчмейкинг и появились наши игровые сервера, которые обслуживали игровые комнаты.

Как следствие, мы устранили часть описанных ранее ужасов by desing. Матчмейкинг уехал с компьютера в офисе на мастер-сервер. Расчет результатов боя — с профиль-сервера на игровые сервера. Потихоньку переносили логику матча с мастер-клиента на игровые сервера. Захват маяков, условия победы, расчет урона…

Инфраструктура 3.0. Что дальше?


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

Немногим позже подъехала наша фича с кланами, под которую появилась следующая инфраструктура 3.0:



Ключевое отличие от всего, что было раньше — сервисы. Появился отдельный Communication-сервис. Клиент научили устанавливать соединение с «ангарной» комнатой на игровом сервере и делать API-запросы (единая точка входа для взаимодействия с сервисами).

В кланах также очень хотелось иметь чат, первая версия которого и была реализована на Photon Chat’е. Но нас не устраивала потеря истории чата при отключении всех клиентов от чат-комнаты, поэтому мы реализовали собственный. Cassandra используется как раз для хранения истории:



Ну теперь вроде всё хорошо, но чего-то не хватает. Матчмейкинг! Он же все еще был на мастер-сервере. Поэтому перейдем к следующей (она же — текущая) версии инфраструктуры.

Инфраструктура 4.0. Текущая версия



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

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

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


  1. MrBuha
    10.01.2018 14:00

    Классная статья! Понравилось, как Вы версионность инфраструктуры описали. Емко и «по существу». Добавил в закладки.


  1. VioletGiraffe
    10.01.2018 14:05

    Какие технологии используются на серверах/сервисах? Я имею в виду, на каком языке (или языках) логика написана?


    1. nonnname Автор
      10.01.2018 14:31

      Если вкратце, то целый зоопарк:
      Master/game servers — c#, akka, photon engine
      Profile servers — Java 8, Guice, Resteasy, Hazelcast, Cassandra
      Microservices clan/league/matchmaking/communication — scala, akka, postgresql, scalikejdbc, cassandra, phantom


      1. AbstractGaze
        10.01.2018 15:54

        Я про cassandra и подобный тип хранения узнал только вчера (из курса), а тут еще и статья. В краце не поясните почему так? Почему не mongodb например?


        1. nonnname Автор
          10.01.2018 16:14

          Исторически сложилось. У нас AppMetr был на кассандре. Посмотрели — модно, молодежно и масштабируемо. И запилили.


          1. nonnname Автор
            10.01.2018 16:19

            Ну и еще в пользу кассандры можно записать то, что она децентрализованная, а mongo — это master-slave.


  1. Aivendil
    10.01.2018 16:32
    +2

    Спасибо за статью! Редко на хабре увидишь рассказ о реальной разработке, так как все боятся, что за «неидеальность» камнями закидают:)


    1. AbstractGaze
      11.01.2018 08:48

      Вряд ли… Камни как раз позволяют понять проблемы если они есть или увидеть если не заметили. Скорее тут боязнь делиться удачными решениями, чтобы конкуренты не обошли. Правда эта боязнь постоянно теряет свою актуальность, если уже не потеряла целиком.


  1. Hixon10
    10.01.2018 20:51

    Спасибо за статью!

    Расскажите, пожалуйста, как у вас сделана балансировка? Как клиент выбирает, на какие сервисы идти, например.


    1. nonnname Автор
      11.01.2018 12:14

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


  1. amaxim
    11.01.2018 11:11

    Спасибо за рассказ. Что такое Amazon RDS для Redis в квадратике Communication?


    1. nonnname Автор
      11.01.2018 12:23

      Amazon RDS для Redis это мой ляп, спасибо, что заметили, сейчас поправлю. Речь, конечно же, о aws.amazon.com/redis (Fully managed Redis on AWS)