しばやん雑記

Azure とメイドさんが大好きなフリーランスのプログラマーのブログ

httpPlatformHandler をもっと面白く使っていきたい

Azure Web サイトが Java に対応した時に同時に追加された httpPlatformHandler ですが、何か面白い使い方があると思うので軽くまとめておきます。

まずはちょっと似てる ARR と httpPlatformHandler の違いから簡単に。

ARR の場合

ARR の役割はリバースプロキシとロードバランサーになるので、基本的には HTTP トラフィックをそのまま別の URL やサーバー群に振り分けます。

Application Request Routing : The Official Microsoft IIS Site

IIS に ARR をインストールすることで、nginx と同じような機能を実現することが出来ます。

httpPlatformHandler の場合

httpPlatformHandler の役割はローカルホストでサーバーを起動し、それに対して HTTP トラフィックを流し込むことです。ARR では柔軟に設定が行えましたが、httpPlatformHandler ではローカルホストで固定です。

説明用に某セミナー用に作った画像を引っ張り出してきました。

f:id:shiba-yan:20141221183536p:plain

ARR と決定的に異なるのが、httpPlatformHandler は指定された実行ファイルのプロセス管理までを行う点です。初回リクエストのタイミングで、httpPlatformHandler は Web.config で指定されているプロセスを起動し、同時にリッスンすべきポート番号を渡します。

この時 HTTP_PLATFORM_PORT 環境変数にポート番号が入っているので、起動されたプロセスではこのポートで接続を待機します。*1

プロセス管理を行うことから FastCGI っぽくも感じますが、通信自体は HTTP そのままです。

出来ること

上の図でも書いてありますが、Java のアプリケーションサーバーや Rack を使ったアプリケーションを、IIS を意識させることなく動作させることが出来ます。


既に Ruby や Go に関しては httpPlatformHandler を使うことで、CGI / FastCGI よりも実用的なパフォーマンスを出せることを確認しています。

あまり意味はないですが、Node.js に関しても iisnode を使うことなく httpPlatformHandler でホスティングが可能です。実際に例を挙げると以下のような Web.config を用意することで、起動するようになります。

<httpPlatform processPath="node.exe d:\home\site\wwwroot\hello.js" arguments="">
  <environmentVariables>
    <environmentVariable name="PORT" value="%HTTP_PLATFORM_PORT%" />
  </environmentVariables>
</httpPlatform>

環境変数 PORT を設定することで、process.env.PORT で実行時のポート番号を取れるようにできます。

出来ないこと

ARR を使った場合とは異なり、httpPlatformHandler はポートが 1 つで固定なため SSL なトラフィックは全てオフロードされて渡されます。つまり、SPDY とか HTTP/2 を流し込むといったことは出来ません。

あと、FastCGI や iisnode を使った場合とは異なり、常に 1 つのプロセスしか起動されないため、それぞれのプロセスに負荷分散を行うということも出来ません。負荷分散を行う場合には、さらにその下にプロセスを管理するレイヤーが必要になるでしょう。

おまけ : httpPlatform 設定について

元々は Java 向けに用意されたとあって、ドキュメントは基本的に Java 向けに書かれています。

Upload a custom Java website to Azure

Web.config で必要なテンプレート的な設定は以下のような感じです。

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
  <system.webServer>
    <handlers>
      <add name="httpPlatformHandler" path="*" verb="*" modules="httpPlatformHandler" resourceType="Unspecified" />
    </handlers>
    <httpPlatform processPath="startup.bat" arguments="">
      <environmentVariables>
        <environmentVariable name="PORT" value="%HTTP_PLATFORM_PORT%" />
      </environmentVariables>
    </httpPlatform>
  </system.webServer>
</configuration>

基本的には全てのパス、HTTP メソッドに対して有効なハンドラーを追加し、httpPlatform 設定で起動するプロセスのパスを追加する形になります。

設定可能な項目

  • processPath
    • 実際に起動される実行ファイル
  • arguments
    • 実行ファイルに渡されるコマンドライン引数
  • startupTimeLimit
    • アプリケーションが起動完了するまでの最大時間
  • startupRetryCount
    • 起動に失敗した時にやり直す回数
  • requestTimeout
    • HTTP リクエストのタイムアウト時間
  • rapidFailsPerMinute
    • ラピッドフェール保護が動くまでの 1 分間の失敗回数
  • stdoutLogEnabled
    • 標準出力、標準エラー出力に書きだされた内容をログとして保存するか
  • stdoutLogFile
    • ログファイルのパス
  • environmentVariables
    • 子プロセス起動時に追加で渡す環境変数

渡される環境変数

  • HTTP_PLATFORM_PORT
    • 実際の HTTP リクエストが流し込まれるポート番号
  • HTTP_PLATFORM_DEBUG_PORT
    • Java でリモートデバッグを行うための特殊なポート番号
    • Web.config 内で利用した場合のみ開かれるらしい*2

*1:それ以外のポートは Web サイトの制限で開くことは出来ません。

*2:https://github.com/Azure/azure-websites-java-remote-debugging