Нагрузочное тестирование в Skyforge, или Боты – санитары сервера. Часть 1

    Привет, Хабр!
    Меня зовут Александр Акбашев. Я – QA-инженер Allods Team на проекте Skyforge. В зону моей ответственности входит организация тестирования сервера нашей игры, и именно о тестировании сервера будет данная статья. В мае я делал доклад на КРИ, который превратился в статью из двух частей. Эта статья – первая из них.



    Skyforge с высоты птичьего полета


    Технологический стек Skyforge таков: клиент игры написан на C++, сервер игры разрабатывается на Java, много различных полезных утилит и скриптов написано на Python. Еще у нас есть инструменты для дизайнеров, написанные на C#, но в статье не будет больше ни слова про C#. :)

    Что же такое боты и зачем они нужны?


    Во время разработки проекта Аллоды Онлайн перед командой сервера встал серьезный вопрос: как проводить комплексные и нагрузочные тесты сервера? Решили написать для этого ботов – автономное клиентское приложение, эмулирующее поведение реального игрока. С тех пор, конечно, много воды утекло. Боты, используемые в Skyforge, уже мало похожи на самых первых хиленьких ботов. Назначение и инфраструктура тестов, проводимых с их использованием, также эволюционировали: теперь боты помогают нам получать огромное количество серверных характеристик для анализа. Всё благодаря тому, что на нашем проекте в процесс непрерывной интеграции включены ботовые тесты.

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

    Что же собой представляют боты?


    Наши боты реализованы так называемым «методом белого ящика»: у клиента, написанного на C++, удален интерфейс, а вместо него добавлен «мозг», написанный также на C++. Более того, общая база кода у клиента и ботов позволяет тестировать достаточно низкоуровневые вещи в самом клиенте.

    «Мозги» ботов реализованы с помощью конечного автомата – графа переходов из одного состояния в другое при определенных условиях. Также боты имеют постоянные активные элементы, которые действуют независимо от того, в каком состоянии сейчас находится бот и его «мозг». Они поддерживают, например, бессмертие ботов и чат-активности. С ботами можно переписываться в личном или общем игровом чате – они всегда готовы морально поддержать команду QA, цитируя различные истории с башорга.

    Пример простейшего графа переходов: бот появляется на карте, бежит, видит монстра и убивает его. Если есть трофеи – поднимает, если нет – бежит дальше.



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

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

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

    Первое – адекватность поведения. Боты должны соответствовать игрокам по поведению. Если получилось так, что боты не соблюдают требования гейм-дизайна, значит, надо их чинить. Например, бот, пробегая определенный участок, должен убить столько же монстров, сколько и настоящий игрок в таких же условиях.

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

    Тесты решают


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

    Проверка сервера

    Благодаря непрерывной интеграции, несколько раз в сутки мы собираем свежую версию сервера. Однако нет уверенности в том, хорошая вышла сборка или нет и можно ли её использовать. Тестировщики не всегда могут сразу же обновить клиент и проверить новую сборку. Для этого сейчас используется smoke test, который проверяет свежую сборку с помощью бота. Это достаточно простой бот: он заходит на сервер, ищет монстра и убивает его. Если все прошло гладко – сервер рабочий и на нем можно играть.

    Репетиция главного теста

    У нас есть ночной тест, который идет 8 часов и позволяет собрать очень много ценной информации. К сожалению, итерации теста очень дорогие, и, чтобы не пропускать запуски этого теста из-за ошибок, которые можно исправить за 5 минут, проводится отдельный дневной тест. Он запускается на той же версии кода и тех же данных, что и ночной, но всего на час. Таким образом, в течение дня проводятся репетиции ночного запуска. При необходимости мы успеваем исправить различные ошибки до конца рабочего дня. Прохождение часового теста на 99% гарантирует прохождение теста ночного.

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

    Проверка контента

    Контент Skyforge достаточно объемный. У нас очень много объектов игрового мира. Поэтому, когда запускается ночной тест, не всегда понятно, какие элементы дизайна приводят к дополнительной нагрузке. Не всегда понятно, почему на одном гейммеханическом сервере с определенным набором карт все хорошо, а на другом и с другим набором карт все плохо. Карта ли виновата, количество игроков или фаза луны GC? В результате были добавлены отдельные тесты по картам. Они позволяют сравнивать игру в стерильных условиях. Например, если взять три карты и прогнать их на одинаковых версиях кода и данных, мы получим разные сравнительные характеристики и температурные карты, на которых видно, где могут возникнуть критические места. Эти тесты, наверное, самое полезное, что у нас есть для профилирования игрового контента.


    Пример температурной карты (на шкале – некий performance rating, вычисляемый в ботах)

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

    Самый главный тест

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

    Заключение


    Очевидно, что ботовые тесты работают на стыке всех элементов проекта: запускается сервер, клиент, используется ресурсная система, база данных, мастер-сервер, билд-агент… И если хоть один из этих элементов сломается, весь тест можно считать проваленным. Необходимо прикладывать большие усилия, чтобы вся система работала как часы.

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

    Надеюсь, данная заметка про ботов была интересна сообществу. Спасибо за внимание!

    Слайды и видео


    Ниже представлены видео и слайды с конференции КРИ-2013


    Слайды

    Другие материалы можно посмотреть на сайте разработчиков Skyforge и в нашем сообществе Вконтакте.
    Mail.ru Group
    Building the Internet

    Comments 30

      +3
      Было бы еще интересно почитать про внутренне устройство ботов поподробнее. Как они «видят » монстров? Как переключаются состояния? Как достигается поведение, аналогичное поведению реального игрока (как оно корректируется)?
        +4
        Боты общаются с игрой не через UI, а непосредственно вызывая те или иные функции, которые есть в игровом клиенте. Поэтому на ботах хранится список всех объектов окружающего его пространства — мобы, лут и прочее. В связи с чем достаточно просто пробегать по этому списку, который постоянно обновляется, и выбирать нужные элементы.

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

        Есть дизайн, разрабатываемый гейм-дизайнерами, в котором указаны конкретные времена для конкретных активностей. Боты должны выдерживать этот дизайн.
          0
          А что произойдет если злоумышленник поковыряется в вашем протоколе и начнет мечом рубить монстров на другом конце карты? Ну или по крайней мере, я могу «открыть» себе всю карту. Вы как-то боритесь с этим / тестируете такое поведение или подобные выкрутасы запрещены соглашением и преследуются по понятиям закону?
            +2
            Конечно, боремся. Конечно, запрещено :)
            Насчёт тестирования протокола на устойчивость против злоумышленников ничего сказать не могу — просто не владею информацией.
              0
              Вы на самом деле спрашиваете элементарные вещи :) На сервере проверяются любые присылаемые клиентом данные, скажем в случае атаки выполняется проверка того, что игрок и монстр находятся на допустимом расстоянии, у игрока достаточно манны и т. д. Кроме того с сервера обычно никогда не приходит полная информация о состоянии игрового мира, лишь о том «кусочке» где находится данный персонаж, так что весь мир вы не просмотрите :)
                0
                Возможно, я не точно задал вопрос. Интересно было тестируют боты эксплойты или нет. Понятно, что сервер должен проверять, понятно, что есть юнит-тестирование, однако MMO — достаточно сложный механизм. Баги вполне могут быть.
                  0
                  Боты не могут протестировать эксплоиты, потому что уязвимости, которые должны эксплуатироваться ещё надо найти, а это отдельная не связанная с ботами задача.
                  Как вам уже выше ответили — все очевидные вещи, типа расстояния атаки и пр. проверяются на серверной стороне.
          –2
          На каких платформах выйдет? Mac и Linux будут?
            +5
            Боты никогда никуда не выйдут. На Маке их запускать не пробовал — хотя любопытство было. А на Линуксе они не очень производительно из под wine работают.
              0
              Наверное я не правильно сформулировал свой вопрос. Имел в виду не ботов, а саму игру. Понимаю что оффтоп, но всё же интересно.
                +1
                Windows — платформа для нас приоритетная, т.к. именно на ней сосредоточено больше всего игроков. Но и для других платформ какие-то компоненты Skyforge будут доступны. Дальше, увы, рассказать не могу — NDA.
            +12
            На сколько омерзительна система монетизации в проектах mail.ru, на столько же хороши в последнее время статьи про геймдев от mail.ru.
            Спасибо за статью, с нетерпением ожидаю вторую часть.
              +6
              Спасибо! Постараюсь Вас не подвести со второй частью.
              +2
              Боты это только инструмент, и одна из сложных задач это анализ данных от инструмента:) Расскажите, какие метрики выделяете с помощью этих ботов и на какие смотрите? Делаете какие-то регрессионные задачи?:)

              Есть еще какие-то сценарии у ботов? Ну например работа с инвентарем, аукцион, или под новый год большая доля пользователей собирается в одной локации ?:)

              Тесты запускаете на отдельном стенде, где нет настоящих игроков?:)
                +1
                Спасибо за отличный вопрос!
                Да, конечно, боты — это только инструмент. И во второй части статьи я как раз планировал подробно рассказать о том, какие характеристики мы смотрим. Но раз уж был задан вопрос, я на него отвечу.
                Т.к. наш сервер написан на Java, то мы очень тщательно следим за JVM — за сборками gc, за safepoint'ами и прочее. Так же у нас есть метрики отзывчивости сервера.
                По метриках баз данных лучше всех ответит Randll.
                Нагрузочные тесты у нас входят в CI, поэтому мы быстро можем заметить сильный регресс. С медленным регрессом всё сложнее. Т.к. постоянно изменяется не только код, но и данные.

                Сценарии — да, конечно. Боты либо поддерживают, либо должны поддерживать все активности, которыми игрок может заняться. В том числе, мы тестируем и большие компании в одной локации :)
                Есть отдельный нагрузочный стенд, но и на стенд с тестировщиками боты тоже ходят, чтобы никому не было одиноко.
                  +1
                  Я имел ввиду не метрики и характеристики тестируемого приложения, а сами метрики по которым вы оцениваете производительность. Возможна ситуация когда разработчик решил подправить селект к базе и он стал тяжелым. По метрикам приложения вы этого не заметите, а вот на базе будет творится что-то страшное. Уследить за всеми метриками довольно сложно, хотя если мониторить общесистемные метрики на всех участвоваших машинках можно.

                  Я имею ввиду именно метрики производительности, время ответа, время отклика, пропускная способность запросов. Как реализована эта часть? Вы просто в CI запускаете, например, 500 ботов и смотрите только на общесистемные метрики, или же всматриваетесь в распределения времен ответов, смотрите как выполнение одних сценариев влияет на другие? Например сценарий инвернтаря хорошо нагрузил базу данных и получение информации об окружающих NPC или игроках замедлилось в N раз.
                    +2
                    Как правило, это выглядит так. Мы запускаем ботов, смотрим царицу всех метрик — нагрузку на сервер, которая является величиной обратной тику, т.е. чем быстрее сервер обрабатывает все запросы — тем меньше нагрузка. Нормальной величиной нагрузки мы считаем 1. Так вот, если у нас нагрузка стала выше 1, кнопочка в UI окрашивается в красный цвет, и мы начинаем разбираться в причинах этого явления. Находим причины. Так появляется еще один график или даже несколько, посвященных именно этой причине — т.к. в процессе разбора полетов код для построения графика был написан, почему бы его не использовать.
                    И появляются некоторые ограничения, при которых нужно обращать внимание на этот график, даже при нормальной нагрузке. Скажем, превышена максимальная плотность объектов вокруг игрока — соответствующая кнопка красная.

                    По базам данных — у нас есть «шарфики» — это вид графиков, известный как stack. На этих графиках мы смотрим за тем, сколько операций одного типа у нас выполняется в единицу времени. Вместе с графиком нагрузки это очень ценная информация для отладки. И если состав операций не изменился, а нагрузка изменилась — значит есть регресс в операциях.

                    Надеюсь, что ответил на Ваш вопрос.
                      0
                      Что такое «нагрузка» в вашем понимании? Что-то вроде Load Average?:)
                      Проблема вся в том, что для пользователя могут начатся тормоза даже при сохранении уровня «нагрузки».

                      Представьте ситуацию, пользователь открывает свой инвентарь и в базу летит селект и fetch всех строк. И раньше инвентарь был небольшим, и это было можно сделать за одну операцию. Но есть пользователи у которых инвентарь большой, и вы решили сделать select порциями по N строк, используя простой LIMIT. Так вот суть в том, что уровень нагрузки на сервер может остаться тем же, а клиенту необходимо еще все это скомпоновать и результируещее время ответа можеть быть выше чем прежде. На выполнение той же задачи нужно отправить, получить и обработать больше чем раньше.

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

                      Лучше разграничить все метрики на 2 типа: метрики софта/железа (прикладные/системные) и метрики производительности(время, пропускная способность, времена ответа/отклика, квантили/процентили), и только по последним говорить о производительности. Первый тип имеет только косвенное отношение к производительности:)
                        +1
                        Все метрики можно разделить, используя разные критерии. Как уже отмечал Андрей в своей статье, загруженный аватар — это своего рода кэш. Поэтому пример выбран не совсем удачно.

                        Со «знатными багами» мы боремся таким образом, что наши qa-специалисты, занимающимся ручным тестированием, иногда проверяют игру под нагрузкой.

                        Нагрузка на сервер — это величина, обратно пропорциональная времени, которое мы проводим в обработке. Есть контракт, что это время не может быть больше (допустим) 200 миллисекунд. Если пользователь видит «тормоза», это означает, что сервер стал дольше обрабатывать его запросы. Следовательно, сервер больше времени проводит в обработке. Таким образом, нагрузка увеличится.
                      +1
                      Для обычных серверов у нас есть метрика, называемая «нагрузка», которая включает в себя всё. :)

                      С базой чуть сложнее.
                      Мы смотрим
                      — сколько всего датабазных транзакций у нас прошло единицу времени.
                      — разбивка по типам. т.е. 100 операций взять предмет, 12 операций завершить квест и т.п.
                      — логируем, но не очень смотрим, мин/макс/среднее время отклика по одному типу транзакции за каждые 3 секунды. Это инфа для дебага а не для ежедневного просмотра.
                      — загрузку сервера исполнения транзакций в % от максимальной. Т.е. процент времени, который сервис тратит на обработку запросов.
                      — раз в несколько месяцев запускаем нагрузочный тест с логированием sql-я и потом, через pgfouine, находим и вычищаем топ тормозящих запросов.

                      Если кто-то подправил запрос и он стал тяжёлым, то мы увидим что нагрузка на датабазный сервис поднялась. Если кто-то сделал слишком частый запрос — мы увидим ненормальное количество операций определённого типа. Если кто-то написал медленный запрос, который выполняется редко, мы отловим это по профайлингу SQL-я.
                  0
                  Не смотря на то, что играть в игры от mail.ru как геймеру со стажем не интересно, читать реально интересно. Затягивает. Поражаешься простоте и гениальности некоторых идей.

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

                  А читаешь о реализациях, описанных у Вас и думаешь «Это же реально просто почему мне такая мысль не приходила в голову?»

                  А технических подробностей можно в будущих публикациях узреть? Ну там, например, сколько в штуках всего, сколько не справилось со своей задачей (упёрся в дерево и тупил, созерцая его ствол (условно)), и т.д.
                    +1
                    Вторая часть, которая ожидается где-то через 2 недели, как раз будет более техническая, правда, скорее о инфраструктуре тестов.

                    Статья о том, как устроены различные состояния в ботах, в том числе, хитроумный поиск точки, в которую боту стоит пойти, чтобы не найти дерево, не планировалась, но, судя по комментариям, читателям это интересно, поэтому я постараюсь найти время, чтобы её написать. Но ничего обещать не буду :) Если есть конкретные вопросы — задавайте, с радостью отвечу.
                      0
                      Анализировали ли вы, насколько стратегия среднего игрока отличается от
                      появляется на карте, бежит, видит монстра и убивает его. Если есть трофеи – поднимает, если нет – бежит дальше.
                        +1
                        Боты изначально разрабатывались для проведения нагрузочного тестирования. Для этой цели не очень важно, чем занят каждый конкретный «средний игрок» — главное, чтобы профиль создаваемой нагрузки был похож на то, что ждет нас на боевых.

                        И да, описанное в статье поведение — это простой пример. В наших сценариях есть много разных стратегий поведений, но почти все содержат ядро — «бегаю, убиваю, собираю лут». Т.к. согласно нашим представлениям именно это поведение будет вносить наибольший вклад в нагрузку на сервера.
                      0
                      ну Headless боты это не новинка.
                      0
                      А почему конечные автоматы-то? Behaviour Trees гораздо более гибкие, меньше переписывать при изменении окружающих условий, да и на ниве бото-строения они себя зарекомедовали прекрасно.
                        +1
                        Так исторически сложилось, что в самой первой версии ботов, разрабатываемых еще для Аллодов, были использованы именно конечные автоматы. Каких-то проблем с добавлением новых состояний или с производительностью мы не испытываем, поэтому остаются конечные автоматы.
                        0
                        Оффтоп: если честно, то вообще хотелось бы почитать статьи об ИИ…
                          +1
                          Когда я только начинал работать в Allods Team, и искал статьи об ИИ в рунете, то наткнулся на статью Тимура Бухараева, написанную так же по мотивам КРИ и посвященную Героем V.
                          Сейчас, правда, Тимур уже не занимается ИИ.
                            0
                            Отличная статья! Действительно отличная!
                            Основная цель у игры — развлечь человека, сделать ему приятное. А человек любит побеждать, любит ощутить свое превосходство, пусть даже над электронным болваном. Поэтому ИИ, который тоже работает на индустрию развлечений, должен сначала посопротивляться для вида, а потом проиграть.

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

                            Не пойман — не вор

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

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

                        Only users with full accounts can post comments. Log in, please.