Быстрая автоматическая установка Ruby on Rails на IIS 7

Популярность фреймворка Ruby on Rails постоянно растет, общество становится шире и, если раньше об использовании Ruby на Windows говорилось редко, то сегодня это вполне реальная практика.

Такие проекты как RubyInstaller (http://rubyinstaller.org/) и RailsInstaller (http://railsinstaller.org/) значительно упрощают создание рабочей среды на Windows. Вы можете использовать нативный MRI 1.8 и 1.9, JRuby или даже IronRuby работающий на .NET. С Windows работает большинство gem-пакетов, причем благодаря DevKit (https://github.com/oneclick/rubyinstaller/wiki/Development-Kit) «сишные» джемы можно собирать прямо из исходников. 

Однако, несмотря на активное развитие средств разработки, до сих пор Windows и в частности веб-сервер IIS практически не использовались как «продакшн» решение для развертки Rails приложений. Но с появлением нового инструмента Helicon Zoo на базе Web Platform Installer – эта ситуация поменялась.

Helicon Zoo

Helicon Zoo – это репозиторий веб фреймворков и приложений, позволяющий легко устанавливать и запускать Rails, Django (фактически любые rack, wsgi или FastCGI приложения) и Mojolicious на веб-сервере IIS.

Helcon Zoo использует Microsoft Web Platform Installer (https://www.microsoft.com/web/downloads/platform.aspx). Это репозиторий и среда развертывания веб приложений и фреймворков от Microsoft, которая уже содержит в себе множество ASP.NET и PHP приложений. Для реализации функционала понадобилось лишь создать собственный feed с продуктами, чтобы пользователи получили возможность удобной и простой установки из репозитория. 

Однако просто добавить продукты в репозиторий недостаточно. Ядром Helicon Zoo является native IIS модуль, по сути, играющий роль моста между веб-сервером IIS и фреймворками на Ruby, Python и Perl и др. Модуль работает по протоколу FastCGI, который уже зарекомендовал себя как надежный и быстрый метод взаимодействия с веб сервером. Ввод-вывод обрабатывается асинхронно, используя технологию IOCP. В качестве транспорта используются именованные каналы либо сокеты. В ближайшее время разработчиками планируется полностью реализовать поддержку асинхронного FastCGI (к сожалению ни один из существующих на данный момент фреймворков асинхронный FastCGI не поддерживает). 

Поддерживаются IIS 7, IIS 7.5, а также IIS Express.

Устанавливаем Ruby on Rails

Скачайте Web Platform Installer (https://www.microsoft.com/web/downloads/platform.aspx) и запустите его. В появившемся окне нажмите «Options»: 

В опциях необходимо добавить ссылку на feed Helicon Zoo: www.helicontech.com/zoo/feed/ 

Теперь если выбрать вверху «Application» а в меню слева перейти на «Tools», вы увидите новые приложения: «Blank Ruby on Rails Project», «Blank Django Project», «Blank Perl Project» и «Blank Mojolicious Project»: 

Это пустые «Hello World» заготовки, которые устанавливают необходимые зависимости для дальнейшей разработки. 

Нажмите на кнопку «Add» напротив «Blank Ruby on Rails Project», а затем на кнопку «Install». 

Инсталлятор предложит установить следующие зависимости: 

После нажатия на кнопку «I Accept» нужные пакеты будут загружены и установлены, после чего вам будет предложено настроить сайт для нового приложения. 

Вы можете создать новый сайт либо выбрать существующий: 

Когда установка и настройка закончены, приложение готово к запуску: 

Под капотом

После установки «Blank Ruby on Rails Project» web.config файл для выбранного IIS-сайта выглядит следующим образом: 

<?xml version="1.0" encoding="UTF-8"?> 

<configuration>

<system.webServer>

<handlers>

<add name="rails.project.x86" scriptProcessor="ruby.1.9.pipe" path="*" verb="*" modules="HeliconZoo_x86" preCondition="bitness32" resourceType="Unspecified" requireAccess="Script" />

<add
 name="rails.project.x64" scriptProcessor="ruby.1.9.pipe" path="*" verb="*" modules="HeliconZoo_x64" preCondition="bitness64" resourceType="Unspecified" requireAccess="Script" />

</handlers>

</system.webServer>

</configuration>


По умолчанию в качестве транспорта между IIS-модулем и воркером Ruby on Rails используются именованные каналы. Чтобы использовать сокеты, достаточно заменить параметр «scriptProcessor» на «ruby.1.9.tcp». 

Все доступные скрипт-процессоры описаны в секции <heliconZooServer> файла applicationHost.config

Через web.config также можно влиять на работу Rails-приложения. Так, например, по умолчанию оно запускается в отладочном режиме (RAILS_ENV = development). Чтобы переключиться в продакшн режим, вы можете установить переменную RACK_ENV следующим образом: 

<?xml version="1.0" encoding="UTF-8"?>

<configuration>

<system.webServer>

<heliconZoo>

<application name="rails.project.x64" >

<environmentVariables>

<add
 name="RACK_ENV" value="production" />

</environmentVariables>

</application>

</heliconZoo>


Секция <heliconZoo> в файле web.config используется в основном для установки переменных окружения при вызове воркера. По сути, через секцию <environmentVariables> вы можете передавать в приложение любые необходимые параметры. В руби они будут доступны через глобальный хэш «ENV».

Что дальше?

Работа над проектом Helicon Zoo ведется очень активно, компания-разработчик HeliconTech будет рада любым замечаниям и предложениям. На данный момент готовиться обновленная версия, в которой будет поддержка MRI 1.8, JRuby, а также Rails 2.3. 

Коллекция «Blank» заготовок в скором времени будет расширена другими руби-фреймворками в частности Sinatra и готовыми приложениями, такими как RedMine и другие.

<engine name="python.2.7.pipe" fullPath="c:\python27\python.exe" arguments="-O %SystemDrive%\Zoo\Workers\python\zoofcgi.py" transport="pipe" />

Web.config

Конфигурация веб-приложений, работающих через Zoo осуществляется через файл web.config. Вот пример такого файла для конфигурирования Django-приложения для работы в 32-битном пуле:

<?xml version="1.0" encoding="UTF-8"?> <configuration> <system.webServer> <heliconZoo> <application name="django.project.x86" > <environmentVariables> <add name="PYTHONPATH" value="%APPL_PHYSICAL_PATH%;%PYTHONPATH%" /> <add name="DJANGO_SETTINGS_MODULE" value="settings" /> <add name="DEPLOY_FILE" value="deploy.py" /> <add name="DEPLOY_LOG" value="log\deploy.log" /> </environmentVariables> </application> </heliconZoo> <handlers> <add name="django.project.x86" scriptProcessor="python.2.7.pipe" path="*" verb="*" modules="HeliconZoo_x86" preCondition="bitness32" resourceType="Unspecified" requireAccess="Script" /> </handlers> </system.webServer> </configuration>

Вот важные моменты:

  • scriptProcess="python.2.7.pipe" — ссылка на FastCGI-движок определенный в applicationHost.config;
  • переменная окружения PYTHONPATH — путь, по которым python ищет свои модули; в нашем случае мы добавляем в PYTHONPATH путь к нашему django-приложению;
  • переменная окружения DJANGO_SETTINGS_MODULE — питоний путь к конфигурационному файлу settings.py Django-приложения, например, ‘mysite.settings’
  • переменная окружения ‘DEPLOY_FILE’ — путь к файлу внутри приложения, который будет запускаться перед выполнением первого запросу к приложению после рестарта IIS-приложения. В этом файле нужно выполнять, например, команды для синхронизации БД: ‘manage.py syncdb –noinput’;
  • переменная окружения ‘DEPLOY_LOG’ — путь внутри приложения к файлу, в который будет записываться вывод команды DEPLOY_FILE для отладочных целей. Директория, в которой находится этот лог-файл, должна иметь права на запись для пользователя, от которого работает IIS-приложение (обычно группа IIS_IUSRS).

Статический контент

орк Django не годится для быстрой и безопасной обработки статических файлов (изображений, скриптов, файлов стилей). Статику должен обрабатывать веб-сервер напрямую. Для этого нужно сложить все статические файлы в директорию и выключить в ней обработчик запросов в django-приложение:

<?xml version="1.0" encoding="UTF-8"?> <configuration> <system.webServer> <handlers> <remove name="django.project.x86" /> </handlers> </system.webServer> </configuration>

Пример Django-проекта на IIS 7

Предположим наш django-проект состоит из трех приложений:

  • site — собственно сам сайт с шаблонами, статикой, urls.py и settings.py
  • blog
  • store

Статические файлы, расположенные в site/media будут доступны через виртуальную директорию /media/ (т.е. MEDIA_URL='/media/'). После установки Blank Django Project в корень сайта и копирования нашего django-проекта, получим такую структуру директорий:

/media/ — это виртуальная директория, которая указывает на site/media; в ней отключен Zoo модуль как описано выше. В корневом web.config PYTHONPATH указывает на корень сайта и DJANGO_SETTINGS_MODULE установлен в ‘site.settings’:

... <heliconZoo> <application name="django.project.x86" > <environmentVariables> <add name="PYTHONPATH" value="%APPL_PHYSICAL_PATH%" /> <add name="DJANGO_SETTINGS_MODULE" value="site.settings" /> </environmentVariables>

Производительность

И напоследок самое интересное – тестирование производительности. Развернутое тестирование будет позже, сейчас пока «на скорую руку», но и по этим результатам вполне можно судить. Тестовая машина в качестве сервера — Core 2 Quad 2.4 Ghz, 8 Gb RAM, гигабитная сеть. Для генерации нагрузки использовался более мощный компьютер с Apache Benchmark. Для тестирования Apache и Nginx использовалась Ubuntu 11.04 Server x64. IIS 7 тесты работали на Windows Server 2008 R2. Никаких виртуалок — честное железо. В качестве транспорта на Nginx использовали самый продвинутый uwsgi, а также wsgi и fast_cgi для сравнения. Еще на IIS 7 сравнили с PyISAPIе.

В качестве тестовых страниц написали два небольших скрипта. Первый выводит текущее время с высоким разрешением – это сделано для того, чтобы была уверенность что, страницы не берутся из кеша. Второй делает то же самое, но предварительно сохраняет результат в базе данных. Все это через шаблон, чтобы задействовать реальную инфраструктуру Django, база данных – MySQL. Настройки везде по умолчанию, т.к. цель протестировать именно наиболее типичные конфигурации. Итак, результаты (в запросах в секунду):

Тут все более менее понятно и стабильно. Uwsgi впереди, видимо за счет более тесной интеграции с кодом Django — нужно будет его покурить… PyISAPIe сильно отстает, что и понятно.

А вот с базой данных результат не столь стабилен. Почему Nginx + fcgi + MySQL показал столь странные 175 запросов в секунду – не понятно. Результат MySQL на Windows тоже удручает, хотя на shared хостинге проблема возможно и не будет такой критичной. Дело в том что производительность падает в основном из-за каких-то внутренних блокировок в MySQL, сам же сервер практически не нагружен, пока генерирует эти 104 запроса. Можно предположить, что с ростом количества сайтов на сервере, и соответственно ростом количества баз данных, если они не будут блокироваться между собой, суммарная мощность сервера будет достаточной. 

Так что мы решили добавить MS SQL Express к тестам. Его результат тоже понятен – все упирается в сам Python и драйвера базы данных к нему, однако в целом выглядит вполне прилично. PyISAPIe с MS SQL Express не заработал.

Хочется отдельно отметить способность IIS 7 держать большое число подключений. Так IIS 7 + Helicon Zoo с легкостью выдерживал тысячи одновременных подключений (больше нам просто нечем было генерировать), в то время как Ubuntu, с настройками по умолчанию, с ростом числа подключений быстро пасовала. А Apache еще и оказался весьма прожорливым на память. Так с ростом числа подключений Apache потребил около 3-х Гб памяти за 20 секунд теста — дальше не проверяли.

Выводы

Представленное решение показывает стабильную работу и приличную производительность. Оно вполне готово для использования как в качестве среды разработки так и в продакшене. Особенно важной является возможность использования Helicon Zoo различными Windows хостингами, с целью предоставления сервисов Django своим клиентам. Хочется надеяться, что с ростом числа Django серверов на Windows, ее разработчики станут уделять больше внимания отладке и оптимизации своего кода под Windows платформу. Да и армия существующих Windows-разработчиков может стать неплохим подспорьем для нынешних open-source проектов.

Автор статьи:Владимир Юнев