最近、
Dropwizard で
Dropwizard で 可能な session clustering 方法
JDBC を
使って RDB に 保存する
java - Dropwizard Session Clustering - Stack OverflowMongoDB に
保存する MongoDB session clustering in Dropwizard - Google グループ Hazelcast に
保存する martindow/dropwizard-hazelcast-session: A Dropwizard bundle for providing clustered session replication using Hazelcast distributed maps.
Dropwizard は
現在、
参考記事
前提.使用ライブラリ
前提となる
- mongo-java-driver
<!-- MongoDB --> <dependency> <groupId>org.mongodb</groupId> <artifactId>mongo-java-driver</artifactId> <version>3.2.2</version> </dependency>
- dropwizard
<dependency> <groupId>io.dropwizard</groupId> <artifactId>dropwizard-core</artifactId> <version>1.0.6</version> </dependency> <dependency> <groupId>io.dropwizard</groupId> <artifactId>dropwizard-servlets</artifactId> <version>1.0.6</version> </dependency> <dependency> <groupId>io.dropwizard</groupId> <artifactId>dropwizard-assets</artifactId> <version>1.0.6</version> </dependency>
jetty-nosql の、 MongoSessionManager を 使って 実装する
使っている、mongo-driver
の
mongo-driver
の
pom へ 依存関係を 追加
参考記事のMongoSessionManager
はjetty-nosql
に
Dropzaird 1.0.6 の
を9.3.9.v20160517
で、
jetty-nosql
は、
jetty-nosql
が
除外しています。
当初除外していなかったのですが、
- mongo-driver-v2 で
動けばOKなら
<!-- mongo-driver-v2 で動けばよいなら --> <dependency> <groupId>org.eclipse.jetty</groupId> <artifactId>jetty-nosql</artifactId> <version>9.3.9.v20160517</version> <exclusions> <exclusion> <groupId>org.eclipse.jetty</groupId> <artifactId>jetty-server</artifactId> </exclusion> <exclusion> <groupId>org.eclipse.jetty.toolchain</groupId> <artifactId>jetty-test-helper</artifactId> </exclusion> <exclusion> <groupId>org.mongodb</groupId> <artifactId>mongo-java-driver</artifactId> </exclusion> <exclusion> <groupId>org.eclipse.jetty.tests</groupId> <artifactId>test-sessions-common</artifactId> </exclusion> <exclusion> <groupId>org.eclipse.jetty</groupId> <artifactId>jetty-jmx</artifactId> </exclusion> </exclusions> </dependency>
- mongo-driver-v3 でも
動かすなら
<dependency> <groupId>org.eclipse.jetty</groupId> <artifactId>jetty-nosql</artifactId> <version>9.3.16.v20170120</version> <exclusions> <exclusion> <groupId>org.eclipse.jetty</groupId> <artifactId>jetty-server</artifactId> </exclusion> <exclusion> <groupId>org.eclipse.jetty.toolchain</groupId> <artifactId>jetty-test-helper</artifactId> </exclusion> <exclusion> <groupId>org.mongodb</groupId> <artifactId>mongo-java-driver</artifactId> </exclusion> <exclusion> <groupId>org.eclipse.jetty.tests</groupId> <artifactId>test-sessions-common</artifactId> </exclusion> <exclusion> <groupId>org.eclipse.jetty</groupId> <artifactId>jetty-jmx</artifactId> </exclusion> </exclusions> </dependency>
- 注意点 現在(2017/02/17時点)での、
jetty-nosql の versionの 最新は、
jetty-9.4.2.v20170215
ですが、9.3.0
>9.4.0
でSession 関連 API に 結構な 変更が 入っており、
Method 互換性がありません。
jetty のversion と 合わせてた ものを ちゃんと 持ってくる ことを お奨めします。
実装
Bundle に
Bundle.java (抜粋)
public class MyBundle implements ConfiguredBundle<MyConfiguration> { @Override public void initialize(Bootstrap<?> bootstrap) { // Do Nothing... } @Override public void run(WicketConfiguration configuration, Environment environment) throws Exception { MutableServletContextHandler context = environment.getApplicationContext(); // Mongo Session Manager 登録 setSessionHandlerTo(environment); environment.jersey().disable(); } /** * setSessionHandlerTo * * @param env */ private void setSessionHandlerTo(Environment env) throws UnknownHostException { // Set SessionHandler MongoClientURI mongoURI = new MongoClientURI(MongoDBResource.getUriString()); // Not Close... MongoClient mongoClient = new MongoClient(mongoURI); // 非推奨だが、ライブラリが対応していないので使う.. DB db = mongoClient.getDB("jetty_session"); DBCollection collection = db.getCollection("jetty_session_collection"); env.lifecycle().addLifeCycleListener(new AbstractLifeCycle.AbstractLifeCycleListener() { @Override public void lifeCycleStarting(LifeCycle event) { log.info("lifeCycleStarting start event = {}", event); if (!(event instanceof Server)) { return; } Server server = (Server) event; MongoSessionIdManager sessionIdManager = new MongoSessionIdManager(server, collection); MongoSessionManager sessionManager = null; try { sessionManager = new MongoSessionManager(); } catch (UnknownHostException e) { throw new IllegalStateException(e); } sessionIdManager.setWorkerName("node1"); sessionIdManager.setScavengePeriod(1800000L); sessionIdManager.setScavengeBlockSize(0); sessionIdManager.setPurge(true); sessionIdManager.setPurgeDelay(1800000L); sessionIdManager.setPurgeInvalidAge(1800000L); sessionIdManager.setPurgeValidAge(5400000L); sessionIdManager.setPurgeLimit(0); sessionManager.setSessionIdManager(sessionIdManager); sessionManager.setPreserveOnStop(true); env.servlets().setSessionHandler(new SessionHandler(sessionManager)); } }); } }
説明1
MongoSessionIdManager
の生成には、 Server クラスの インスタンスが 必要です。
env.getApplicationContext().getServer();
でもJetty Serverには アクセスできたのですが、
StartServer 前だからなのが、NullPointerException が 発生しました。
java - Dropwizard Session Clustering - Stack Overflow
を確認した ところ、 AbstractLifeCycle.AbstractLifeCycleListener
を使って、 JDBCSessionManager
を設定していたので、
この方法を 参考に、 設定実装を 記述しました。 説明2 処理の
流れは、
1.MongoSessionIdManager
を生成して、 MongoSessionManager
に設定。
2.SessionHandler
のコンストラクタに、 MongoSessionManager
を設定して、 SessionHandler
を生成する。
となります。 2
この流れが 9.4.0
からだと変わっています。
動かして、 NoSuchMethod エラーが 発生する 場合の 対処
サーバを
Exception in thread "main" java.lang.NoSuchMethodError: com.mongodb.DBCollection.ensureIndex(Lcom/mongodb/DBObject;Lcom/mongodb/DBObject;)V at org.eclipse.jetty.nosql.mongodb.MongoSessionIdManager.<init>(MongoSessionIdManager.java:186)
Difference between createIndex() and ensureIndex() in java using mongodb - Stack Overflow
に記載が
Github で
MongoSessionIdManager uses deprecated ensureIndex · Issue #641 · eclipse/jetty.project Patch が
<dependency> <groupId>org.eclipse.jetty</groupId> <artifactId>jetty-nosql</artifactId> <version>9.3.16.v20170120</version> </dependency>
MongoSessionIdManager の 設定に ついて
- 設定値
Session Clustering with MongoDB
から
MongoSessionIdManager
、MongoSessionManager
に、
設定値 | 説明 | デフォルト |
---|---|---|
scavengeDelay | Sessionデータを削除にかける時間 | 不明(MongoSessionIdManagerから設定できない) |
scavengePeriod | Sessionデータを削除する間隔 | 30分(ms指定) |
scavengeBlockSize | 各削除クエリを制限するセッションIDの数。 メモリに非常に多くのセッションがある場合、これを0以外の値に設定すると、削除を複数のクエリに分割することで削除をスピードアップできます。 デフォルトは0で、すべてのセッションIDが1つのクエリで考慮されます。 | 0 |
purge (Boolean) | settionストアから無効なセッションを完全に削除するか否か | true |
purgeDelay | Purge処理の実行間隔 | 1日(ms指定) |
purgeInvalidAge | 無効なセッションがパージ対象となるまでの期間 | 1日(ms指定) |
purgeValidAge | どれくらいまで遡って、Purge処理の対象とするか指定する期間値 | 336日(ms指定)2 |
purgeLimit | パージクエリから返されるアイテムの数を表す整数値。デフォルトは0で、無制限です。 期限切れの古いセッションが多い場合、この値を設定すると、パージ処理が高速化される可能性があります。 | 0 |
preserveOnStop | SeesionManagerが停止した時に全てのセッションを保持するか否か | true |
[3] 相当、
MongoDB に 記録される Session データ
Mongo DB に
{ "_id" : ObjectId("58a6e651fb556ea0b033964a"), "id" : "node11enougmx2cmn1fyywq690pz76", "created" : NumberLong("1487332945990"), "valid" : true, "context" : { "::*" : { "__metadata__" : { "version" : NumberLong(2) }, "wicket:Key[type=org%2Eapache%2Ewicket%2Eprotocol%2Ehttp%2EWicketFilter, annotation=[none]]:session" : BinData(0,"..."), "wicket:Key[type=org%2Eapache%2Ewicket%2Eprotocol%2Ehttp%2EWicketFilter, annotation=[none]]:wicket:persistentPageManagerData - Key[type=org%2Eapache%2Ewicket%2Eprotocol%2Ehttp%2EWicketFilter, annotation=[none]]" : BinData(0,"..."), "Wicket:SessionUnbindingListener-Key[type=org%2Eapache%2Ewicket%2Eprotocol%2Ehttp%2EWicketFilter, annotation=[none]]" : BinData(0,"...") } }, "maxIdle" : -1, "expiry" : NumberLong(0), "accessed" : NumberLong("1487332957425") }
説明1
maxIdle
値が-1
なので、無期限で sessionは 維持されます。
mongoSessionManager#setMaxInactiveInterval(1800);
で設定すると、 以下のようになります。
"maxIdle" : 1800
説明2
"wicket:Key
で設定されている セッション情報は、 Wicket を 使用しているので、 設定されているのかと 思います。
BinaryDataで文字列と して、 そこそこ 大きい 情報が 詰まれています。
Session に男らしく 情報を 詰め 込んでいることが わかりました。
このと
基本的に
別に
追記 (2017/07/17)
Dropwizard 1.0.6 から
jetty のMongoSessionIdManager
が
結構な
Dropwizard 1.0.6 から
に
以上です。
コメント