Jakarta TomcatのIn-Memory-Sessionクラスタに、Perlで参加する。つまりTomcatのセッション情報をPerlで読むというお話。
Atami Application Serverの目玉としてあげていた「Jakarta Tomcatとのセッション情報共有」の準備ということで、とりあえずTomcatのin-memory-clusterにPerlで参加して、Tomcat側で更新されたセッション情報をダンプするだけのコードを書いてみた。TCPReplicatedSessionManager.pmまだ評価中のコードなのでAtamiのサーバには組み込んでなくて、単体のサーバとして動かして検証中。
$ cvs update $ perl Makefile.PL $ make $ perl -Mblib Ajp13/Modules/Cluster/TCPReplicatedSessionManager.pmで起動し、Tomcat側で更新されたセッション情報をSTDOUTにダンプします。ただし現状ではjava.lang.Stringでセットしたセッション情報しかサポートしていませんが(汗)
Tomcat側のセッションクラスタの設定についてはTomcatのドキュメントを参照してください。基本的に$CATALINA_HOME/conf/server.xmlの該当箇所のコメントを外すだけですが。
Tomcatのセッションレプリケーション
概略は先ほどあげたドキュメントにも書いてありますが、メモもかねて簡単に。Tomcatはクラスタリング時のセッション情報共有の手段として
- 共有ストレージ上のファイルでセッション情報を共有
- JDBCを介してRDBMSでセッション情報を共有
- ホスト間に張ったSocketでセッション情報を共有
- セッションを共有するクラスタへの参加表明 (0.5秒毎にUDPでマルチキャスト)
- セッション情報の受信と送信 (デフォルト4001/tcpでlisten)
ここまでは簡単で良いんですが、ここからさきの2番のサーバに送られるメッセージが厄介。
メッセージの形式
TomcatのJava Servletでセッション情報の操作を行うと、クラスタ内の各ホストにその情報が配布されます。その際に使用されるメッセージを大ざっぱに示すと"FLT2002": # メッセージ先頭 length(4byte): # メッセージボディ部の長さ body(length): # メッセージ本体 "TLF2003": # メッセージ末尾です。受信後サーバは
"\x06\x02\x03": # Ackを送り返します。
ちなみにbody部はgzipされているので、ボクらのトモダチtcpdumpで4001/tcpを見張っていても何をやっているかさっぱり判りません。
というわけでbody部をgunzipすると、メッセージ本体を取得することができます。でもこれってjava.io.ObjectInputStream/ObjectOutputStreamのデータなんですよね。そう、これは
プラットフォーム依存ってヤツです(違) つまりJavaのオブジェクトををシリアライズしたデータでして、一応ドキュメントはありますが、もう、データとして読みたい部類の物では有りません。
とりあえずこの辺のデータを解析し、TomcatのServlet側でセットされたセッション情報(今のところStringのみ)をPerlで受信できるようになりました。この後、String以外の一般的なオブジェクトをサポートできた段階で、Atami Application Serverに組み込もうと思います。最初は Tomcat -> Atami の流れだけサポートし、将来的に Tomcat <-> Atami と双方でセッション情報を共有できるように持っていければ嬉しいですね。
そして相変わらずスポンサー大募集中。