DynamoDB の Write しきい値が最大値に張り付いたままなのですが

| コメントをどうぞ

年末にはまだ遠い。
かといって始まったばかりとも言いがたい。
そんな11月、いかがお過ごしでしょうか。
ここ湾岸エリアは寒風が吹きすさんでおります。
さ、さむい。。。(懐が
DiceK Mikamiです。

本日はセッションレプリケーションを調査していたときに「ぐぬぬ。。。」となったことに関して共有したいと思います。

「infoScoop for Google Apps」では、長らくセッションレプリケーションによるセッション永続化を行っていませんでした。
そのため、「リリースだぁ!」となると担当者たちが死んだ魚の目をしながら残業申請書を書いていました。
そんな状態を打開するためDynamoDBによるセッションレプリケーションについて調査をいたしました。
 

環境

  • EC2 ×2:Tomcat7にテストアプリを稼働
  • ELB:各インスタンスへのロードバランサー
  • RDS(MySQL):アプリで利用するデータベース
  • DynamoDB:セッション永続化用
     

設定

以下のサイトを参考にさせていただきました。

「Amazon DynamoDBによるTomcatセッション永続化とフェイルオーバー」
http://dev.classmethod.jp/cloud/amazon-dynamodb-tomcat-session-management/
 

動きはしたが。。。

動きました。
大変簡単です。
レプリケーションもきちんと行われています。
この状態でDynamoDBのコンソールを開くとなんとWriteしきい値が最大値に張り付いたままになっているではないですか!
Readは程よい感じなのになぜ。。。
DynamoDBでは、デフォルトでReadは10ユニット、Writeは5ユニットのしきい値があります。
これを超えるとCRUDにちょっとした問題が発生します。
しかし、セッションの書き込み自体はできている。
???
 

TomcatのPersistentMangerの仕組みががが

色々調べているとわかったのですが、どうもDynamoDBにセッションを保存するライブラリが怪しいのではないかと。

aws/aws-dynamodb-session-tomcat
https://github.com/aws/aws-dynamodb-session-tomcat

このライブラリは、TomcatのPersistentManagerを拡張したものになります。
PersistentManagerの設定値を使って、セッションの格納や取り出しを行ったりしているのですが、今回はこれの保存部分の動きが怪しいわけです。
実際にライブラリに仕掛をして、色々確認したところ、どうも1分に1回保存処理が動いているようです。
セッションの保存は、以下の式によって計測できます。

maxIdleBackup + processExpiresFrequency * backgroundProcessorDelay

この式によって与えられた秒数後に保存が実行されます。
maxIdleBackupはライブラリによって30が与えられています。
processExpiresFrequencyはデフォルトで6。
engine.backgroundProcessorDelayはデフォルトで10。
つまり、最終アクセスから90秒後に1度だけ保存処理が走る、、、と思っていた時期もありました。

実は違うのです。
確かに、最終アクセスからの時間はあっておりました。
ですが、上式よりmaxIdleBackupを差し引いた値(つまり、60)間隔で周期的に保存処理が実行されていたのです。
保存自体は、Tomcatメモリに存在し、かつアクセスが発生していないセッションを対象にしているので、接続中は絶対に発生することはないのですが、そう都合よくいかないものです。
 

どう解決するか

いくつか解決する方法はあります。

  1. とにかく課金
  2. Tomcatのセッション時間を短くする
  3. セッション保存間隔を延ばす

1番に関しては、言わずもがなですね。
Read/Writeのしきい値は、課金によって増やすことができます。
さぁ!課金生活をはじめるときです!
貧乏人にはマネのできないマネーパワーを今こそ使うときです!

2番に関しては、Tomcatのメモリ上にセッションが保持され続けることが問題なのだから、Tomcatのセッション時間を短くしてしまえば、保存処理は発生しません。
セッションタイムアウトはのデフォルト設定で30分となっていますが、明示的に指定したい場合は、web.xmlに記述します。

<session-config>
  <session-timeout>セッションタイムアウト時間(分)</session-timeout>
</session-config>

あまりにも短くしすぎるとセッション切れが頻発しますので、その点が気になるところです。

3番に関しては、そもそも保存を1分間隔でやっているのが問題なわけですからそれを調整すると言う案です。
processExpiresFrequencyまたはbackgroundProcessorDelayを調整することで保存間隔を指定できます。
processExpiresFrequencyは、context.xmlのManagerタグにて指定することができます。
backgroundProcessorDelayもcontext.xml内に記述できますが、デフォルトでは親(StandardEngine)のものを利用するので、そちらを修正しても良いかもしれません。
あまりにも長すぎると緊急時にセッションが保存されてなかったなどと言うことが起きてしまいますので、まぁ程よくと言うのが良いかもしれません。
  

追記

今回利用したライブラリですが、現在(2014/10/28時点)、盛大にバグっております。
一応、修正したものをプルリクエストしているのでマージされることを祈りましょう。

。。。というのは、あまりにもひどいので私の方で修正したものをGithubにあげておきましたので、どうぞご利用ください、

corestrike/aws-dynamodb-session-tomcat
https://github.com/corestrike/aws-dynamodb-session-tomcat/tree/pull-request-marge

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です

次のHTML タグと属性が使えます: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>