1

jboss5.1、EJB3.0、およびスタンドアロン Java アプリケーションを「サブスクライバー」として使用しています

jmsトピックを介してサブスクライバーにメッセージを発行するメカニズムがあります。サブスクライバーがメッセージを受け取ると、将来のメッセージを再度リッスンし始めるまで、いくつかの操作を行う必要があります。

問題は、サブスクライバーがトピックからメッセージを受け取った場合、さらにメッセージをリッスンするのに十分な速さで戻る必要があることです (そうしないと、別のメッセージが発行される場合にそれを見逃すことになります)

したがって、私の解決策は、ejb パブリッシャー内で数秒間 putThread.sleep() を実行することです。

この方法では、新しいメッセージが発行される前に、すべてのサブスクライバーがリッスンに戻ったことを確認できません。

EJB 内でスレッドを使用することはお勧めできません。

そのシナリオの解決策はありますか?

ありがとう、レイ。

4

3 に答える 3

1

さて、あなたの問題は、実際には、メッセージを処理するときにJMSキューのリッスンを停止してから、自分自身を登録し直すことです。もちろん、前のメッセージを処理しているときにメッセージを見逃す可能性があります。

JMSキューから自分自身を登録解除しないことをお勧めします。一度に単一のメッセージを確実に処理するために、処理をプッシュする単一のスレッドプールを使用できます。

たとえば、以前に次のようなものがあった場合:

public void onNewJMSMessage(JMSMessage message) {
    unregisterMySelf();
    processMessage(message);
    registerMySelf();
}

代わりにこれを使用してください:

次のようなクラスメンバーを開始します。

private ExecutorsService processingPool = Executors.newSingleThreadExecutor();

public void onNewJMSMessage(final JMSMessage message) {
    processingPool.submit(new Runnable() {

         @Override
         public void run() {
              processMessage(message);
         }
    });
}

これにより、一度に1つのメッセージのみが処理されることが保証されます(それ以外の場合は、シングルスレッドプールの一意性を確保するためにシングルトンを設定する必要があります)。

これを行うと、主Thread.sleepに、EJBで悪であり、あらゆる種類の頭痛の原因となるものを取り除くことができます。

于 2012-04-20T14:04:28.663 に答える
0

このスレッドが古いことは承知していますが、2 セント追加せざるを得ないと感じています。上記のKyuさんのおっしゃることに賛成です。

EJB2 仕様に従って、エンタープライズ Bean はスレッドを管理すべきではありません。最新の仕様がこれについて何を言おうとしているのかはわかりませんが、これが変更された場合、私はショックを受けるでしょう.

問題は、JMS がメッセージが失われないように設計されていることです。そのため、MDB は何があってもメッセージを消費します。また、MDB は (他の EJB と同様に) コンテナー管理であることを覚えておく必要があります。メッセージを消費するために動作する MDB のインスタンスが 1 つしかないと思うのはなぜですか (もちろん、そのように設計している場合を除きますが、そうではないと確信しています)。

于 2016-07-12T00:55:06.323 に答える