Wicket stuff に DataStores · wicketstuff/core Wiki
というライブラリがあり、Memcached や、Radis を使うものはあるのですが、
MongoDB を使っているものがなく、Cache の用途だと Memcached や Radis のほうが向いていそうだとは思いながら、
インストールが面倒に思い、MongoDBDatastore
を作ってみようという気になりました。
その過程で、StoreSettings
について調べてましたので、
その結果について記載します。1
IDataStore クラスが登場してくる周辺に登場するので、関係があるのかと思って調べていました。
StoreSettings の前に、DataStore について
Apache Wikcet 7.x ユーザガイド8章邦訳+訳注 - Qiita
にページキャッシングの記載がありますが、
Wicket の ステートフルなページは、以下の順番で、アプリケーションにキャッシュされます。
-
第1レベルのキャッシュ これは、ユーザーセッションに紐づけられたキャッシュです。
最後のリクエストで使用されたページのみ保存されます。
wicket/PageStoreManager.java at master · apache/wicket が実装を保持しています。 -
第2レベルのキャッシュ アプリケーションスコープ のキャッシュです。
デフォルトで、SerializedPagesCache
が使用されています。
sessionId
とpageId
をキーとして、アプリケーションのメモリー上にキャッシュされます。
SerializedPagesCache
は、wicket/DefaultPageStore.java at master · apache/wicket
のインナークラスです。 -
第3レベルのキャッシュ
このキャッシュが、DataStore の実装でコントロールできます。
デフォルトだと、DiskDataStore
が使われます。
第2レベルキャッシュに存在しないデータも、第3レベルのキャッシュ には存在します。
実装としては、以下のような作りになっています。- 第2レベルキャッシュにも、第3レベルキャッシュにも、データ保存は試みる。
- 第2レベルキャッシュの設定次第で、
1.
の保存時に、設定上限を上回った場合は削除される。 - コンポーネントの
unbind
時は、第2レベルキャッシュ、第3レベルキャッシュからもデータは削除を試みる。2
コンポーネントのunbind
がどのタイミングで走るのかがあまりよくわかっていないです。
この辺りの内容は、25 Wicket Internals 6.x にも記載されています。
DiskDataStore の 実装について
wicket/DiskDataStore.java at master · apache/wicket
のコンストラクタ実装は以下の通りです。
-
DiskDataStore.java
呼び出し先のwicket/DefaultPageManagerProvider.java at master · apache/wicket は以下のような実装になっています。/** * Construct. * * @param applicationName * @param fileStoreFolder * @param maxSizePerSession */ public DiskDataStore(final String applicationName, final File fileStoreFolder, final Bytes maxSizePerSession) { this.applicationName = applicationName; this.fileStoreFolder = fileStoreFolder; maxSizePerPageSession = Args.notNull(maxSizePerSession, "maxSizePerSession"); sessionEntryMap = new ConcurrentHashMap<>(); try { if (this.fileStoreFolder.exists() || this.fileStoreFolder.mkdirs()) { loadIndex(); } else { log.warn("Cannot create file store folder for some reason."); } } catch (SecurityException e) { throw new WicketRuntimeException( "SecurityException occurred while creating DiskDataStore. Consider using a non-disk based IDataStore implementation. " + "See org.apache.wicket.Application.setPageManagerProvider(IPageManagerProvider)", e); } }
-
DefaultPageManagerProvider.java
DiskDataStore の ファイル保存先は、protected IDataStore newDataStore() { StoreSettings storeSettings = getStoreSettings(); Bytes maxSizePerSession = storeSettings.getMaxSizePerSession(); File fileStoreFolder = storeSettings.getFileStoreFolder(); return new DiskDataStore(application.getName(), fileStoreFolder, maxSizePerSession); }
storeSettings.getFileStoreFolder()
の戻り値が使われます。
デフォルトは、システムプロパティjavax.servlet.context.tempdir
で指定された値、
設定がなければ、File.createTempFile("file-prefix", (String)null).getParentFile()
で得られたディレクトリが使用されます。
DiskDataStore内のgetStoreFolder
で 以下フォルダを指定してますので、
実際には、protected File getStoreFolder() { return new File(fileStoreFolder, applicationName + "-filestore"); }
javax.servlet.context.tempdir
で指定されたディレクトリの下にアプリケーション名 + "-filestore"
というディレクトリ作成され、その配下にページクラスがシリアライズされ、セッションごとに保存されていきます。
StoreSettings の 実装について
上記を踏まえて、StoreSettings の API について記載します。
メソッド名 | 内容 |
---|---|
setAsynchronous(boolean async) | 非同期で使用するか設定します。3 |
setAsynchronousQueueCapacity(int queueCapacity) | 非同期でDataStoreを使用する際のキューの容量を設定します。 |
setFileStoreFolder(File fileStoreFolder) | DiskDataStoreが保存するフォルダを設定します。4 |
setInmemoryCacheSize(int inmemoryCacheSize) | 第2レベルキャッシュに格納されるページインスタンスの最大数を設定します。 |
setMaxSizePerSession(Bytes maxSizePerSession) | DiskDataStoreに保村するセッションごとのページインスタンスが格納されるFileの最大サイズを設定します。 |
対になるgetメソッドが存在しますが、
省略します。
3.True を設定すると、IDataStoreには、AsynchronousDataStoreを介してアクセスされます。
4.DiskDataStore でのみ使用します。独自実装する場合は、明示的に使おうとしないと使われない。
DataStore を自前で実装する際の考慮点
調べた結果以下のことが、わかりました。
-
setFileStoreFolder について
DiskDataStore を使用する場合のみ使用される。DataStore を独自実装する場合は、使用する実装にしないと使われないので注意。 -
setMaxSizePerSession について
setFileStoreFolder
と同様に、DiskDataStore を使用する場合のみ使用される。
意味的には、別のDataStore の場合も、データサイズ超えたら消すなど、使う実装にすることは可能だと思う。
なので、設定できるようにすると、「格好は良い」かもしれない。 -
setInmemoryCacheSize について
第2レベルキャッシュ の設定に関する値なので、DataStoreとして何を使ってもアプリケーションには影響する。
小さい値を設定すれば、DataStore の値が使われる可能性が高まる。
大きすぎるとアプリケーションのメモリを圧迫する値 -
setAsynchronous について
DataStoreによっては、「DataStoreの保存自体が非同期化されている」ので、その場合は意味がない。
実装するDataStoreにより、どちらかは使い分けたほうがよさそう。
個人的には、第2レベルキャッシュ、が DataStoreだと思っていたので、
勉強になりました。
以上です。
コメント