読者です 読者をやめる 読者になる 読者になる

しばやん雑記

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

Windows Azure Web サイトが Java に対応したので Ruby on Rails を動かしてみた

タイトルは意味不明だと思いますが、JRuby を動かす話でもないので割と詐欺ではないはずです。

相変わらず突然ですが、Windows Azure Web サイトが Java というか Tomcat と Jetty に対応しました。ちなみに、私は Java 出来ないので割と普通な人のブログを見てください。

Windows Azure の Webサイトで Tomcat, Jetty の稼働をサポート!!! - 割と普通なブログ

で、聞いたところによると Tomcat や Jetty は IIS があると動かすのがしんどいらしいですが、今回の Web サイトは IIS が生きたまま Tomcat と Jetty を動作させているようです。なので、Java 対応よりもどうやって実現しているかが気になりました。

というわけで、いつも通り Kudu を使って applicationHost.config を覗き見するわけですが、早速気になる記述を発見しました。以下は Jetty を有効にした状態での applicationHost.config の一部です。

<location path="java-sample">
  <system.webServer>
    <defaultDocument>
      <files>
        <clear />
        <add value="Default.htm" />
        <add value="Default.html" />
        <add value="Default.asp" />
        <add value="index.htm" />
        <add value="index.html" />
        <add value="iisstart.htm" />
        <add value="default.aspx" />
        <add value="index.php" />
        <add value="hostingstart.html" />
      </files>
    </defaultDocument>
    <handlers>
      <add name="httpPlatformHandlerMain" modules="httpPlatformHandler" path="*" verb="*" resourceType="Unspecified" />
    </handlers>
    <httpPlatform processPath="%JAVA_HOME%\bin\java.exe" arguments="-Djava.net.preferIPv4Stack=true -Djetty.port=%HTTP_PLATFORM_PORT% -Djetty.base=&quot;%programfiles(x86)%\jetty-distribution-9.1.0.v20131115&quot; -Djetty.webapps=&quot;d:\home\site\wwwroot\webapps&quot;  -jar &quot;%programfiles(x86)%\jetty-distribution-9.1.0.v20131115\start.jar&quot; etc\jetty-logging.xml" startupTimeLimit="30" startupRetryCount="5" />
  </system.webServer>
</location>

Java を有効にした場合、httpPlatform という構成と httpPlatformHandler という HTTP ハンドラが追加されていました。どうやらこのハンドラが鍵を握っているようです。

もうちょっと httpPlatform 構成を見ていくと processPath と arguments という属性があります。おそらく、ここに指定したパスのアプリケーションをリクエストが来た時に実行するみたいですね。そして arguments の中身に %HTTP_PLATFORM_PORT% という怪しげな環境変数もあります。

以上の情報を総合すると、Web サイトは以下のような流れで Java というか Tomcat と Jetty に対応したようです。

  1. 全てのリクエストを処理する httpPlatformHandler を IIS に追加
  2. httpPlatformHandler は構成に従い外部アプリケーションを起動、その時にポート番号(HTTP_PLATFORM_PORT)を渡しておく
  3. IIS に届いたリクエストは httpPlatformHandler が HTTP_PLATFORM_PORT に対して横流し
  4. Tomcat / Jetty は HTTP_PLATFORM_PORT をリッスンしているのでリクエストを処理出来る

要するにリバースプロキシ的なことを実現するのが httpPlatformHandler ということになりそうです。なので、実際には Java に限らずアプリケーションサーバを持つ環境であれば動作させることが出来そうですね。

なので、ようやくタイトルに戻ってきましたが、この Java を動作させる仕組みを使って Ruby on Rails のサーバを動作させてみます。

Ruby on Rails は Rack を使っているので Windows 上で動作して、さらに Rack に対応したサーバを選択する必要があります。最近では Unicorn が流行っているみたいですが Windows には対応していなかったので、ちょっと古めな感じがしますが Thin を使ってみました。

Thin - yet another web server

といっても特にやることは Windows Azure Web サイトで Ruby を動かしてみた(CGI 編) - しばやん雑記Windows Azure Web サイトで Ruby on Rails を動かしてみた - しばやん雑記 で書いたこととあまり変わりません。相変わらず RubyInstaller を使ったランタイムの手動インストールは必要です。

Rails と Thin のインストールは gem を使って行いますが、基本的には以下の記事を参考に行いました。

WindowsでRails (ThinをWindowsサービスとして動かす) - In My Programming Life

gem を使ってインストールが出来れば、後は適当に Rails のアプリケーションを作成しておくだけです。

そして一通りの準備が終わったら、wwwroot 以下に以下のような内容の Web.config を作成しておきます。

<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <system.webServer>
    <httpPlatform processPath="D:\home\ruby19\bin\ruby.exe" arguments="D:\home\ruby19\bin\thin -e development -p %HTTP_PLATFORM_PORT%  -c 'D:\home\site\wwwroot\sample' start" startupTimeLimit="60" startupRetryCount="5" />
  </system.webServer>
</configuration>

今回は完全に Ruby のパスやアプリケーションのルートを決め打ちにしてしまいましたが、環境変数と管理ポータルのアプリケーション設定を組み合わせることで、柔軟に設定が出来る Web.config を作れるはずです。

そして実際に動作確認ですが、とりあえず管理ポータルからは Java を適当に有効にしておきます。

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

実際には httpPlatformHandler の追加もしておけば管理ポータルを弄る必要はなさそうですが、今回はちょっと手を抜きました。

これで準備が完了したので、いつも通り Web サイトへブラウザでアクセスしてみます。上手くいけば Rails の見覚えのある画面が表示されるはずです。

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

念のために Kudu の PowerShell を使ってプロセスの情報を確認しておきます。

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

ちゃんと Ruby のプロセスが立ち上がっていることが確認できました。

そして恐らく FastCGI で動かした時のように、リクエスト数が増えるにしたがってプロセスが増えて、初期化の時間が追加されるということがありません。そしてプロセスがタイムアウトで落ちるということもないみたいなので、Web サイトを使った Ruby のホスティングが割と実用的になった気がします。