1

JMS アーキテクチャの構築を開始したばかりで、次の基本設定があります。

  1. グラスフィッシュ v2.1
  2. TopicConnectionFactory を介してトピックをリッスンする MDB (すべてローカル サーバー上)

現在、MDB は新しいメッセージが到着するとワーカー スレッドを生成します。メッセージを順番に配信する場合でも、要求を同時に処理する前にスレッドが特定の条件をチェックするように同期メカニズムが必要です。

これらのスレッドがデータを共有する方法はありますか? または、同期に使用できる他のメカニズム (データベース テーブル/行ロックを除く) はありますか?

前もって感謝します。


明確にするために、私は自分のスレッドを作成していません。誰もが正しく指摘したように、コンテナは私のためにそれを行います. 私のジレンマを例を挙げて説明しましょう。

-メッセージ A は t=0 に到着し、データ ID 1 を「作成」します

- メッセージ B は t=0.1 に到着し、データ ID 1 を「更新」します

ここで、コンテナーが A と B を処理する 2 つのワーカーを生成し、データを更新するよりもデータを「作成」する方がはるかに時間がかかると仮定すると、更新はより早く処理され、効果はありません。

より明確にするために、

-メッセージ B の処理中に、t=1 でデータ ID 1 を探します (見つからないため、何もせずに終了します)。

- データ ID 1 は、t=2 でメッセージ A を処理中に作成されます。

4

6 に答える 6

6

ペダンアラート!私はテクノロジーの実際の仕様を読むタイプの人間です。

EJB 仕様バージョン 3.0 のセクション 21.1.2 (プログラミングの制限) を読むと、コードでのスレッドの使用が禁止されています。これが言語と理論的根拠です...

エンタープライズ Bean は、スレッドの管理を試みてはなりません。エンタープライズ Bean は、スレッドの開始、停止、一時停止、再開、またはスレッドの優先順位や名前の変更を試みてはなりません。エンタープライズ Bean は、スレッド グループの管理を試みてはなりません。

これらの関数は、EJB コンテナー用に予約されています。エンタープライズ Bean がスレッドを管理できるようにすると、ランタイム環境を適切に管理するコンテナーの機能が低下します。

したがって、あなたが言っていることを実行すると、EJB 警察が真夜中にドアをノックしてあなたを連行します。または、アプリが誤動作し、文句を言うとベンダーが笑ってしまうかもしれません。または、悪いことは何も起こりません。

しかし、ダッフィーモが言うように、なぜこれを行うのですか?多数のスレッドによって提供されるスケーラビリティが必要な場合は、MDB でそれを構成できますか? EJB のポイントは、そのようなものを処理することです。

于 2009-05-07T02:21:47.070 に答える
4

MDB がワーカー スレッドを生成する必要がある理由がわかりません。JMS のメッセージ リスナーに関連付けられたスレッド プールがあります。それが仕事をしているはずのスレッドです。

EJB 仕様では、Bean でスレッドを生成しないと規定されています。コンテナーはスレッド化を処理します。これには MDB も含まれます。

リスナーは、キューから取り出したメッセージを処理する必要があります。必要なデータはメッセージに含まれている必要があります。共有する必要性は何ですか?

あなたのアプローチは、推奨される EJB プラクティスに反していると思います。

于 2009-05-07T01:22:36.307 に答える
3

本当の問題は、通常、アプリケーションサーバーが前述のワーカーを単独で生成することです。JMSは、メッセージが少なくとも1つのプロデューサー内で生成されるのと同じ順序で消費されることを保証しますが、MDB仕様は、順序が保持されないことを明示的に示しています(前述のワーカーのため)。JSR-000220 Enterprise JavaBeans 3.0最終リリース(ejbcore)のセクション5.4.11を参照してください。

これを回避するためのポータブルで100%信頼できる方法はありません。労働者の性質上、制御できない競合状態が導入されます。

幸い、ほとんどのアプリケーションサーバーには、プロプライエタリで互換性がありませんが、ワーカーの数を構成する方法があります。

JBossおよびActiveMQの場合、これは機能します。

@PoolClass(value = org.jboss.ejb3.StrictMaxPool.class, maxSize = 1)
@MessageDriven(activationConfig = {
    @ActivationConfigProperty(propertyName = "acknowledgeMode", propertyValue = "Auto-acknowledge"),
    @ActivationConfigProperty(propertyName = "destinationType", propertyValue = "javax.jms.Queue"),
    @ActivationConfigProperty(propertyName = "maxSessions", propertyValue = "1"),
    @ActivationConfigProperty(propertyName = "destination", propertyValue = "TEST.FOO")
})
@ResourceAdapter("activemq-ra.rar")
public class NewMessageBean implements MessageListener { ... }

この場合、「maxSessions」はワーカーの数です。他のJMSプロバイダーとは異なる場合がありますが、それは正しい方向を示しているはずです。

于 2010-05-05T12:46:45.840 に答える
2

前述のように、JMS フレームワークは、スレッドのディスパッチなどのスケジューリングの問題を処理します。これで行うことはすべて、デフォルトの動作よりも劣るというだけでなく、JMS の機能が大幅に制限される可能性があります。

より洗練された JMS ハンドラーは、複数のノード (= サーバー) で動作するように設計されているため、共有メモリ ソリューションを使用すると、1 つのノード上の 1 つの JVM に制限されます。JMS の大きな利点はスケーラビリティであるため、これは残念なことです。

JMSy の解決策として考えられるのは、「cookie」キューを使用して、アクティビティを同期するための単一のダミー「cookie」メッセージにすることです。プロセスが競合するアクティビティを実行するときは、「Cookie」キューから単一のメッセージを「待機して取得」し、競合する作業が完了すると、Cookie をキューに戻します。JMS の魔法は、ほとんどすべてのブロッキング、待機、およびエラー回復を処理します。

于 2009-05-07T02:35:59.733 に答える
0

全員がすでに回答した後、質問の性質が完全に変わったようです。後世のために非常に遅れた応答をチップします。これは、順序付けに使用できる何らかのタイプのメッセージ ID があることを前提としています。あなたは「メッセージを順番に配信しています」と言っていますが、これがどのように達成されているかについては正確には述べていません。

...独自のスレッドを開始していないことを明確にしたため、基本的に、データ @ ID=1 の「作成」とその後の「更新」の間に競合状態があります。作成および/または更新中にデータ @ ID=1 をロックしていると思います。したがって、次の 2 つの可能性があります。

  1. 「データ作成」メッセージが最初に到着します。(1) ロック ID=1、(2) データを作成します。(3) ロックを解除します。(4) 保留中の「更新」を適用します。
  2. 「更新」は「作成」の前に到着します: (1) ロック ID=1、(2) 欠落しているデータを作成します (つまり、「アップサート」を実行します: データが存在しない場合でもデータを挿入します)。(3) ロックを解除します。(4) 保留中の「データの作成」メッセージを無視します (「作成」メッセージは「更新」メッセージよりも低いシーケンス番号を持っています)。
    • メッセージの送信者が更新と挿入を同時に (要求/応答なしで) 送信できる場合、実際にはある種のシーケンス番号が必要です。その場合、「挿入」が到着すると、そのシーケンス番号はその行の現在の値よりも小さくなるため、無視できます。または、'create' メッセージ タイプが 'update' メッセージ タイプと異なる場合、データが既に存在する場合、'creates' は常に無視できます。

あなたの質問は、データを同期する方法だと思います。基本的に、スレッドはオブジェクトを共有し、ミューテックス (相互排除) を作成して、単一のスレッドがデータにアクセスできるようにし、別のスレッドをブロックします。これは、Java の低レベルの同期機能 (「synchronized」キーワード)、またはこれを支援する組み込みクラス (http://java.sun.com/docs/books/tutorial/essential/concurrency/highlevel.html )。

于 2009-12-15T07:58:23.363 に答える