Wicket wicketstuff serializer-kryo2 を使う


Wicket は session にPageインスタンスがシリアライズされて保存されますが、
core/serializer-kryo2 at master · wicketstuff/core
に kryo を使った ISerializer の実装があることを知りました。

Javaのシリアライザーをいろいろ試してみる(Java標準、Kryo、MessagePack、Protocol Buffers、JBoss Marshalling) - CLOVER
を見る限り「kryo」のほうがシリアライズ後のサイズが小さく、速度早そうなので、こちらを使用してみました。


前提

  • wicket の version
    7.7.0 です。
<!-- WICKET DEPENDENCIES -->
<dependency>
    <groupId>org.apache.wicket</groupId>
    <artifactId>wicket-core</artifactId>
    <version>7.7.0</version>
</dependency>

wicketstuff serializer-kryo2 を使う

pom.xml に dependency を追加する

<dependency>
    <groupId>org.wicketstuff</groupId>
    <artifactId>wicketstuff-serializer-kryo2</artifactId>
    <version>7.7.0</version>
</dependency>

Application クラス内で、KryoSerializer を設定

    getFrameworkSettings().setSerializer(new KryoSerializer());

これで、使えます。簡単です。

補足

  • KryoSerializer の bufferSize について
    デフォルトコンストラクタ呼び出しだと、DEFAULT_BUFFER_SIZE が適用され、10MB になります。
    この値を、1KBにしたところ、com.esotericsoftware.kryo.KryoException: Buffer overflow.
    が発生しました。10MB を超えるPageクラス(Pageクラス群かも?)はそれほどないかもしれないですが、
    場合によっては、サイズ調整が必要かもしれません。

  • README.md の Notes について
    あまり、テストしていないので、Wicket の Class の カスタムシリアライザーの登録が必要かもしれない旨と、
    内部で、SUN/Oracle JDK 独自のAPI(sun.reflect.ReflectionFactory) を使っているので、他のJDKだと、
    上手く動かないかもしれない旨が記載されています。

  • Kryo の version について
    kryo2が使われています。最新version は kryo4 なので、
    少し古いかもしれません。


InspectingKryoSerializer を使う

KryoSerializer を継承した InspectingKryoSerializer の使い方が、
README.md に記載されていましたので、使用してみました。
Development モード であれば、InspectingKryoSerializer
Deployment モード であれば、KryoSerializer を使うようにしました。

    if (usesDevelopmentConfig()) {
        // ------------------------------------
        // Set Serializer
        // --------
        IReportOutput reportOutput=new LoggerReportOutput();

        // output of report of type sizes, sorted tree report (by size), aggregated tree
        ISerializedObjectTreeProcessor typeAndSortedTreeAndCollapsedSortedTreeProcessors = TreeProcessors.listOf(
                new TypeSizeReport(reportOutput), new SortedTreeSizeReport(reportOutput), new SimilarNodeTreeTransformator(
                        new SortedTreeSizeReport(reportOutput)));

        // strips class object writes from tree
        TreeTransformator treeProcessors = new TreeTransformator(
                typeAndSortedTreeAndCollapsedSortedTreeProcessors,
                TreeTransformator.strip(new TypeFilter(Class.class)));

        // serialization listener notified on every written object
        ISerializationListener serializationListener = SerializationListeners.listOf(
                new DefaultJavaSerializationValidator(), new AnalyzingSerializationListener(
                        new NativeTypesAsLabel(new ComponentIdAsLabel()), treeProcessors));

        InspectingKryoSerializer serializer = new InspectingKryoSerializer(Bytes.megabytes(1L),
                serializationListener);

        getFrameworkSettings().setSerializer(serializer);
    }
    if (usesDeploymentConfig()) {
        // ------------------------------------
        // Set Serializer
        // --------
        getFrameworkSettings().setSerializer(new KryoSerializer());
    }

ログ設定で、以下のように、org.wicketstuff.pageserializerDEBUG レベルにします。
[1].以下は、dropwizardのymlの設定です。

# Logging settings.
logging:
  # The default level of all loggers. Can be OFF, ERROR, WARN, INFO, DEBUG, TRACE, or ALL.
  level: INFO
  # Logger-specific levels.
  loggers:
    org.wicketstuff.pageserializer: DEBUG
    org.apache.wicket.protocol.http: INFO
    org.owasp.csrfguard: INFO
  appenders:
    - type: console
      timeZone: JST

これで、Development モード で起動すると、ページにアクセスしたタイミングで、以下のようなコンソール出力が得られます。

=========================================================================================================================
|bytes|Type                                                                                                             |
-------------------------------------------------------------------------------------------------------------------------
| 4790|java.lang.String                                                                                                 |
| 1168|java.lang.Integer                                                                                                |
|  757|org.apache.wicket.markup.html.link.BookmarkablePageLink                                                          |
|  386|xyz.monotalk.festivals4partypeople.web.ui.pages.festival.search.FestivalsSearchPage$1$1                          |
|  338|org.apache.wicket.markup.repeater.Item                                                                           |
|  289|org.apache.wicket.markup.html.image.ExternalImage                                                                |
|  268|org.apache.wicket.markup.html.basic.Label                                                                        |
|  252|xyz.monotalk.festivals4partypeople.web.wicket.stateless.StatelessAjaxFormValidatingBehavior$FormValidateVisitor$1|
|  223|org.apache.wicket.markup.html.list.ListItem                                                                      |
|  207|xyz.monotalk.festivals4partypeople.web.wicket.stateless.StatelessPagingNavigator$1                               |
|  192|xyz.monotalk.festivals4partypeople.web.ui.panels.feedback.ApplicationFeedbackPanel                               |
|  187|org.apache.wicket.markup.html.list.LoopItem                                                                      |
|  180|org.apache.wicket.request.mapper.parameter.INamedParameters$NamedPair                                            |
|  168|org.apache.wicket.model.Model                                                                                    |
|  150|org.apache.wicket.request.mapper.parameter.PageParameters                                                        |

サイズの大きすぎるオブジェクトや、前述のKryoSerializer のバッファサイズを決定するのに、使う機能なのかと思います。
レポートは、サンプルの通り実装すると、上記 TypeSizeReport と、 2つのTreeSizeReport の出力が得られます。

使用してテストしながら、カスタムシリアライザーの登録が必要なら登録していく形になるかと思います。
以上です。

コメント