Как многие из вас знают, 26-го марта Allods Team (студия Mail.Ru Group) запустила открытый бета-тест (ОБТ) нового MMORPG-проекта Skyforge. Меня зовут Сергей Загурский, я работаю в команде сервера и хочу рассказать о том, как проходил запуск, с какими инцидентами мы столкнулись и как вышли из ситуации победителями.
Ранняя фаза ОБТ
26-го марта ОБТ стартовал для обладателей наборов раннего доступа. В течение недели у них был эксклюзивный доступ к игре, и они могли воспользоваться им для получения небольшой форы перед другими игроками. Эта фаза не принесла нам больших сюрпризов, т.к. нагрузки, в целом, были сравнимы с нагрузками на закрытом бета-тесте и стресс-тесте. Интересное началось потом…
Доступ открыт для всех
2-го апреля, в четверг, в ходе плановой профилактики, была снята галочка «Вход разрешен только обладателям наборов раннего доступа». Несмотря на задержки при входе в игру, всё прошло достаточно гладко для первого дня. Была ночная профилактика, посвященная устранению шероховатостей конфигурации железа/софта.
Пятница!
Интересное началось в пятницу, 3-го апреля. Утром, после окончания ночной профилактики, игроки начали заполнять серверные ёмкости. Через 20 минут после старта серверов мы прошли планку нагрузки на стресс-тесте и вышли на неизведанную территорию. Безусловно, мы проводили в разы более масштабные синтетические нагрузочные тесты, но игрок — существо непредсказуемое, от которого можно ожидать нажатия кнопок, на которые боты нажимать еще не научились. Первые признаки грядущих сложностей не заставили себя долго ждать — уже через 2 часа после открытия сервер первый раз остановил вход пользователей в игру.
Один из главных фокусов при разработке сервера — качество обслуживания. Поэтому мы разработали несколько механизмов, позволяющих оценить его для игроков, уже находящихся в игре. Если эта оценка падает ниже определённого порога, то мы приостанавливаем вход новых игроков, руководствуясь соображением «лучше меньше, да лучше». По превышению этого показателя через два часа после старта мы на полминуты закрылись, а игроки начали наблюдать очередь на вход, которая продвигалась только за счёт тех, кто из неё решил выйти. Многие из разработчиков находились в это время в игре и несколько недоумевали, т.к. по субъективным ощущениям качество обслуживания не пострадало. Тому было несколько причин. Анализ нагрузки выявил несколько нод с аномальной нагрузкой. Самым высоконагруженным был сервис, обслуживающий внутриигровой рынок. В самой игре рынок, по ощущениям, работал с приемлемой задержкой. Вторыми по нагрузке были несколько нод, хранящих данные игровых персонажей. Тут требуется небольшой экскурс в недавнюю историю этих нод.
На этапе закрытого бета-теста мы были несколько обеспокоены рисками того, что наши основные ноды с базами могут не осилить нагрузку. Поэтому мы незадолго до начала ОБТ задействовали под базы несколько дополнительных машин. По конфигурации они подходили во всём, кроме дисковой подсистемы. Поэтому на эти машины поставили SSD-диски из закромов и подключили к серверному стенду в новой ипостаси.
Особенность балансировки персонажей по нодам с БД сыграла с нами небольшую шутку. Конкретный номер ноды, на которой будет храниться персонаж игрока, определяется в момент, когда пользователь создаёт аккаунт. Даже если этот аккаунт создавался с игрового портала. Нетрудно догадаться, что все игроки, проявившие интерес к игре, зашедшие на портал игры и зарегистрировавшие там аккаунт, были сбалансированы на «старые» ноды. В их числе были и все разработчики. Впоследствии это мешало нам составить картину качества обслуживания с точки зрения игрока, т.к. на этих нодах нагрузка была в пределах нормы. Об этих особенностях мы знали, разумеется, заранее и предприняли меры, чтобы на «старые» ноды новые пользователи регистрировались только после того, как нагрузка на «старых» и «новых» нодах будет выровнена. Так в нашей игре появились, как мы их назвали, ноды «для старожилов», на которых жили все обладатели наборов раннего доступа.
Вернёмся к хронике. Как я уже говорил, нагружены были не все ноды с базами, а только несколько. Причём на нодах «для старожилов» качество обслуживания было выше, несмотря на то, что игроков на них в этот момент было сильно больше. В это время сервер закрывал свои двери уже в N-ый раз, и мы, руководствуясь тем, что внутри игры ничего не лагало, решили скорректировать границу максимальной нагрузки, после которой сервер приостанавливает вход игроков в игру. Таких коррекций было несколько, каждая из которых временно улучшала ситуацию с входом в игру. Мы пытались нащупать значение, на котором нагрузка стабилизируется. После очередной коррекции нагрузка на нодах с БД стабилизировалась, а рынок продолжал деградировать.
Случилось. Дэшборд рапортовал о том, что сервер начал процедуру аварийной остановки. Краткое расследование показало, что сервер был потушен в строгом соответствии с заложенным в него алгоритмом. Что называется, by design.
В распределенной системе игрового сервера есть много нод, которые отвечают за хранение тех или иных данных о персонажах и игре в целом в БД. Стратегия быстрого восстановления при сбоях включает в себя периодическое создание консистентных restore point'ов на всех нодах с базами данных. Раз в некоторый отрезок времени специальный сервис координирует создание этих restore point'ов и уведомляет о проблемах с их созданием. Система настроена таким образом, чтобы исключить откат прогресса персонажей в случае нарушения целостности данных, более чем на 10 минут. В нашем случае сервис отрапортовал о невозможности создания restore point'ов для БД рынка и инициировал остановку игрового сервера. В ходе вынужденной профилактики было решено деактивировать игровой рынок. Самым надёжным решением было отдавать в клиент пустые списки возможных операций. Заплатку, которая делала эти списки пустыми, мы залили с помощью hotswap сразу после перезапуска.
В процессе всего этого была выяснена причина аномальной нагрузки на некоторых нодах, хранящих данные игровых персонажей. В силу рокового стечения обстоятельств на новые ноды с базами были установлены диски меньшей производительности. Диски на замену были найдены, замена была запланирована на плановую профилактику в понедельник. Также коллеги успели изготовить патч, исправляющий аномальную нагрузку на рынке, выкладка которого тоже планировалась в понедельник.
После перезапуска
Ситуация, казалось, стабилизировалась. Нагрузка на некоторых нодах с БД была высокой, но стабильной. Большинство игроков наблюдали это как задержки при поднятии лута, операциях с адептами и прокачкой графа развития. Рынок был полностью отключен, и это блокировало ощутимую часть user experience. Более глубокий анализ показал, что с точки зрения нагрузки гораздо больший вес имеют операции по продаже, и мы с помощью того же hotswap’а включили возможность покупки на рынке. Результаты анализа нас не обманули, рынок стал отвечать за приемлемое время.
Сервер работал, команда собиралась в 19:00 провести небольшой корпоратив, посвященный запуску ОБТ. И тут в логах проскакивают подозрительные сообщения от БД, говорящие о нарушении целостности баз на нодах с менее производительными дисками. Небольшой диалог с командой оперирования, проверка состояния реплик — и в 19:00, во время торжественной части корпоратива, под крики «Ура!» и брызги шампанского, подозрительные ноды отправляются на профилактику.
Pg_dump на репликах и мастере показывал одно и то же неутешительное сообщение об ошибке. Всё указывало на потерю части данных игровых персонажей. Планы резко меняются. Плановая профилактика переносится с понедельника на ночь с пятницы на субботу. Срочно выезжает курьер для доставки SSD до нужного датацентра. Оперативно начинаем сборку новой версии сервера, в которую входят все исправления и оптимизации, сделанные на тот момент. Мы, поседевшие, сидим и разбираем сбойнувшие базы.
Разбор показал, что нарушена целостность не всех баз. Оператор переконфигурировал сервер таким образом, чтобы запуститься без испорченных баз. Более спокойный и глубокий анализ выявил, что вследствие сбоя Postgres’а были испорчены только индексы, которые, к всеобщему удовлетворению, были корректно пересозданы.
Новые сбои
В момент, когда я подходил с этой новостью в команду оператора, они удалённо координировали замену медленных дисков на нормальные. Телеметрия показывает сбой и падение количества игроков (да, в Skyforge всё это время продолжали играть те игроки, чьи персонажи были на включенных нодах). Ошибка сотрудника. В 3 часа ночи дежурный администратор вытащил диски не из 12-го, а из 11-го юнита. В 11-м юните находится нода с сервисом аутентификации. Истерический смех.
К счастью, RAID, из которого вытащили диски, не рассыпался, и этот инцидент лишь немного продлил профработы. Кстати, вплоть до момента полной остановки сервера на нём оставались 6 человек, которые играли. После остановки сервиса аутентификации можно продолжать играть до тех пор, пока не произойдёт переход на другую карту (что, кстати, является багом, и в будущих версиях переход не будет зависеть от сервиса аутентификации).
Запуск в 7 утра
Утром сервер был запущен на всех базах. Итогами этих ночных профработ в том числе были: а) замена медленных SSD на обычные на некоторых нодах, б) временный перенос синхронных реплик на RAM-диск, чтобы снизить нагрузку на SSD. Нагрузка на нодах, хранящих данные персонажей, больше не вызывала беспокойства.
Шо, опять?
В 13:45 субботы нагрузка на нодах с данными игровых персонажей улетает в бесконечность, и сервер аварийно останавливается уже известным нам сервисом создания restore point’ов. Причина: переполнились RAM-диски с синхронными репликами, и ноды заблокировались на коммите. Т.к. на тот момент мы уже знали, что острой необходимости в RAM-дисках для реплик нет, то в ходе внеплановой профилактики мы переключили синхронные реплики обратно на SSD и перезапустили сервера. В субботу также выяснилось, что в горячке сборки новой версии сервера, в неё-таки не попали оптимизации по рынку, поэтому продажу на рынке снова пришлось отключить.
Подведем итоги
Топ проблемных мест, из-за которых мы потратили больше времени, чем могли бы:
- Синтетическая нагрузка на нагрузочных тестах рынка размазывалась по всем позициям на рынке, а в реальности был серьёзный contention на одной из позиций. Это и приводило к аномально высокой нагрузке сервиса рынка.
- Недооценка возможности сбоя со стороны железа и RDBMS. Это было для нас некоторой неожиданностью и, будь мы подготовлены, внеплановой профилактики вообще можно было избежать.
По поводу чего мы, в контексте вышеупомянутых приключений, испытываем гордость:
- Инструментарий для hotswap позволил нам оперативно реагировать в различных ситуациях. Это касалось как включения/отключения фичей игры, так и расширения диагностики без остановки сервера.
- Сервер подтвердил свою устойчивость при отключении/падении отдельных нод.
- Диагностика и автоматические отчёты о работе сервера нам очень помогли в обнаружении и определении причин сбоев.
Автор: shortcircuit