【意訳】データベース駆動アプリのための、Play2最適化について #play_ja
この記事は、HerokuのPrincipal Developer EvangelistのJames Ward氏の記事の意訳です。参考程度にどうぞ。
誤訳・誤植等ありましたら、@modal_soulまでリプライいただけるとありがたいです。
先週Matt Raible氏と共に、UberConfで行われたPlay vs. Grailsスマックダウンでプレゼンテーションをしました。 このセッションの目標は、同じフレームワークを用いて同じアプリケーションを作り、Play2+JavaとGrailsを比較することです。 比較のために、いくつかのベンチマークを含む評価基準を使用しました。 結果については、こちら(Matt’s session recap blog)に詳しく掲載されています。 評価結果のプレゼンの後、これらのタイプのアプリケーションでPlay2のAkkaスレッドシステムを最適化するのに重要なことを発見しました。 Play2は、ブロッキングのコールを含まないHTTPリクエスト(i.e. 非同期)のためにout-of-the-boxに最適化されています。 Javaのほとんどのデータベース駆動アプリでは同期コールはJDBC経由で使用されるため、Play2ではこれらのリクエストタイプのためにAkkaを調整するちょっとした設定が必要です。
シンプルな例をあげてみます。時間的に現実的なデータベースブロックをシミュレートするために、このベンチマークをローカルではなくHeroku上で実行します。 “play2bars”example appから”java-ebean”ブランチとHerokuの共有のPostgreSQLデータベースを使います。
Apache Benchを実行して、同時100クライアント接続で10000リクエストをアプリのJSONサービスへ投げるために、同じAWSリージョンにあるEC2サーバーからHerokuのmy appとして、以下のコマンドを実行しました。
最初の最適化前の結果がこちらです
毎秒973リクエストは悪くはありませんが、下記のようなエラーが確認できました。
これは、Akkaが長時間ブロックされたことを意味しており、同期のコード実行を改善するようにPlay中のAkkaの設定を変え、評価を再実行しました。その結果は以下のようになりました。
今回は、毎秒1374リクエストになりました。シンプルな最適化の方法は、Akkaで処理を行うスレッドを増やすして、タイムアウト値を長く設定することです。それによりスレッドが同期DBによってブロックされた際、より多くのリクエストをハンドリングするためにさらにスレッドを呼び出します。実際に使ったPlayの設定は以下です。
Akkaで使用されるスレッドの数は、CPUと”parallelism-factor”の設定値を掛け合わせた値で、”parallelism-max”が上限値です。 デフォルトの”parallelism-factor”は”1”に設定されていて、この場合スレッド数はCPU数と同じで、”parallelism-max”のデフォルトは”24”です。これらの設定について詳しくは、Playのドキュメントで確認できます。
すべての設定ファイルはこちらのplay2barsプロジェクトから
このベンチマークはあくまで参考であって、それぞれの環境で異なってくると思います。それぞれの環境に合わせたチューニングをしてください。質問があれば是非。
Latest post:
- OpenWhiskのScala sbtプロジェクトのgiter8テンプレートを作った
- OpenWhisk+Scalaで作るServerless Architectureとっかかり
- BluemixにPlayframeworkアプリケーションをデプロイする
- sbt、Giter8を統合するってよ
- Scala 2.12.0でSAM型