質問

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

このアプリケーションを、クラスターで実行するように構成する複数のOC4Jアプリケーションサーバーにデプロイする予定です。

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

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

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

役に立ちましたか?

解決

競合する消費者パターンとリースパターンの組み合わせを使用して、クラスタ内のメッセージをかなり大規模に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〜1/2分ごとに更新します。これにより、フェールオーバーが可能になりました。アクティブなMDBが停止すると、別のMDB(そして1つだけ)が引き継ぎます。

これはかなり簡単なはずです。ここで、休止状態のMDBにロックをときどきチェックして、ロックが解放されたかどうかを確認させます。

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

他のヒント

最初のポイント:これはかなり安っぽいデザインであり、一度に処理できるのは1つのメッセージのみであるため、パフォーマンスが大幅に制限されます。パフォーマンスの改善が得られないため、フォールトトレランスのみのためにクラスタリングしていると思いますか?

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

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

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

私はstevendickに同意します。あなたはこの設計に順調に進んでいないのかもしれません。シーケンスIDまたは同様のアプローチに関して、エンタープライズ統合パターン:メッセージングソリューションの設計、構築、および展開(Gregor Hohpe y Bobby Woolf作)を使用して、メッセージングアーキテクチャに関する洞察を得ることをお勧めします。それは素晴らしい本で、たくさんの有用なパターンです...あなたが直面している力と問題はそこによく説明されていると確信しています。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top