遅刻してしまった・・・。
あまり深い内容はできないのですが、PlayFrameworkのプロジェクトでプロダクション環境にデプロイするときにAkkaの設定をちゃんとやらんとやばそうなので、そのへんのことを共有(まだ本番デプロイしたことはないのですが)。
負荷テストの実施
まず、負荷の検証の内容として、自宅のiMacに簡単なPlayアプリケーションを作って、MacbookAirから負荷をかけてみました。
iMac側のアプリケーションには1000回ループして、hogeをひたすら連結するというアクションを作成。
MacbookAir側からはJMeterを使って、100スレッドで100秒間ひたすらリクエストを投げまくってみる、という雑なパフォーマンスのかけ方をしてみました。
その結果、75%くらいのエラーが発生しました。∑(゚Д゚)ガーン
原因
PlayFrameworkのマニュアルによればActionのディスパッチにAkkaのアクターを使って、複数のリクエストを並列に捌いています。
Action invoker アクターは Action のコードを実行するために使われます。複数の Action を並列に実行するために、複数のアクターを起動し、それらを Round Robin ルータで制御しています。また、全てのアクターはステートレスです。
Action invoker アクターは、リクエストボディをパーズするために使われる ボディ・パーサー を取得するためにも使われます。この取得処理はアクターからの返信(パーズに使われる BodyParser オブジェクト)を待機するという実装になっていて、設定されたタイムアウト時間を経過すると失敗する仕様です。
Action invoker アクターは actions-dispatcher ディスパッチャーによって実行されます。
で、このaction-dispatcherの並行度が最大24にデフォルトでは制限されています。
play {
akka {
:
actor {
:
actions-dispatcher = {
fork-join-executor {
parallelism-factor = 1.0
parallelism-max = 24
}
}
:
}
}
}
akkaのデフォルト設定の上書き
そこで、上記の設定を変更するためにデフォルトのakkaの設定を上書きします。で、PlayFrameworkの初心者の私はこの設定をどこに書くかで早速迷いましたが、ようはakka用のconfを作ってメインのconfファイルでincludeするだけでした。
# 最後の方で・・・
include "akka.conf"
play {
akka {
event-handlers = ["akka.event.slf4j.Slf4jEventHandler"]
loglevel = WARNING
actor {
deployment {
/actions {
router = round-robin
nr-of-instances = 256
}
/promises {
router = round-robin
nr-of-instances = 24
}
}
retrieveBodyParserTimeout = 1 second
actions-dispatcher = {
fork-join-executor {
parallelism-factor = 128.0
parallelism-max = 256
}
}
promises-dispatcher = {
fork-join-executor {
parallelism-factor = 1.0
parallelism-max = 24
}
}
websockets-dispatcher = {
fork-join-executor {
parallelism-factor = 1.0
parallelism-max = 24
}
}
default-dispatcher = {
fork-join-executor {
parallelism-factor = 1.0
parallelism-max = 24
}
}
}
}
}
変更したのは以下のパラメーター。
- play.akka.deployment./actions.nr-of-instances
- play.akka.actions-dispatcher.fork-join-executor.parallelism-factor
- play.akka.actions-dispatcher.fork-join-executor.parallelism-max
。
このへんの値はこちらの記事を参考にしました。
結果
当初のテストでは75%近くまでエラーが発生していたのが、同一条件の負荷をかけてもエラーが0%にまで下がり、スループットも若干向上しました。効果は明らかにありました。が、まだ、これらの値の設定をどのように変更すれば良いのかは現在見ている、、というか調べたかったのですが、遅刻もしているので、とりあえずここまで。。。
アドヴェント・カレンダーに突っ込んだものの、薄い内容でごめんなしあ。