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 ではローカルホストで固定です。
説明用に某セミナー用に作った画像を引っ張り出してきました。
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