アプリケーションの本番稼動
アプリケーションを本番環境向けに最適化するシンプルな tips を紹介します。
本番稼動向け application.conf の設定
まず最初に、本番モードを指定するベストな方法は、本番環境のフレームワークに特別な ID を与えることです。例として production という ID にしてみましょう。どのようにして ID を与えるかについては、複数環境用 application.conf の管理 を参照してください。
フレームワークを本番モードに設定する:
%production.application.mode=prod
このモードでは、フレームワークは全ての Java ソースとテンプレートをプリコンパイルします。この段階でエラーが見つかった場合、アプリケーションは開始されません。ソースの変更は動的にリロードされません。
実際に利用するデータベースを定義する:
もし (db=mem または db=fs いずれかの) 開発用データベースを使っていたのであれば、より堅牢なデータベースエンジンを設定すべきです:
%production.db.url=jdbc:mysql://localhost/prod
%production.db.driver=com.mysql.jdbc.Driver
%production.db.user=root
%production.db.pass=1515312
JPA の自動スキーマ更新を無効にする:
もし Hibernate が提供する自動スキーマ更新機能を使っていたのであれば、本番環境ではこの機能を無効にすべきです。
本番環境サーバにおいて、Hibernate に自動的に本番環境スキーマやデータを ALTER させるというのは、一般的には悪いアイディアです…
最初のデプロイについては、別の問題として考えることもできます。この場合のみを指定するには、以下のようにします:
%production.jpa.ddl=create
安全な秘密鍵を定義する:
Play の秘密鍵は、セッション署名のような暗号機能を保証するために使用されます。アプリケーションは、この秘密鍵を厳重に管理しなければなりません。
%production.application.secret=c12d1c59af499d20f4955d07255ed8ea333
play secret コマンドを使って、安全で (少なくとも ‘本物の’ OS 上では) ランダムな新しい秘密鍵を生成することができます。アプリケーションを複数台のサーバに分散させる場合は、すべてのアプリケーションインスタンスに 同じ秘密鍵 を使用することを忘れないでください!
ログの設定
本番環境において、ローテーションするログファイルを使用することは良い考えです。コンソールログは logs/system.out ファイルに書き込まれ、このファイルは制限無しに肥大化するので、ログをコンソールに出力してはいけません!
カスタマイズした log4j.properties を conf/ ディレクトリに作成してください:
log4j.rootLogger=ERROR, Rolling
log4j.logger.play=INFO
# Rolling files
log4j.appender.Rolling=org.apache.log4j.RollingFileAppender
log4j.appender.Rolling.File=application.log
log4j.appender.Rolling.MaxFileSize=1MB
log4j.appender.Rolling.MaxBackupIndex=100
log4j.appender.Rolling.layout=org.apache.log4j.PatternLayout
log4j.appender.Rolling.layout.ConversionPattern=%d{ABSOLUTE} %-5p ~ %m%n
フロントエンド HTTP サーバのセットアップ
アプリケーションの HTTP ポートを 80 番に設定することで、簡単にアプリケーションをスタンドアロンサーバとしてデプロイすることができます:
%production.http.port=80
しかし、同一サーバ上で複数のアプリケーションを管理したり、拡張性や耐障害性のために複数のアプリケーションインスタンスを負荷分散する場合、フロントエンド 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" => 9000 ),
( "host" => "127.0.0.1", "port" => 9001 ) )
)
}
Apache をセットアップする
以下の例は、 標準的設定の Play の前面で動作する Apache httpd server のシンプルな設定を示しています。
LoadModule proxy_module modules/mod_proxy.so
...
<VirtualHost *:80>
ProxyPreserveHost On
ServerName www.loadbalancedapp.com
ProxyPass / http://127.0.0.1:9000/
ProxyPassReverse / http://127.0.0.1:9000/
</VirtualHost>
アプリケーションの透過的な更新を可能にするプロキシサーバとしての Apache
基本的なアイディアとして、web アプリケーションの 2 つの Play インスタンスを実行し、前面のプロキシにこれらを負荷分散させます。1 つのインスタンスが使用できない場合、すべてのリクエストを使用できるもう 1 つのインスタンスにフォワードします。
同一の Play アプリケーションを 2 つ起動しましょう: ひとつは 9999 番ポートで、もうひとつは 9998 番ポートで実行します。
アプリケーションを 2 つコピーして、conf ディレクトリにある application.conf を編集してポート番号を変更してください。
それぞれのアプリケーションディレクトリで、以下のように実行します:
play start mysuperwebapp
ここで、Apache web サーバに負荷分散させるよう設定しましょう。
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 オプションは、二番目の Play アプリケーションがスタンバイ状態にあることを意味します。しかし、負荷分散するよう指示することもできます。
mysuperwebapp をアップグレードしたい場合は、毎回、以下を実行する必要があります:
play stop mysuperwebapp1
すると、ロードバランサは全てを mysuperwebapp2 にフォワードします。その間に mysuperwebapp1 を更新してください。更新が完了したら、以下を実行してください:
play start mysuperwebapp1
これで mysuperwebapp2 を安全に更新することができます。
Apache はクラスタの状態を閲覧する方法も提供します。クラスタの現在の状態を確認するには、単純にブラウザに /balancer-manager を指定してください。
Play は完全にステートレスなので、2 つのクラスタ間でセッションの管理をする必要はありません。とても簡単に 2 つ以上の Play インスタンスにスケールすることが可能です。
高度なプロキシ設定
フロント HTTP サーバを使用する場合、リクエストアドレスは HTTP サーバからやって来るように見えます。Play アプリケーションとプロキシを同一筐体で実行する、一般的なセットアップにおいては、Play アプリケーションからは、リクエストが 127.0.0.1 からやって来るように見えるでしょう。
プロキシサーバは、プロキシされたアプリケーションにリクエストがどこからやって来たかを伝える特別なヘッダを、リクエストに追加することができます。ほとんどの web サーバは、第一引数をリモートクライアントの IP アドレスとした X-Forwarded-For ヘッダを追加します。フォワードサポートを有効にするには、Play アプリケーションを以下のように設定します:
XForwardedSupport=127.0.0.1,10.0.0.25
Play は request.remoteAddress をプロキシの IP からクライアントの IP に変更します。これが動作するよう、プロキシの IP アドレスをリストする必要があります。
しかし、ホストヘッダが付加されない場合、プロキシの問題は依然として残ってしまいます。Apache 2.x を使用する場合、ディレクティブに以下のように追加することができます:
ProxyPreserveHost on
host: ヘッダはクライアントから発行されたオリジナルのホストリクエストヘッダになります。これらふたつのテクニックを連携することで、アプリケーションはスタンドアロンと同じようになります。