Когда мы с Брайаном впервые начали этот блог, я написал о нескольких методах развертывания приложений Ruby в Windows Azure . Существует новый способ развертывания, о котором я хотел рассказать, прежде чем продолжить тестирование Ruby Applications в Windows Azure, поскольку этот новый метод развертывания станет основой для следующих нескольких публикаций в этой строке.
Осенью Windows Azure добавила новую функцию, которая позволила вам указать точку входа для роли в файле ServiceDefinition.csdef. Это означает, что вы можете напрямую указать исполняемый файл или скрипт, который вы хотите запустить, вместо того, чтобы создавать оболочку .NET. Стив Маркс создал пример использования этого для запуска Python в Windows Azure ( https://github.com/smarx/pythonrole ,), который я адаптировал в качестве примера запуска Ruby в Windows Azure. Вы можете найти пример проекта по адресу https://github.com/Blackmist/rubyrole .
Один небольшой недостаток этого примера; требуется доступ к машине с Windows. Это связано с тем, что он использует утилиты, предоставляемые в составе Windows Azure SDK . Любая из перечисленных версий SDK, вероятно, должна работать, но я тестировал только с «Other» и «.NET» версиями SDK.
Вот краткий обзор того, как работает этот образец.
ServiceDefinition.csdef
Файл ServiceDefinition определяет порты, используемые этой ролью, хранилище файлов для каждого экземпляра, пользовательские переменные среды, задачи запуска и, наконец, команду для запуска в качестве точки входа программы для этой роли. В частности, он делает следующее:
- Определяет общедоступный TCP-порт 80, который называется HttpIn
- Определяет локальное хранилище для экземпляра с именем ‘ruby’
- Определяет следующие задачи запуска:
- installRuby.cmd — устанавливает Ruby с RubyInstaller.org
- installDk.cmd — устанавливает DevKit с RubyInstaller.org
- installDependencies.cmd — устанавливает Bundler, а затем запускает «комплектную установку» для установки любых драгоценных камней, перечисленных в Gemfile.
- Определяет точку входа приложения — run.cmd
Обратите внимание, что все указанные файлы .cmd находятся в подкаталоге \ WorkerRole этого примера. Путь не указан в записях файла ServiceDefinition.
Ресурсы ‘HttpIn’ и ‘ruby’, размещенные в этом файле, обычно доступны только для приложений .NET, однако мы можем представить их как переменные среды. HttpIn запрашивается и используется для создания переменных среды ADDRESS и PORT, а полный физический путь к хранилищу, выделенному для ‘ruby’, хранится в переменной среды RUBY_PATH. Существует также переменная среды EMULATED, которая используется для определения, запущен ли проект в эмуляторе Windows Azure или в Windows Azure.
Во время инициализации роль выделит хранилище, назовет его «ruby» и откроет порт 80, как указано в «HttpIn». Затем он запустит команды запуска. После того, как они завершены, он запустит «run.cmd» для запуска приложения.
Вот интересные части файла ServiceDefinition. Полный список файлов см. По адресу https://github.com/Blackmist/rubyrole/blob/master/ServiceDefinition.csdef .
Определение порта
<Endpoints> <InputEndpoint name="HttpIn" protocol="tcp" port="80" /> </Endpoints>
LocalStorage для каждого экземпляра
<LocalResources> <LocalStorage name="ruby" cleanOnRoleRecycle="true" sizeInMB="1000" /> </LocalResources>
InstallRuby.cmd Задача запуска
Обратите внимание, что это определяет не только командную строку для запуска, но и переменные среды, создаваемые для этой задачи.
<Task commandLine="installRuby.cmd" executionContext="elevated"> <Environment> <Variable name="EMULATED"> <RoleInstanceValue xpath="/RoleEnvironment/Deployment/@emulated" /> </Variable> <Variable name="RUBY_PATH"> <RoleInstanceValue xpath="/RoleEnvironment/CurrentInstance/LocalResources/LocalResource[@name='ruby']/@path" /> </Variable> </Environment> </Task>
RUBY_PATH Определение переменной
<Variable name="RUBY_PATH"> <RoleInstanceValue xpath="/RoleEnvironment/CurrentInstance/LocalResources/LocalResource[@name='ruby']/@path" /> </Variable>
Точка входа в приложение
<EntryPoint> <ProgramEntryPoint commandLine="run.cmd" setReadyOnProcessStart="true" /> </EntryPoint>
ServiceConfiguration.Cloud.csfg и ServiceConfiguration.Local.csfg
Файл ServiceConfiguration указывает параметры конфигурации службы, например количество экземпляров, создаваемых для вашей роли. Это все, что я действительно указал на данный момент, однако этот файл также можно использовать для включения функций удаленного рабочего стола для развертывания, а также для диагностики. В настоящее время единственным важным значением здесь является количество экземпляров, которое равно 2 для облака и 1 для локального.
Почему 2 для облака? Потому что для гарантии SLA от Microsoft требуется как минимум два экземпляра роли. Если один из них отключен из-за аппаратного сбоя, балансировки ресурсов и т. Д., У вас по-прежнему работает другой. Если для локального счетчика установлено значение 1, то при тестировании с использованием эмулятора Windows Azure на локальном компьютере мы запускаем только один экземпляр.
Облачная версия этого файла используется при развертывании в облаке, а локальная версия используется эмулятором. Вот облачная версия в качестве примера:
<?xml version="1.0"?> <ServiceConfiguration xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" serviceName="RubyRole" xmlns="http://schemas.microsoft.com/ServiceHosting/2008/10/ServiceConfiguration" osFamily="2" osVersion="*"> <Role name="WorkerRole"> <ConfigurationSettings /> <Instances count="2" /> </Role> </ServiceConfiguration>
Приложение
Приложение находится в каталоге / WorkerRole / app. Для этого примера это просто базовое приложение Sinatra (app.rb) следующим образом:
require 'sinatra' set :server, :thin set :port, ENV['PORT'] set :bind, ENV['ADDRESS'] get '/' do "Hello World!" end
Важно отметить, что при этом используются переменные среды PORT и ADDRESS, чтобы определить порт и адрес для прослушивания. Если вы посмотрите на файл ServiceDefinition.csfg, эти переменные среды будут заполнены там на основе конечной точки HttpIn. Использование этих двух переменных среды позволяет приложению правильно работать в зависимости от того, запущено ли оно в эмуляторе (который может переназначить порт, если у вас уже есть что-то на порту 80), или в Windows Azure.
Типичный рабочий процесс
При использовании этого типичный рабочий процесс:
- Создайте новое веб-приложение в каталоге / WorkerRole / app.
- Сделайте любые изменения, необходимые для ‘/WorkerRole/run.cmd’, чтобы запустить приложение. Например, ‘call rails s’ вместо ‘ruby app.rb’.
- Запустите файл run.cmd из каталога / rubyrole. Это запустит приложение в эмуляторе Windows Azure.
- После того, как все работает как нужно, запустите «pack.cmd» из каталога «/ rubyrole», чтобы создать пакет развертывания «RubyRole.cspkg».
- Перейдите на Windows.Azure.com и войдите в свою подписку, затем создайте новую размещенную службу. Используйте RubyRole.cspkg в качестве файла пакета и ServiceConfiguration.Cloud.csfg в качестве файла конфигурации.
Файлы pack.cmd и run.cmd в каталоге / rubyrole зависят от утилит cspack.exe и csrun.exe, установленных Windows Azure SDK. Cspack.exe упаковывает папку «/ WorkerRole» в пакет развертывания, а csrun.exe запускает пакет в эмуляторе Windows Azure. Вот код для обоих:
pack.cmd
@echo off if "%ServiceHostingSDKInstallPath%" == "" ( echo Can't see the ServiceHostingSDKInstallPath environment variable. Please run from a Windows Azure SDK command-line (run Program Files\Windows Azure SDK\^<version^>\bin\setenv.cmd^). GOTO :eof ) cspack ServiceDefinition.csdef /out:RubyRole.cspkg
run.cmd
@echo off if "%ServiceHostingSDKInstallPath%" == "" ( echo Can't see the ServiceHostingSDKInstallPath environment variable. Please run from a Windows Azure SDK command-line (run Program Files\Windows Azure SDK\^<version^>\bin\setenv.cmd^). GOTO :eof ) cspack ServiceDefinition.csdef /copyOnly /out:RubyRole.csx csrun RubyRole.csx ServiceConfiguration.Local.cscfg if "%ERRORLEVEL%"=="0" ( echo Browse to the port you see above to view the app. To stop the compute emulator, use "csrun /devfabric:shutdown" )
Задачи запуска
Я не собираюсь перечислять источник для всех задач запуска здесь, но я хочу назвать конкретную вещь, о которой нужно знать. Дело в том, что когда вы запускаете приложение с помощью команды run.cmd для запуска приложения в эмуляторе Windows Azure, оно фактически использует локальную копию Ruby, установленную на вашем компьютере, вместе с установленными вами драгоценными камнями. Поэтому важно, чтобы эти задачи запуска были выполнены так, чтобы они не загромождали ваши установки при запуске в эмуляторе.
Это цель переменной среды EMULATED; он будет существовать только при запуске в эмуляторе. Вот источник для installRuby.cmd, обратите внимание, что первое, что мы делаем, это проверяем, существует ли EMULATED, и выходим, чтобы предотвратить переустановку Ruby на вашем локальном компьютере.
REM Skip Ruby install if we're running under the emulator if "%EMULATED%"=="true" exit /b 0 REM Strip the trailing backslash (if present) if %RUBY_PATH:~-1%==\ SET RUBY_PATH=%RUBY_PATH:~0,-1% cd /d "%~dp0" REM Download directly from rubyinstaller.org powershell -c "(new-object System.Net.WebClient).DownloadFile('http://rubyforge.org/frs/download.php/75465/rubyinstaller-1.9.3-p0.exe', 'ruby.exe')" REM Install Ruby and DevKit start /w ruby.exe /verysilent /dir="%RUBY_PATH%" REM Ensure permissive ACLs so other users (like the one that's about to run Ruby) can use everything. icacls "%RUBY_PATH%" /grant everyone:f icacls . /grant everyone:f REM Make sure Ruby was installed properly (will produce a non-zero exit code if not) "%RUBY_PATH%\bin\ruby" --version
Резюме
Мы дошли до того, что можем развертывать приложения Ruby в Windows Azure, не требуя Visual Studio .NET и оболочки .NET, но нам все еще требуется система Windows для этого подхода. Надеемся, что у нас будет решение для разработки и развертывания из систем, отличных от Windows, однажды.
На следующей неделе я покажу, как использовать этот пример для запуска тестов Ruby в Windows Azure.