Заметки про игры

Истории из командного центра Pax Dei

Разработчики Pax Dei рассказали несколько закулисных историй о технической стороне работы игры. В тексте много технических терминов, но все равно было интересно почитать о том, как табуны кроликов положили сервер.

Вот мы и подошли к концу первых 24 часов нашего второго альфа-тестирования. Как и следовало ожидать, было усвоено много уроков, пришлось переступить через свою гордость, но мы также получили несколько приятных сюрпризов.

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

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

Наш стек довольно сложен и состоит из множества серверов, работающих со множеством сервисов в разных географических регионах. Для этого теста мы задействовали около 150 виртуальных серверов, распределенных между ЕС и США. Примерно две трети из них — это серверы Unreal, работающие с определенными зонами в конкретных мирах и автоматически запускающиеся при входе игроков в эти зоны. Остальные — это внутренние серверы, выступающие в качестве конечных точек API для различных игровых сервисов. К ним относятся инвентарь, аватар, группы, здания и аутентификация. За всеми этими сервисами стоят несколько больших баз данных, в которых хранятся все данные о клиентах, их персонажах и связанных с ними постоянных состояниях.

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

Во время таких мероприятий, как сейчас, мы собираем команду Liveops, которая следит за Datadog, а также мониторит каналы социальных сетей, работая посменно круглые сутки. Эта команда состоит из наших самых опытных инженеров по надежности сайта, инженеров-программистов и комьюнити-менеджеров. Состав этой команды таков, что она должна быть способна устранять критические ситуации в реальной среде, находить приемлемое решение, тестировать и развертывать это решение, а затем контролировать, что оно действительно решило проблему, и все это при максимальном обновлении сообщества и обеспечении того, чтобы все, что делается, затрагивало наименьшее количество людей. Вся эта команда собирается в так называемом Командном центре, который представляет собой канал видеоконференции, где проблемы обсуждаются и решаются коллективно. Подумайте об этом как об управлении полетами Apollo (по крайней мере, именно с этим они любят себя сравнивать).

Вот несколько историй из Командного центра.

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

Когда около 12:30 по Гринвичу мы достигли популяции примерно в 5 тысяч игроков, мы начали получать первые предупреждения. Сервер Redis начал опасно приближаться к 100% нагрузке процессора. Серверы Redis используются для кэширования и быстрого сохранения изменчивого состояния серверов Unreal в нескольких мирах в одном регионе AWS. Они очень эффективны и, как правило, не являются чем-то, что легко прогибается под нагрузкой, но вам все равно нужно иметь некоторое обоснованное первоначальное предположение о том, какая мощность процессора ему потребуется. Обычно мы можем сформировать обоснованные предположения, симулируя трафик на различных конечных точках, но в случае с сервером Redis мы не стали проводить такие тесты, а ограничились стресс-тестами с использованием внутренних игроков, а также специальных тестовых ботов. Эти тесты и близко не подходили к симуляции текущей нагрузки, и стало ясно, что необходимо переключиться на более производительную ноду. Обычно это можно сделать вживую и прозрачно, но в данном случае служба не была настроена на работу с легкодоступной репликой (так называемый режим Multi-AZ).

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

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

Кролики. Кролики повсюду.

Всегда кролики, не так ли? Правило распределения ресурсов, которое использовалось для контроля популяции кроликов, вело себя плохо в некоторых биомах, что приводило к увеличению количества кроликов. Теперь, несмотря на то, что кролик кажется невинным существом, на самом деле он считается полноценным существом в нашем подсчете НИП. Когда сервер полностью заполнен игроками, НИП необходимо держать под контролем, так как они конкурируют за ресурсы процессора сервера для таких задач, как обнаружение столкновений и поиск пути. Обновить распределение ресурсов, чтобы уничтожить этих кроликов, достаточно просто, но в данном случае это потребовало бы перезагрузки затронутых зон. Поскольку у нас не было четкого представления о том, какой узел может быть затронут кроличьим нашествием, и учитывая, что мы уже боролись с еще одним нарушением из-за перезапуска Redis, а также необходимость применять одни и те же изменения к разным регионам мира, было решено перевести всю игру в режим обслуживания, чтобы мы могли перезагрузить все должным образом.

Режим технического обслуживания, по сути, закрывает доступ для всех игроков, поэтому он сразу же отключает сервис, позволяя нам перезагрузить мир и завершить некоторые изменения, которые мы хотели применить. Мы хотим избегать этого как можно чаще, потому что это на 100 % нарушает процесс игроков. Тем не менее, с этим связана и другая проблема: выход из режима технического обслуживания.

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

Примерно через 20 минут простоя мы вернулись в седло, а количество игроков постоянно росло, так как к игре начали присоединяться не только жители ЕС, но и США. Примерно в 17:30 по Гринвичу мы достигли того, что, по нашим прогнозам, должно было стать пиком количества подключенных игроков за день.

В этот момент мы начали наблюдать некоторую турбулентность в силе, и в данном случае она оказалась связана с перегрузкой базы данных. Казалось, что она затрагивает в основном один регион, но поскольку некоторые из наших запросов к БД работают с несколькими БД в нескольких регионах, эффект ощущался повсюду. Казалось, что наши БД правильно настроены и даже при такой высокой нагрузке не должны работать на 100 % процессора, но что-то заставляло БД останавливаться.

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

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

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

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

Именно поэтому мы проводим такие тесты, как Альфа, и очень благодарны сообществу, которое участвует в подобных мероприятиях, помогая обнаружить эти труднодоступные проблемы и создать более надежные системы для их решения в будущем. Мы еще раз хотим выразить искреннюю благодарность всему нашему сообществу за поддержку и страсть к Pax Dei.

Дальше