Статьи

Легкое развертывание PHP-приложения в Windows Azure

Те из вас, кто развертывает приложения PHP в Windows Azure, вероятно, используют инструментарий Windows Azure для Eclipse или фантастические доступные инструменты командной строки . Я дам вам третий вариант, который позволяет выполнить настройку на 100% и является гораздо более легким, чем описанные выше. Конечно, если вы хотите использовать готовые функции этих инструментов, придерживайтесь их.

Примечание: хотя этот пост предназначен для разработчиков PHP, он также показывает, как создать собственный .cspkg с нуля для любого другого языка. Это касается и вас, .NET и Ruby!

О, моя подсветка синтаксиса не работает, так что вы не увидите никаких необычных цветов в этом посте 🙂

Этап 1. Создание базового шаблона пакета

Каждый пакет Windows Azure — это пакет OpenXML, содержащий ваше приложение. Для тех, кто не любит модный жаргон: это специальный ZIP-файл. Фактом является то, что он содержит точную копию структуры папок, которую вы можете создать самостоятельно. Все, что нужно, это создать следующую структуру папок и файлов:

  • ServiceDefinition.csdef
  • ServiceConfiguration.cscfg
  • PhpOnAzure.Web

    • бункер
    • Ресурсы
    • Web.config

Я пойду через каждый из них. Прежде всего, файл ServiceDefinition.csdef — это метаданные, описывающие ваше развертывание Windows Azure. Он (может) содержать следующий XML:

<?xml version="1.0" encoding="utf-8"?>
<ServiceDefinition name="PhpOnAzure" xmlns="http://schemas.microsoft.com/ServiceHosting/2008/10/ServiceDefinition">
  <WebRole name="PhpOnAzure.Web" enableNativeCodeExecution="true">
    <Sites>
      <Site name="Web" physicalDirectory="./PhpOnAzure.Web">
        <Bindings>
          <Binding name="Endpoint1" endpointName="HttpEndpoint" />
        </Bindings>
      </Site>
    </Sites>
    <Startup>
      <Task commandLine="add-environment-variables.cmd" executionContext="elevated" taskType="simple" />
      <Task commandLine="install-php.cmd" executionContext="elevated" taskType="simple" />
    </Startup>
    <Endpoints>
      <InputEndpoint name="HttpEndpoint" protocol="http" port="80" />
    </Endpoints>
    <Imports>
      <Import moduleName="Diagnostics"/>
    </Imports>
    <ConfigurationSettings>
    </ConfigurationSettings>
  </WebRole>
</ServiceDefinition>

По сути, он сообщает Windows Azure о создании WebRole с именем «PhpOnAzure.Web» (обратите внимание на несовпадение совпадений с одним каталогом структуры папок, описанным ранее). Он будет содержать один сайт, который прослушивает HttpEndpoint (порт 80). Затем я добавил 2 задачи запуска: add-environment-variables.cmd и install-php.cmd. Подробнее об этом позже.

Затем ServiceConfiguration.cscfg — это файл фактической конфигурации для вашего развертывания Windows Azure. Это выглядит так:

<?xml version="1.0" encoding="utf-8"?>
<ServiceConfiguration serviceName="PhpOnAzure" xmlns="http://schemas.microsoft.com/ServiceHosting/2008/10/ServiceConfiguration" osFamily="2" osVersion="*">
  <Role name="PhpOnAzure.Web">
    <Instances count="1" />
    <ConfigurationSettings>
      <Setting name="Microsoft.WindowsAzure.Plugins.Diagnostics.ConnectionString" value="<your diagnostics connection string here>"/>
    </ConfigurationSettings>
  </Role>
</ServiceConfiguration>

Как и в развертывании WIndows Azure на основе инструментария, он позволяет задавать детали конфигурации, например строку подключения, в которую монитор диагностики должен записывать все журналы.

PhpOnAzure.Web папка является фактическим корень , где моя веб — приложение будет жить. Это wwwroot вашего приложения, папка htdocs вашего приложения. Пока не размещайте здесь никакого содержимого n, поскольку мы автоматизируем это позже в этом посте. В любом случае, он (необязательно) содержит файл Web.config, где я указываю, что index.php должен быть документом по умолчанию:

<?xml version="1.0"?>
<configuration>
  <system.webServer>
    <defaultDocument>
      <files>
        <clear />
        <add value="index.php" />
      </files>
    </defaultDocument>
  </system.webServer>
</configuration>

Все еще в порядке? Хороший! (Я не буду принимать нет за ответ :-)). Добавьте туда папку bin и папку ресурсов . Папка bin будет содержать наши задачи запуска (см. Ниже), папка resources будет содержать копию инструментов командной строки установщика веб-платформы.

Это оно! Пакет развертывания Windows Azure на самом деле довольно прост и его легко создать самостоятельно.

Этап 2. Автоматическая установка среды выполнения PHP

Я должен признать: это украдено у превосходного канадского Windows Azure MVP Кори Фаулера, известного как SyntaxC4 . Он писал об использовании задач запуска и инструмента командной строки WebPI для автоматической установки PHP при загрузке виртуальной машины Windows Azure. Прочитайте его пост для более подробной информации, я просто расскажу об этой задаче. Который я беззастенчиво скопировал и из его блога. Кредиты причитаются.

Под PhpOnAzure.Web \ bin добавьте скрипт с именем install-php.cmd и скопируйте следующий код:

    @echo off
    ECHO "Starting PHP installation..." >> ..\startup-tasks-log.txt

    md "%~dp0appdata"
    cd "%~dp0appdata"
    cd ..

    reg add "hku\.default\software\microsoft\windows\currentversion\explorer\user shell folders" /v "Local AppData" /t REG_EXPAND_SZ /d "%~dp0appdata" /f
    "..\resources\WebPICmdLine\webpicmdline" /Products:PHP53 /AcceptEula  >> ..\startup-tasks-log.txt 2>>..\startup-tasks-error-log.txt
    reg add "hku\.default\software\microsoft\windows\currentversion\explorer\user shell folders" /v "Local AppData" /t REG_EXPAND_SZ /d %%USERPROFILE%%\AppData\Local /f

    ECHO "Completed PHP installation." >> ..\startup-tasks-log.txt

Что это делает:

  • Создать локальную папку данных приложения
  • Добавьте это имя папки в реестр
  • Вызовите «webpicmdline» и установите PHP 5.3.x. И, конечно, / AcceptEula гарантирует, что вам не нужно заходить в центр обработки данных Windows Azure, разбивать контейнер и нажимать «Я принимаю» на экране вашей виртуальной машины.
  • Происходит удивительность: PHP 5.3.x установлен!
  • И все попадает в файл startup-tasks-error-log.txt в корне вашего сайта. Это позволяет вам проверять вывод всех этих команд после загрузки вашей виртуальной машины.

Этап 3: Исправление проблемы

Пока только солнышко. Но … Так как здесь используется метод создания веб-роли с полным IIS (что хорошо), существует небольшая проблема… Обычно ваша веб-роль раскручивает размещенное в IIS ядро ​​и запускается в том же процессе, который запускал виртуальную машину в первое место. В обычной веб-роли процесс размещения содержит несколько интересных переменных среды, касающихся вашего развертывания: идентификатор развертывания, имя роли и даже имя экземпляра!

С полным IIS ваша веб-роль выполняется внутри IIS. Настоящий IIS, верно. И этот процесс отличается от того, который запустил вашу виртуальную машину, что означает, что эти полезные переменные среды недоступны для вашего приложения. Это не проблема для многих приложений, но если вы используете диспетчер диагностики на основе PHP из Windows Azure SDK для PHP (или другой код, который зависит от этих переменных среды, то вы… беда.

К счастью, задачи запуска имеют доступ к сборкам Windows Azure, которые также могут предоставить вам эту информацию. Так почему бы не создать задачу, которая копирует эту информацию в переменную окружения машины?

Нам понадобятся два сценария: один .cmd файл, запускающий PowerShel, и, конечно, PowerShell. Давайте начнем с файла с именем add-environment-variables.cmd в папке PhpOnAzure.Web \ bin :

    @echo off
    ECHO "Adding extra environment variables..." >> ..\startup-tasks-log.txt

    powershell.exe Set-ExecutionPolicy Unrestricted
    powershell.exe .\add-environment-variables.ps1 >> ..\startup-tasks-log.txt 2>>..\startup-tasks-error-log.txt

    ECHO "Added extra environment variables." >> ..\startup-tasks-log.txt

Ничего особенного, как и обещали, мы запускаем PowerShell. Но для того, чтобы у нас были все возможные варианты в PowerShell, сначала для политики выполнения устанавливается Unrestricted . Затем запускается add-environment-variables.ps1 :

    [Reflection.Assembly]::LoadWithPartialName("Microsoft.WindowsAzure.ServiceRuntime")

    $rdRoleId = [Environment]::GetEnvironmentVariable("RdRoleId", "Machine")

    [Environment]::SetEnvironmentVariable("RdRoleId", [Microsoft.WindowsAzure.ServiceRuntime.RoleEnvironment]::CurrentRoleInstance.Id, "Machine")
    [Environment]::SetEnvironmentVariable("RoleName", [Microsoft.WindowsAzure.ServiceRuntime.RoleEnvironment]::CurrentRoleInstance.Role.Name, "Machine")
    [Environment]::SetEnvironmentVariable("RoleInstanceID", [Microsoft.WindowsAzure.ServiceRuntime.RoleEnvironment]::CurrentRoleInstance.Id, "Machine")
    [Environment]::SetEnvironmentVariable("RoleDeploymentID", [Microsoft.WindowsAzure.ServiceRuntime.RoleEnvironment]::DeploymentId, "Machine")


    if ($rdRoleId -ne [Microsoft.WindowsAzure.ServiceRuntime.RoleEnvironment]::CurrentRoleInstance.Id) {
        Restart-Computer
    }

    [Environment]::SetEnvironmentVariable('Path', $env:RoleRoot + '\base\x86;' + [Environment]::GetEnvironmentVariable('Path', 'Machine'), 'Machine')

Вот это да! Много кода? Да. Прежде всего, мы загружаем сборку Microsoft.WindowsAzure.ServiceRuntime . Затем мы запрашиваем переменные текущей среды для переменной с именем RdRoleId и копируем ее в переменную с именем $ rdRoleId . Затем мы устанавливаем для всех переменных среды ( RdRoleId, RoleName, RoleInstanceID, RoleDeploymentID ) их фактические значения. Просто так. Разве PowerShell не крутая вещь?

После всего этого переменная $ rdRoleId сравнивается с текущей переменной среды RdRoleId . Они одинаковы? Хороший! Они разные? Перезагрузите экземпляр. Перезагрузка экземпляра — единственный простой способ для IIS и PHP поднять эти новые значения.

Этап 4: Автоматизация упаковки

Осталось сделать одну вещь: у нас сейчас есть структура папок, но я не вижу ни одного файла .cspkg для развертывания… Давайте это исправим. создавая старый добрый пакетный файл, который делает упаковку для нас. Обратите внимание, что это * не * необходимая часть, но она облегчит вашу жизнь. Вот сценарий:

    @echo off

    IF "%1"=="" GOTO ParamMissing

    echo Copying default package components to temporary location...
    mkdir deploy-temp
    xcopy /s /e /h deploy deploy-temp

    echo Copying %1 to temporary location...
    xcopy /s /e /h %1 deploy-temp\PhpOnAzure.Web

    echo Packaging application...
    "c:\Program Files\Windows Azure SDK\v1.4\bin\cspack.exe" deploy-temp\ServiceDefinition.csdef /role:PhpOnAzure.Web;deploy-temp\PhpOnAzure.Web /out:PhpOnAzure.cspkg
    copy deploy-temp\ServiceConfiguration.cscfg

    echo Cleaning up...
    rmdir /S /Q deploy-temp

    GOTO End

    :ParamMissing
    echo Parameter missing: please specify the path to the application to deploy.

    :End

Вы можете вызвать его из командной строки:


пакет c: \ patch-to-my \ app

Это скопирует ваше приложение во временную папку, объединит шаблон, созданный на предыдущих шагах, и создаст файл .cspkg, вызвав файл cspack.exe из Windows Azure SDK и файл ServiceConfiguration.cscfg, содержащий вашу конфигурацию.

Этап 5: Пакет Привет, мир!

Давайте создадим приложение, которое нуждается в массовом масштабе. Вот исходный код файла index.php, который будет обрабатывать все запросы. Поместите его в ваш c: \ temp или куда хотите.

<?php
echo “Hello, World!”;

Далее, вызовите package.ba t, созданный ранее:

    package c:\patch-to-my\app

Там вы идете: PhpOnAzure.cspkg и ServiceConfiguraton.cscfg к вашим услугам. Загрузите, разверните и наслаждайтесь. После загрузки виртуальной машины в Windows Azure будут установлены все переменные среды и автоматически установлен PHP. Не стесняйтесь поиграть с созданным мной шаблоном ( lightweight-php-deployment-azure.zip (854.44 kb) ), так как вы также можете установить, например, расширение Wincache или драйвер SQL Server для PHP из командной строки WebPI. инструменты. Или включите свой собственный PHP дистрибутив. Или достигните мирового господства, установив число экземпляров на очень большое число (конечно, для этого нужно позвонить в Microsoft, если вы хотите выйти за пределы 20 экземпляров, просто чтобы узнать, достойны ли вы мирового господства).

Вывод

Наряду с официально поддерживаемыми инструментами для упаковки, есть и старое доброе ремесленное мастерство. А если вы автоматизируете некоторые детали, вам будет очень легко упаковать ваше приложение в очень легкую форму. Наслаждайтесь!

Вот загрузка: lightweight-php-deployment-azure.zip (854,44 кб)