Под капотом квеста для программистов


    В настоящий момент мы работаем над новым проектом – разработкой online квеста, суть которого заключается в том, чтобы программисты, разделившись на два лагеря (ИТшники и ФСБшники), решали бы самые разные задачи из области программирования на своем любимом языке, проходя при этом некоторую интересную историю посредством чтения красочного комикса с захватывающим сценарием. Сразу оговоримся, что ограничений на языки программирования нет. Единственное ограничение: они могут быть просто не проинсталлированы на серверах ввиду их редкости, например. Сегодня нам хотелось бы рассказать о проблемах, с которыми мы встретились в разработке серверной части.

    Самой главной проблемой проекта стало обеспечение безопасности серверов во время игры, т.к. мы позволим запускать у себя, по сути, посторонний код без каких либо ограничений на доступ к ресурсам. Т.е. запуская программы, мы должны таким образом настроить окружение, чтобы отработанная программа (которая может по факту может оказаться инсталлятором вируса) не сломала сервер и была удалена по окончании работы. При решении проблемы необходимо сформировать список пунктов, из которых она состоит. Наш список выглядит так:
    1. У нас есть сервер, на котором будет крутиться некоторое программное обеспечение, полученное из внешнего источника, и которое, по факту, неизвестно что будет делать, пока работает;
    2. Есть, в перспективе, большое количество пользоваталей, которые будут заливать на сервак большое количество приложений. Часть из них, вполне возможно, могут оказаться даже вирусами: мы позволим заливать все, начиная от php, заканчивая exe файлами. Проблема похожа, но немного шире: программа может резидентно остаться работать на сервере;
    3. Запускаясь, программы будут выедать огромное количество ресурсов.


    Затем, мы приступили к поиску решений.



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


    Если бы нашей платформой выступал Linux, это было бы решением. Это было бы хорошим и устойчивым решением, которое бы всех устроило как по стоимости, так и по времени создания. Однако, так исторически сложилось, что наша группа — разработчики .NET и нам чужда эта система. А потому, чтобы не подрывать безопасность сервера своим незнанием тонкостей, было решено остановиться на Windows платформе.
    Песочницу в системе Windows создать можно. По этому вопросу было проведено целое исследование. Например, можно процесс ограничить по количеству выделяемой им оперативной памяти. Или по количество дисковой памяти, которое может быть занято на файловой системе. Можно ограничить процесс почти во всем, однако, да простит меня Билл Гейтс, в ОС Windows слишком много вирусов, а это значит что все эти преграды могут быть устранены, например, вирусом. Потому, на середине разработки этой версии, было решено от нее все-таки отказаться. Несмотря на то, что по сути это было бы классным решением: нет проблем сбора результатов работы программы, и нет проблем очистки от деятельности программы. С помощью объектов ядра Windows, которые называются Jobs, ставятся ограничения на использование ресурсов ОС, а с помощью правил в NTFS – ограничения на работу в файловой системе. Практически то, что надо, но чувство самосохранения подсказывало, что есть еще варианты, которые могут быть сделаны достаточно быстро.


    На самом деле, этот вариант лежит на поверхности как первое, что приходит в голову. Есть виртуальная машина, на которую надо задеплоить необходимые приложение и файлы. Далее, приложение запускается, его output собирается в файл, а после завершения работы – файл забирается с виртуальной машины, которая в свою очередь сбрасывается в исходное состояние. Это решение обладает целым рядом плюсов, делающих его выигрышным по всем статьям:
    1. Состояние машины сбрасывается, а это значит, что там, внутри, хоть апокалипсис, хоть снос операционной системы с жестких дисков. Абсолютно все равно, что происходит. В конце работы (или по таймауту) просто берем и откатываем до снапшота.
    2. Окружение не ломается после того, как отработает предыдущая машина.
    3. Можно контролировать каждую мелочь.
    4. Однако, есть один минус: сложное управление.

    Сначала мы думали, что внутри машины придется запускать агента, который будет управлять деплоем, запуском, и забором output программы для последующей пересылки на хост-машину. Однако потом, как выяснилось, есть замечательный продукт: VirtualBox, у которого есть богатый API и агент, который мне так необходим. Почему меня так обрадовало наличие готового агента? Чем больше компонент мы запустим с нуля, тем больше багов мы словим. Не потому, что мы такие неопытные, нет. Просто баги есть всегда, а в только что написанном ПО тем более. Отлаженный сотнями тысяч запусков код гораздо лучше самописного.
    По той же самой причине мы отказались от одного рискованного шага: чтобы сэкономить на ресурсах можно было бы использовать в качестве гостевой операционной системы ReactOS. Реально можно было бы. Если бы не одно НО. Часть интерпретаторов там просто не запустилась. Ни в какую. Может быть в этой ОС есть всего одна ошибка, и она находится глубоко в ядре. Но ее наличие аффектит половину приложений и создает ощущение нестабильности происходящего. Если бы не это, мы бы выбрали именно ее, хотя бы по следующим причинам:
    1. Она сравнительно ничего не занимает на жестком диске (~40Мб)
    2. Она почти не занимает оперативную память (~40 Мб)
    3. Она практически не забирает на себя ресурсы процессора

    Это делает ее идеальной для случая, когда на одной физической машине надо запустить до 20 виртуальных машин. Эта шикарная операционная система и будет идеальной, когда ее аккуратно допилят до безбажного состояния. Легковесный Windows, время запуска которого исчисляется секундами (~5).
    Итак, итоговое решение:
    1. Хостинг – облачный. Имеет API, можно динамически, программно, наращивать ноды, если на сервер придут тысячи человек и начнут играть. Также динамически можно их отключать.
    2. Нода поднимается с шаблона. В шаблоне – Windows, Git, VirtualBox и скрипт. Скрипт выкачивает последнюю версию исполняемых файлов с репозитория и запускает сервис.
    3. Сервис стартует, поднимает VirtualBox, ищет на нем шаблонную виртуальную машину и в зависимости от конфигурации, клонирует ее в нескольких экземплярах. Машина – предварительно настроенная, с интерпретаторами PHP, Perl, Python, Ruby, Lua, а также — Java, .Net Framework 3.5 версии. Windows 7 64bit.
    4. Начинает слушать очередь команд.
    5. Когда приходит команда, она парсится, на свободную вирт машину, закачивается скрипт или EXE файл игрока, запускается. На решение задачи отводится 30 секунд. По истечении времени либо когда процесс завершится, файл output.log, в который пишется OUTPUT поток программы копируется на хост машину и виртуальная машина сбрасывается в исходное состояние, откатываясь на последний снапшот.
    6. Результаты уходят в браузер.


    На данный момент можно говорить о следующих результатах нашей работы:
    1. Единственное, что нам не нравится – это размер образа виртуальной машины. На рабочей станции клонирование 4 Гб образа на пять нод занимает порядка 20-30 минут. При исправлении бага – это было бы кошмарное время. Поэтому наличие готового агента на стороне гостевой виртуальной машины и наличие стабильных версий интерпретаторов – это отдельный жирный плюс. Это в какой-то степени гарантирует бесперебойность работы гостевой машины. Как будет вести себя в облаке – скоро нагрузим и узнаем;
    2. Полное время, которое занимает весь путь от браузера в виртуальную машину, запуск, ожидание окончания и обратно – в виде логов (с учетом отката гостевой машины до исходного состояния), занимает 4 секунды при загрузке в 20% CPU максимум. Это отличный результат. Т.е. при запуске сервера, на котором будет крутиться 5 вирт машин, мы сможем обрабатывать до 75 проверок заданий в минуту. Т.е., можно предположить, что отделаться можно и одним сервером. Второй будет работать, на всякий случай. И третий, если отключится (а вдруг!) один из двух.
    3. Мы не стали делать валидацию почтовых адресов при подписке по простой причине: во-первых если будут вводить левые адреса, почта все равно людям придет. Второе — зачем рассылать спам о том что вы, типа, подписались, если можно это просто написать на экране? И третье: зачем заставлять людей лезть в почтовый ящик удалять этот спам?:)


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

    Luxoft
    80.03
    think. create. accelerate.
    Support the author
    Share post

    Comments 36

      +3
      На топкодере используется следующая полезная идея: вместо того, чтобы писать ответ в файл и считывать данные из файла, все данные передаются по сети. В результате нет никаких ограничений на форму задачи — она может быть интерактивной. Это может быть проще, чем забирать файл с виртуальной машины. Кроме того, в таком случае уменьшается влияние IO и времени старта программы на замер времени вычислений.
        +1
        Если мы в следующем году соберемся, то тоже применим эту схему, потому как есть много идей на задачки, не input-output типа, а именно интерактивные. Сейчас задача стояла — отточить heavy-load решение, не усложняя решение.
          0
          Можно писать в файл, расположенный на samba share. Тогда он и по сети передастся, и ввод-вывод будет через ФС.
        +2
        Довольно элегантное решение — писать заголовки в картинках :)
          0
          Вы меня извините, но такое ощущение, что рекламируются продукты Microsoft, потому что стиль заголовков сразу же ассоциируется с новым Метро дизайном :)
            0
            Никакого отношения к ним не имеем :) А заголовки… Просто так, нам кажется, красивее. Шрифт долго выбирали :)
              +1
              Насчёт красоты, согласен, очень даже.
                +1
                Но зачем?
                Чтобы тот, кто читает из какого-нибудь агрегатора или в браузере без картинок не мог увидеть заголовок? Обычные заголовки так плохи?
              0
              Извиняюсь, но мой гугло-аккаунт ни в какую не хочет проходить валидацию :(
                0
                P.S. Я имею ввиду напоминалку о запуске игры.
                  0
                  Напишите его, пожалуйста, в личку, а мы добавим, видимо, отсутствующее правило, в валидатор :) Извините за неудобства, пожалуйста.
                0
                Хорошее дело, успехов!

                А Haskell можно? У него есть и интерпретатор, и компилятор, на Windows работает вполне, только библиотеки разные туда нужно еще доставить. Какие — вопрос отдельный.
                  +1
                  Можно, конечно, включим в дистрибутив!
                    0
                    Замечательно, спасибо!
                      0
                      Хотелось бы еще видеть Common Lisp, раз уж хаскель разрешили. Сам никогда на винде его не пробовал, но ходят слухи что можно.
                    0
                    а у меня чисто технический вопрос — как вы VirtualBox на винде поднимали в качестве сервиса?
                      0
                      он и так в виде сервиса работает. gui всего лишь фронт-енд к нему.
                        0
                        если вы про VBoxHeadless то я не могу понять как его запустить _до_ логина пользователя. перепробовал уже кучу утилити, в т.ч. sc.exe из комплекта windows server 2008 r2, но не получил нужного результата, а именно: запустить виртуальную машину в полностью автоматическом режиме после загрузки системы, но до логина какого-либо пользователя.

                          0
                          Я не пробовал, у нас для управления им написан свой сервис, который управляет ими через COM интерфейс ))
                            0
                            а вы его в public выкладывать не планируете?
                              0
                              Смысла особого не вижу. Он может понадобиться только для того чтобы повторить реализацию квеста, т.к. он заточен под решение этой задачи. Больше ни для чего другого его не использовать. Попробуйте задать вопрос на stackoverflow.com, там отвечают очень оперативно )
                                0
                                на stackexchange я смотрел подобные вопросы. нашёл только что был такой проект, но из-за того что в VB часто меняют API они его забросили.
                            0
                            psix048.blogspot.com/2012/02/virtualbox-windows.html
                            Не знаю, как на 2008, а на 2003 это у нас работает. На Win7 тоже проверял.
                        0
                        Я правильно понимаю, что каждый запуск игры требует: 1) загрузить windows, 2) непосредственно запустить игру, 3) выключение игры, 4) откатывание до снапшота? Сколько же это занимает времени?
                          +2
                          Не совсем, винда ставится на паузу в рабочем состоянии. Откат идет на уже рабочий вариант
                            0
                            Хорошо. (Не знал такой возможности, нужно будет поковыряться, спасибо за информацию) И всё-таки вы не ответили на последний вопрос — сколько времени затрачивается на обработку одной игры?
                              0
                              от 4-х секунд в минимальной до 20 в максимальной нагрузке :) Но мы будем стараться сократить время до 10 в максимуме :)
                          +1
                          Замечательно, что геймификация всё больше внедряется в нашу жизнь! Не сочтите за рекламу, скорее за предложение к сотрудничеству, возможно вам на будущее пригодится конструктор квестов из бизнес-инкубатора ИТ-парка. Запустимся где-то через месяц.
                            0
                            интересная идея :) вы депенгуете фрилансеров :)
                          • UFO just landed and posted this here
                            • UFO just landed and posted this here
                                0
                                Висит на «Ожидание очереди» уже час.
                                • UFO just landed and posted this here
                                  0
                                  Не могу программку загрузить в «Задаче Марины», уже даже с телефона пробовал(
                                    0
                                    Каким браузером пользуетесь? предлагаю перевести переписку в luxquest@gmail.com
                                    0
                                    Оппа… Игра началась 10го числа, а напомнимания о начале до сиз пор нет.
                                    Регистрация не работает — зачем вводить телефон если на него не ничего не приходит уже не пару минут а 24 часа прошло?
                                    Никаких контактов для связи с «админами».
                                    Вот тебе «отличная» органиция

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