8

多数の同時リクエストを処理する必要があるWicketWebアプリケーションを構築しています。負荷テストを行うためのテスト環境といくつかのjmeterスクリプトをセットアップしましたが、ほとんどのページをステートレスにすると、アプリケーションのCPUとメモリのフットプリントを削減できることに気付きました。

最大のページのonBeforeRender()メソッドにコードを追加して、ページがステートフルになる原因となっているコンポーネントを示しています。これは私がそれを検出するために持っているコードです:

@Override
protected void onBeforeRender() {    
    if (!getSession().isTemporary()) {
        visitChildren(Component.class, new IVisitor<Component>() {
            @Override
            public Object component(Component component) {
                String pageClassName = AbstractStatelessBasePage.this.getClass().getName();
                if (!component.isStateless()) {

                    String msg = pageClassName+" is stateful because of stateful component " + component.getClass().getName() + " with id " + component.getId() + ".";

                    List<IBehavior> behaviourList = component.getBehaviors();
                    for (IBehavior iBehavior : behaviourList) {
                        if (!iBehavior.getStatelessHint(component)) {
                            msg += "\n\t" + "The component has stateful behaviour: " + iBehavior.getClass().getName();
                        }
                    }
                    LOG.error(msg);
                }

                checkedPages.add(pageClassName);
                return CONTINUE_TRAVERSAL;
            }
        });
    }
}

出力では、ステートフル動作は、ページ内の既存のコンポーネントの一部で使用されているAjaxLinksによって引き起こされていることがわかります。

ERROR - AbstractStatelessBasePage$1.component(45) | HomePage is stateful because of stateful component InfoGrid$InfoButton with id infoButton.
    The component has stateful behaviour: org.apache.wicket.ajax.markup.html.AjaxLink$1

いくつかの場所で「true」を返すgetStatelessHint()メソッドを追加しようとしましたが、役に立たないようです。AjaxLinkのWicketソースコード、そのスーパークラス、およびいくつかの周辺コードも確認しましたが、AjaxLinkがすべての場合にステートフルである必要がある理由を発見できないようです。

私の場合、AjaxLinkはステートレスページにあり、リンクはステートを保存しません。このAjaxLinkがステートレスになる可能性があることをWicketに理解させるにはどうすればよいですか?

助けてくれてありがとう、ロルフ

編集:受け入れられた回答はWicket1.4.19で機能します。

以下をmavenpom.xmlに追加しました。

<dependency>
    <groupId>com.jolira</groupId>
    <artifactId>wicket-stateless</artifactId>
    <version>1.0.8</version>
</dependency>

「AjaxLink」を拡張したすべてのコンポーネントを「StatelessAjaxFallbackLink」を拡張するように変更しました。

WicketApplicationクラスに以下を追加することを忘れないでください。トラブルシューティングの時間を節約できます。

@Override
protected IRequestCycleProcessor newRequestCycleProcessor() {
    return new StatelessWebRequestCycleProcessor();
}

StatelessFormやその他のステートレスなものは、何らかの理由でリピーター(「ListView」など)内からは機能しないことに注意してください。

4

2 に答える 2

10

ページに Ajax 動作を追加すると、ページはステートフルになります (AjaxLink は AjaxEventBehavior を使用します)。これは、リンクをクリックすると、Wicket がサーバーでページ インスタンスを探し、その中のリンク コンポーネントを見つけ、最後にそのコールバック メソッド (onClick() など) を実行しようとするためです。ページを保存しないと、ajax 動作インスタンスを見つけてそのコールバック メソッドを実行する方法がありません。

Jolira の Ajax ビヘイビアーとコンポーネント (https://github.com/jolira/wicket-stateless) を使用できます。それらの動作は少し異なります。Jolira の AjaxLink をクリックすると、Ajax 呼び出しはページのまったく新しいインスタンスを作成し、その中で新しく作成された StatelessAjaxLink を見つけ、そのコールバック メソッドを実行し、最終的に AjaxRequestTarget を使用して Ajax 応答用のコンポーネント/javascript を追加し、新しく作成されたページ インスタンスを破棄します (ガベージ コレクションされます)。次の Ajax リクエストは、まったく新しいページ インスタンスで同じことを行います。

「Jolira のコードが Wicket コアにないのはなぜですか?」と尋ねる人もいるでしょう。-部分的な解決策を提供するため。例: statelessAjaxLink1 をクリックすると新しいページが作成され、PanelA が PanelB に置き換えられた StatelessAjaxLink の新しいインスタンスで onClick() が実行され、このパネル (PanelB) が AjaxRequestTarget に追加されます。簡単に言うと、このリンクをクリックすると、ページ内のパネルの本文が置き換えられます。PanelB の内部に StatelessAjaxLink2 がある場合、このリンクは見つかりません。なんで ?それをクリックすると Page の新しいインスタンスが作成され、この新しいインスタンスには PanelB ではなく PanelA が含まれるため、その onClick() メソッドを実行する StatelessAjaxLink2 を見つける方法がありません。

シナリオが十分に単純で、Jolira のコンポーネントがケースをカバーしている場合は、それらを使用してください。より複雑なシナリオは失敗する可能性があることに注意してください。

于 2012-05-14T19:26:35.877 に答える
3

wicket wikiAjaxFallbackLinkで参照されているステートレスのコードと、そこからリンクをたどることができる関連する github プロジェクトがあります。これで問題が完全に解決するかどうかはわかりませんが、少なくとも有益な場合があります。

同様のアプローチが改札 6 で試みられましたが、著者はそれが実験的であると警告しています。コードはこちらです。私はそれを使用しようとしていないので、それを保証することはできません.

于 2012-05-14T11:56:51.797 に答える