§フロント・エンドとなる HTTP サーバのセットアップ
HTTP ポートを 80 番に設定すれば、アプリケーションを簡単にスタンドアロンのサーバとしてデプロイすることができます。
$ start -Dhttp.port=80
プロセスを 80 番ポートにバインドするために root 権が必要なことがあります。
しかし、同じサーバで複数のアプリケーションをホスティングしたり、スケーラビリティや耐障害性の観点から、アプリケーションのインスタンスを複数たちあげて、それらをロードバランシングしたいこともあるでしょう。その場合は、フロントエンド HTTP サーバを利用することができます。
フロントエンド HTTP サーバを利用する場合、Play サーバを直接利用する場合よりも優れたパフォーマンスが得られることは決してないことに注意してください。
§lighttpd を使う
以下は lighttpd をフロントエンド Web サーバとして構成する例です。全く同じ用途に Apache を利用することもできますが、必要なものがバーチャルホスティングやロードバランスの機能だけであれば、 lighttpd の方が設定が簡単なのでおすすめです。
/etc/lighttpd/lighttpd.conf
ファイルで、以下のように定義します:
server.modules = (
"mod_access",
"mod_proxy",
"mod_accesslog"
)
…
$HTTP["host"] =~ "www.myapp.com" {
proxy.balance = "round-robin" proxy.server = ( "/" =>
( ( "host" => "127.0.0.1", "port" => 9000 ) ) )
}
$HTTP["host"] =~ "www.loadbalancedapp.com" {
proxy.balance = "round-robin" proxy.server = ( "/" => (
( "host" => "127.0.0.1", "port" => 9001 ),
( "host" => "127.0.0.1", "port" => 9002 ) )
)
}
§Apache を使う
以下は Apache httpd server を標準的な設定の Play アプリケーションの前段に配置するシンプルな設定の例です。
LoadModule proxy_module modules/mod_proxy.so
…
<VirtualHost *:80>
ProxyPreserveHost On
ServerName www.loadbalancedapp.com
ProxyPass /excluded !
ProxyPass / http://127.0.0.1:9000/
ProxyPassReverse / http://127.0.0.1:9000/
</VirtualHost>
§リバースプロキシに関する詳細設定
フロントエンド HTTP サーバを利用する場合、Play アプリケーションからすると、 HTTP リクエストがその HTTP サーバから送信されているように見えます。通常の設定では、同じマシン上で Play アプリケーションとリバースプロキシを起動している場合、 Play からはリクエストが 127.0.0.1 から送信されているように見えます。
リバースプロキシとなってる HTTP サーバは、プロキシ先の Play アプリケーションにリクエストの送信元を知らせるために、特別なヘッダを付与することができます。ほとんどの Web サーバは X-Forwarded-For というヘッダの第一引数にリクエスト元のクライアントの IP アドレスをつけて送信します。そのような Web サーバを利用している場合、 Play アプリケーションの XForwardedSupport を設定することで、 Play が request.remoteAddress をリバースプロキシの IP アドレスからリクエスト元クライントの IP アドレスに変更してくれます。ただし、この機能を利用するためには、アプリケーションの設定内でリバースプロキシの IP アドレスを全て記述しておく必要があります。
この設定を行った場合でも、 host ヘッダは変更されず、リバースプロキシが送信したままの内容になっています。そこで、例えば Apache 2.x を利用している場合は、次の設定を行うよいでしょう。
ProxyPreserveHost on
この設定を行うと、 Play アプリケーションへ送信される Host ヘッダが、クライアントから送信された元々の Host ヘッダの内容と同じになります。このように、XForwardedSupport と ProxyPreserveHost の二つの設定を組み合わせることで、アプリケーションが直接クライアントに公開されているように振る舞えるようになります。
もし、リバースプロキシへの一部のリクエストのみを Play アプリケーションに処理させたい場合は、一部のパスをプロキシ対象から除外する設定を追加してください。
ProxyPass /excluded !
§アプリケーションを透過的に更新するための、リバースプロキシとしての Apache
基本的な考え方は、 Play アプリケーションのインスタンスを二つ起動して、フロントエンドのプロキシサーバにそれらをロードバランスさせます。一方のインスタンスが落ちている場合には、稼働中のもう一方のインスタンスにのみリクエストを転送するようにします。
まず、同じ Play アプリケーションを 2 回起動します。一つはポート 9999 番、もう一つはポート 9998 で起動します。
$ start -Dhttp.port=9998
$ start -Dhttp.port=9999
次に、 Apache によるロードバランシングの設定を行います。
Apache の設定ファイルに、次のような設定を記述します。
<VirtualHost mysuperwebapp.com:80>
ServerName mysuperwebapp.com
<Location /balancer-manager>
SetHandler balancer-manager
Order Deny,Allow
Deny from all
Allow from .mysuperwebapp.com
</Location>
<Proxy balancer://mycluster>
BalancerMember http://localhost:9999
BalancerMember http://localhost:9998 status=+H
</Proxy>
<Proxy *>
Order Allow,Deny
Allow From All
</Proxy>
ProxyPreserveHost On
ProxyPass /balancer-manager !
ProxyPass / balancer://mycluster/
ProxyPassReverse / http://localhost:9999/
ProxyPassReverse / http://localhost:9998/
</VirtualHost>
特に重要なのは、 balancer://mycluster という部分です。これがロードバランサーの定義です。 +H オプションは、2 番目の Play アプリケーションが待機系であるということの宣言です。ただし、同時にこの待機系をロードバランス対象に加えることもできます。
Apache には、宣言されたクラスタのステータスを表示する機能も備わっています。現在のステータスを表示するためには、ブラウザで /balancer-manager にアクセスしましょう。
Play は完全にステートレスなアーキテクチャになっているため、2 つのクラスタ間でのセッションの共有に頭を悩ませる必要はありません。そのおかげで、特に苦労せず 3 つ以上のインスタンスにスケールアウトさせることが可能です。