4

メッセージ駆動型Beanを使用してJMSメッセージを処理するアプリケーションがあります。このアプリケーションは、OC4Jアプリケーションサーバーにデプロイされます。(10.1.3)

このアプリケーションは、クラスターで実行するように構成される複数のOC4Jアプリケーションサーバーにデプロイすることを計画しています。

問題は、このクラスターでのJMSメッセージ処理にあります。OC4Jクラスター全体で一度に1つのメッセージのみが処理されるようにする必要があります。メッセージは時系列で処理する必要があるため、これは必須です。

OC4Jクラスター全体のメッセージ処理を制御する構成パラメーターを知っていますか?

または、クラスター全体でメッセージ駆動型Beanを同期する独自の同期コードを実装する必要があると思いますか?

4

3 に答える 3

5

競合するコンシューマー パターンとリース パターンの組み合わせを使用して、1 日あたり 150 万以上のメッセージというかなり大規模なクラスター内のメッセージの順次処理を実行しました。

ただし、ここにキッカーがあります-一度に1つのトランザクションしか処理できないという要件は、目標を達成するのを妨げます. 基本的な要件は同じで、メッセージは順番に処理する必要がありました。少なくとも、私たちはそう思っていました。その後、ひらめきがありました。問題をさらに考えてみると、完全な順序付けは必要ないことに気付きました。実際には、各アカウント内でのみ注文する必要がありました。したがって、クラスター内のさまざまなサーバーにアカウントの範囲を割り当てることで、クラスター内のサーバー間で負荷を分散できます。次に、各サーバーは、特定のアカウントのメッセージを順番に処理する責任がありました。

これが 2 番目の巧妙な部分です。クラスタ内のさまざまなサーバーにアカウント範囲を動的に割り当てるリース パターンを使用しました。クラスター内の 1 つのサーバーがダウンした場合、別のサーバーがリースを取得し、最初のサーバーの責任を引き継ぎます。

これは私たちにとってはうまくいき、プロセスは会社の合併のために置き換えられるまで約 4 年間実稼働していました。

編集:

このソリューションについては、こちらで詳しく説明しています: http://coders-log.blogspot.com/2008/12/favorite-projects-series-installment-2.html

編集:

わかりました。すでに必要なレベルで処理を行っていますが、クラスターにデプロイされているため、MDB の 1 つのインスタンスのみがキューからアクティブにメッセージをプルしていることを確認する必要があります。さらに、最も単純で実行可能なソリューションが必要です。

現在持っている MDB メカニズムを放棄する必要はないと思います。基本的にここで話しているのは、分散ロック メカニズムの要件であり、派手な言い回しではありません。

だから、これを提案させてください。MDB がキューからメッセージを受信するように登録する時点で、分散ロックをチェックし、それを取得できるかどうかを確認する必要があります。最初にロックを取得した MDB が優先され、その MDB のみがメッセージを受信するために登録されます。これで、シリアル化が完了しました。このロックはどのような形を取るべきですか? 多くの可能性があります。さて、これはどうでしょう。データベースにアクセスできる場合は、そのトランザクション ロックによって、必要なものの一部が既に提供されています。1 行のテーブルを作成します。行には、現在ロックを保持しているサーバーの識別子と有効期限があります。これはサーバーのリースです。各サーバーには、一意の識別子 (サーバー名とスレッド ID など) を生成する方法が必要です。

サーバーが行への更新アクセスを取得でき、リースの有効期限が切れている場合は、それを取得する必要があります。そうでなければ、あきらめます。リースを取得した場合は、近い将来の時刻 (5 分程度など) で行を更新し、更新をコミットする必要があります。アクティブ サーバーは、期限が切れる前にリースを更新する必要があります。残り時間が半分になったときに更新することをお勧めします。つまり、リースが 5 で期限切れになる場合は 2.5 分ごとです。これで、フェイルオーバーができました。アクティブな MDB が停止すると、別の MDB (1 つだけ) が引き継ぎます。

それはかなり簡単だと思います。ここで、休眠状態の MDB にロックをときどきチェックさせて、ロックが解放されているかどうかを確認する必要があります。

したがって、アクティブな MDB と休止状態の MDB はすべて、定期的に何かを行う必要があります。これを行うために、別のスレッドを生成させることができます。多くのアプリケーション エンジン ベンダーは、これを行うと満足しませんが、スレッドを 1 つ追加することは大したことではありません。もう 1 つのオプションは、多くのエンジンが提供するタイマー メカニズムに結び付けて、リースをチェックするために定期的に MDB を起動させることです。

ところで、サーバー管理者が NTP を使用して時計を適切に同期させていることを確認してください。

于 2009-09-11T15:07:08.500 に答える
-1

私は stevendick に同意します: あなたは設計から外れているかもしれません. シーケンス ID または同様のアプローチについては、 Enterprise Integration Patterns: Designing, Building, and Deploying Messaging Solutions (Gregor Hohpe y Bobby Woolf 著)を使用して、メッセージング アーキテクチャについての洞察を得ることをお勧めします。それは素晴らしい本で、役に立つパターンがたくさんあります... 私はあなたが直面している力と問題がそこによく説明されていると確信しています.

于 2009-09-11T14:55:35.653 に答える
-1

最初のポイント: これは非常にくだらない設計であり、一度に 1 つのメッセージしか処理できないため、パフォーマンスが大幅に制限されます。パフォーマンスが向上しないため、耐障害性のためだけにクラスタリングしていると思いますか?

デフォルトの JMS 実装を OC4J または別のもので使用していますか?

私は過去に IBM の MQ を使用したことがあり、これにはキューを排他的としてマークできる機能がありました。つまり、1 つのクライアントしか接続できませんでした。これは、あなたが望むものを提供するように見えます。

別の方法として、シーケンス ID (インクリメント カウンターと同じくらい簡単) を導入し、メッセージを処理するクライアントは、シーケンス ID が次の予期される値であることを確認し、そうでない場合はメッセージを戻します。このアプローチでは、さまざまなクライアントが、データベースなどの中央で共有されているデータ ストアで最後に確認した有効なシーケンス ID を保持する必要があります。

于 2009-09-11T14:41:40.493 に答える