Oracle® Fusion Middleware Oracle WebLogic Server JMSのプログラミング 11g リリース1(10.3.4) B61629-02 |
|
![]() 前 |
![]() 次 |
以下の節では、メッセージ順序単位を使用して、WebLogic JMSの使用時に厳格なメッセージ順序を提供する方法について説明します。
メッセージ順序単位はWebLogic Serverの付加価値機能です。スタンドアロンのメッセージ・プロデューサや、単体として動作するプロデューサのグループは、この機能を使用して複数のメッセージを処理順序に応じた1つの単位にグループ化できます。この単位を順序単位と呼び、この単位からのすべてのメッセージはその作成順に従って処理されます。
以下の節では、JMS仕様に記述されているメッセージ処理と、WebLogic Serverのメッセージ順序単位機能を使用して拡張したメッセージ処理を比較します。
Java Message Service仕様(http://www.java.sun.com/products/jms/docs.html
)ではメッセージ配信の順序付けが規定されていますが、この順序付けは非常に厳格に適用されます。プロデューサの単一のインスタンスとコンシューマの単一のインスタンスの間の順序が定義されますが、以下のような一般的な状況は考慮されていません。
1つのキューにある多数のコンシューマ。第9章「分散宛先の使用」を参照してください。
単一のプロデューサとして動作する、単一のアプリケーション内の複数のプロデューサ。第9章「分散宛先の使用」を参照してください。
メッセージのリカバリまたはトランザクションのロールバック(これらの場合、同じプロデューサからの別のメッセージが、他のコンシューマに配信されて処理される可能性があります)。「処理中にメッセージが遅延した場合の処理」を参照してください。
フィルタおよび宛先ソート・キーの使用。「メッセージ順序単位の高度なトピック」を参照してください。
メッセージ順序単位機能を使用すると、メッセージ・プロデューサや単体として動作するプロデューサのグループが、複数のメッセージを1つの単位にグループ化してメッセージを作成順に処理することが可能になります。単一のメッセージのメッセージ処理は、メッセージが確認応答、コミット、回復、またはロールバックされたときに完了します。メッセージのメッセージ処理が完了するまでは、その順序単位の残りの未処理メッセージがブロックされます。
この節では、順序単位を使用した場合のJMS確認応答モード(http://www.java.sun.com/products/jms/docs.html
)の規則について説明します。
確認応答モードがCLIENT_ACKNOWLEDGE
、AUTO_ACKNOWLEDGE
、またはDUPS_OK_ACKNOWLEDGE
である場合、順序単位のメッセージは並行処理されません。
コンシューマをクローズすると、セッションの確認応答に関係なく、現在のメッセージ処理が完了します。
CLIENT_ACKNOWLEDGE
- アプリケーションがMessage.acknowledge
およびSession.recover
を呼び出すと、順序単位内でどのメッセージの処理が完了したかが示されます。
AUTO_ACKNOWLEDGE
- receive
の呼出しからセッションが正常に返されたとき、または呼び出されたMessageListener
からセッションが正常に返されたときに、セッションが自動的にクライアントによるメッセージの受信を確認応答します。
非同期モード:正常な完了またはonMessage(msg)
の例外は、メッセージが正常に処理されたタイミングを示します。
同期モード:特定のコンシューマ(たとえばコンシューマA)では、consumerA.receive
、consumerA.setMessageListener
、またはconsumerA.close
が発生したときにconsumerA.receive
が完了します。
DUPS_OK_ACKNOWLEDGE
- receive
の呼出しからセッションが正常に返されたとき、または呼び出されたMessageListener
からセッションが正常に返されたときに、セッションが自動的にクライアントによるメッセージの受信を確認応答します。
非同期モード:正常な完了またはonMessage(msg)
の例外は、メッセージが正常に処理されたタイミングを示します。
同期モード:特定のコンシューマ(たとえばコンシューマA)では、consumerA.receive()
、consumerA.setMessageListener()
、またはconsumerA.close()
が発生したときにconsumerA.receive()
が完了します。
NO_ACKNOWLEDGE
- セッションは、処理の順序を保証しません。メッセージは、使用可能な別のコンシューマで並行処理できます。
メッセージ順序単位では、以下の規則に従ってメッセージが配信されます。
順序単位のメンバー・メッセージは、作成された順番でキュー・コンシューマに配信されます。順序単位内でのメッセージの順序は、ソート条件、優先順位、およびフィルタには影響されません。ただし、未コミットのメッセージにRedelivery Delay
または期限切れになっていないTimetoDeliver
タイマーが設定されている場合は、それ以降のメッセージが遅延します。
順序単位メッセージは、一度に1つずつ処理されます。1つのメッセージの処理が完了したら、順序単位内の次のメッセージが配信されます。
分散キューに送信された順序単位メッセージは、分散キューの1つの物理メンバー上にのみ存在します。詳細については、「分散宛先で順序単位を使用する」を参照してください。
同じ順序単位からの未コミットまたは未応答のメッセージはすべて、同じトランザクション(トランザクション非対応の場合は同じJMSSession
)に存在しなければなりません。順序単位内の1つのメッセージが未コミットまたは未応答である場合、他のメッセージは同じトランザクションまたはJMSSession
にのみ配信されます。これにより、同じ順序単位からのすべての未応答メッセージが1つの回復可能な処理内に保持され、ロールバックや回復に関係なく順序を維持できます。
キューに同じ順序単位からの複数のメッセージがある場合、それらがすべて処理されるまでは、そのキューに次のメッセージを配信したり、キュー・コンシューマにそれらのメッセージを配信したりすることはできません。
たとえば、メッセージがM1からMnまであるとします。
これらのメッセージがトランザクションの一部として配信され、そのトランザクションがロールバックされた(処理が完了した)場合、メッセージM1からMnが使用可能なコンシューマに配信されます。
これらのメッセージがトランザクション外で配信されて回復された(処理が完了した)場合、メッセージM1からMnが使用可能なコンシューマに配信されます。
これらのメッセージがトランザクション外で配信されて確認応答された(処理が完了した)場合、未配信のメッセージMn+1が使用可能なコンシューマに配信されます。
この節では、オンライン書店への本の注文に基づいて、メッセージ順序単位の単純なケース・スタディを行います。
XYZオンライン書店は、JMSを使用して顧客の注文を処理する単純な処理設計を実装しています。JMS処理システムは、以下から構成されます。
キュー(Queue1)に送信するメッセージ・プロデューサ
Queue1からのメッセージを処理する複数のメッセージドリブンBean (MdbX、MdbYなど)
注文および注文のステータス情報を格納するデータベース(myDB)
Joeは、XYZオンライン書店の自分のアカウントにログインして欲しい本を検索します。本を選び、会計に進んで、販売トランザクションを完了します。ここでJoeは、以前に同じ本を買っていたことに気付き、注文を取り消します。ところが1週間後、その本がJoeのもとに届いてしまいます。
Joeの注文シナリオでは、注文の取消しメッセージが、注文メッセージよりも前に処理されました。その結果、買いたくなかった本が届けられてしまいました。ここでは、Joeの注文が処理された手順について説明します。
次の図とそれに対応する各アクションは、Joeの注文がどのように処理されたかを示します。
Joeが、ショッピング・カートから注文ボタンをクリックします。
注文メッセージ(メッセージA)がQueue1に配置されます。
Joeが注文を取り消します。
注文取消しメッセージ(メッセージB)がQueue1に配置されます。
MdbXがQueue1からメッセージAを取得します。
MdbYがQueue1からメッセージBを取得します。
MdbYが取消しメッセージをデータベースに書き込みます。対応する注文メッセージがないため、どの注文メッセージもデータベースから削除されません。
MdbXが注文メッセージをデータベースに書き込みます。
本の発送を処理するアプリケーションがデータベースを読み取り、注文メッセージを見てJoeの家への発送を開始します。
Java Message Service仕様(http://www.java.sun.com/products/jms/docs.html
)にはメッセージ配信の順序付けが規定されていますが、プロデューサの単一のインスタンスとコンシューマの単一のインスタンスの間でのメッセージ配信の順序付けしか規定されていません。Joeのケースでは、Queue1のメッセージを複数のメッセージドリブンBean (MDB)が消費できるため、メッセージの処理順序はまったく保証されなくなっていました。
Joeの注文に関わるすべてのメッセージが常に正しく処理されるようにするには、XYZ書店のシステム管理者がユーザー・セッションに基づいてメッセージ順序単位を構成して、ユーザー・セッションからのすべてのメッセージに順序単位名属性を持たせ、値としてセッションIDを設定します。「順序単位の作成方法」を参照してください。WebLogic Serverでは順序単位内のメッセージが並行処理されることはないため、Joeのユーザー・セッションの間に作成されたすべてのメッセージは作成された順番どおりに処理されます。
次の図とそれに対応する各アクションは、メッセージ順序単位を使用した場合にJoeの注文がどのように処理されるかを示します。
Joeが、ショッピング・カートから注文ボタンをクリックします。
注文メッセージ(メッセージA)がQueue1に配置されます。
Joeが注文を取り消します。
注文取消しメッセージ(メッセージB)がQueue1に配置されます。
MdbXがQueue1からメッセージAを取得します。
MdbYがQueue1からメッセージBを取得します。
MdbYのメッセージBは、MdbXが注文メッセージを応答確認するまではブロックされます。「処理中にメッセージが遅延した場合の処理」を参照してください。
メッセージAがコミットされ、データベースに書き込まれます。
メッセージBがコミットされ、データベースに書き込まれます。
対応する注文メッセージが存在するため、Joeの注文はデータベースから削除され、本が届けられることはありません。
以下の節では、メッセージ順序単位を作成する方法について説明します。「順序単位によるメッセージ配信」および「メッセージ順序単位の高度なトピック」も参照してください。
WLMessageProducer
インタフェースのsetUnitOfOrder()
メソッドを使用して、プロデューサを順序単位名に関連付けます。
次の例では、順序単位名属性の値がmyUOOnameに設定されます。
getProducer().setUnitOfOrder("myUOOname");
プロデューサを順序単位名に関連付けると、プロデューサをクローズするか、プロデューサと順序単位の関連付けが解消されるまで、このプロデューサが送信するすべてのメッセージは順序単位として処理されます。
次のコードでは、プロデューサと順序単位の関連付けの例を示します。
ここでは、JMS接続ファクトリやJMS宛先を構成して、メッセージ順序単位を有効にする方法について説明します。
以下のいずれかの方法で、JMS接続ファクトリと宛先を構成してメッセージ順序単位を有効にします。
接続ファクトリを構成して、常にユーザー生成の順序単位名を使用するようにします。この場合、その接続ファクトリから作成されたすべてのプロデューサで順序単位が有効化されます。Oracle WebLogic Server管理コンソール・オンライン・ヘルプの接続ファクトリの順序単位パラメータの構成に関する項を参照してください。
接続ファクトリを構成して、セッションごとに常にシステム生成の順序単位名を使用するようにします。Oracle WebLogic Server管理コンソール・オンライン・ヘルプの接続ファクトリの順序単位パラメータの構成に関する項を参照してください。
クライアントからWLProducer.setUnitOfOrder(name)
を呼び出して、プロデューサの接続ファクトリの初期設定を変更します。
スタンドアロンの宛先または分散宛先を構成して、常にシステム生成の順序単位名を使用するようにします。管理コンソール・オンライン・ヘルプの以下のトピックを参照してください。
従来のJMSアプリケーションと相互運用する場合には、接続ファクトリまたは宛先に管理的に順序単位を構成する必要があります。この方法は、コードを変更することなく、メッセージが作成順に処理されるようにするための単純なメカニズムを提供します。
順序単位は、名前属性によって特定されます。宛先内では、順序単位名属性に同じ値が設定されているメッセージが、同じ順序単位に属します。名前は、システムからでもアプリケーションからでも指定できます。同じ順序単位内のすべてのメッセージは、同じ名前を共有します。「順序単位の作成方法」を参照してください。
順序単位の名前属性は、以下の規約に準拠させる必要があります。
順序単位名属性の有効な値は、nullでも空でもない文字列でなければなりません。
システム生成の順序単位名は、タイムスタンプ・ベースで統計的に一意になります。
アプリケーションからは、独自の順序単位名を指定できます。たとえば、WebLogic Integrationアプリケーションではワークフロー名を使用したり、Webサービス・アプリケーションでは会話名を使用したりできます。
メッセージ順序単位には、独自のネームスペースがあります。順序単位は、他の名前付きオブジェクトに対して一意にする必要はありません。たとえば、Fooというキューが存在する場合でも、Fooという順序単位名は有効です。
メッセージ順序単位のスコープは、単一の宛先に限定されます。2つの宛先のそれぞれの順序単位を同じ名前にしても構いません。
1つまたは複数のプロデューサが、同じ文字列を使用して順序単位を作成することで、同じ順序単位名のメッセージを送信できます。順序単位名は、配信されたメッセージから抽出されます。次に例を示します。
msg.getStringProperty("JMS_BEA_UnitOfOrder");
したがって、システム生成の順序単位名は、複数のプロデューサで使用できます。このパラダイムは、アプリケーションによって割り当てられた順序単位名にもそのまま適用できます。情報が一元的にシリアライズされているのが最も効率的です。したがって、順序単位名としては会話IDのようなプロパティのみを格納するようにしてください。このパラダイムは、メッセージが順序単位非対応のJMSプロバイダ(WebLogic 9.0より前のリリースやWebLogic以外のJMSプロバイダ)で送信された場合には適用されません。
以下の節では、より高度で複雑な状況での順序単位によるメッセージ処理方法について説明します。
メッセージ処理の間には、通常であればメッセージの処理順序が変更されるような状況が数多く発生します。以下に、メッセージの配信準備を整えることができない典型的なメッセージ処理状態を示します。
メッセージが、コミットされていないトランザクション内にあります。
メッセージのTimeToDeliver
値により、TimeToDeliver
間隔が経過するまでメッセージを配信できません。
コンシューマが回復またはロールバックを呼び出したため、RedeliveryDelay
間隔が経過するまではメッセージを再配信できません。
たとえば、メッセージAとメッセージBが同じ順序単位に届き、上に挙げたような状況でメッセージAを配信できないとします。この場合、メッセージBの配信を遅延させる要因がなくても、順序単位内のメッセージAが配信されるまではメッセージBを配信することはできません。
フィルタと順序単位を使用すると、予期しない動作が発生することがあります。たとえば、メッセージAからZが、同じキューの同じ順序単位にあるとします。Consumer1にはフィルタが設定されており、メッセージA、B、およびCがそのフィルタ条件を満たすため、これらのメッセージがConsumer1に配信されます。
メッセージDからZは、メッセージA、B、およびCが確認応答されるまでは配信できません。
メッセージA、B、およびCが確認応答または回復されます。
メッセージDがメッセージ配信システムから利用可能な状態になります。
メッセージDはフィルタ条件を満たさないため、Consumer1に配信されることはありません。
メッセージEからZは、メッセージDが処理されるまでは配信できません。
メッセージDを含むトランザクションは、ロールバックされる必要があります。
メッセージDが処理されると、メッセージEからZを配信できます。
詳細については、「メッセージのフィルタ処理」を参照してください。
宛先ソート・キーは、メッセージが順序単位の一部でない場合や、同じ順序単位の一部でない場合に、コンシューマにメッセージを配信する順序を制御します。
たとえば、届いたメッセージAおよびBがキュー上の同じ順序単位に含まれており、優先度の降順でソートされていて優先度はメッセージAよりメッセージBのほうが高いとします。
メッセージBのほうがメッセージAよりも優先度が高くても、これらのメッセージは同じ順序単位に含まれているため、メッセージAが処理されるまではメッセージBを配信できません。次に届いたメッセージCは、順序単位が設定されていないか、メッセージAと同じ順序単位には含まれていないとします。この場合、メッセージCの優先度設定とメッセージAの優先度設定によって配信順序が決まります。『Oracle Fusion Middleware Oracle WebLogic Server JMSの構成と管理』の「基本JMSシステム・リソースの構成」を参照してください。
すでに「JMS仕様に準拠したメッセージ処理」で説明したように、アプリケーションで分散キューを使用している場合、Java Message Service仕様(http://www.java.sun.com/products/jms/docs.html
)のメッセージ配信の順序付けは保証されません。WebLogic JMSでは、分散宛先がターゲット指定されている複数のメッセージに同じ順序単位が設定されている場合は、それらのメッセージを同じ分散宛先メンバーに転送します。メンバーは、宛先の順序単位構成に基づいて選択されます。
WebLogicパス・サービスを構成すると、順序単位に含まれるメッセージをその宛先リソース(共通分散宛先のメンバー)にルーティングするために必要な情報を格納する永続マップを提供できます。共通分散宛先のWebLogicパス・サービスが構成されていない場合、メンバー宛先へのルーティング・パスは、分散キューの実行時のロード・バランシング・ヒューリスティックに基づいて決定されます。
WebLogicパス・サービスが構成されていない場合、メンバー・キューへのデフォルトのルーティング・パスは、メッセージ順序単位名と共通分散キュー・メンバーのハッシュ・コードに基づいて選択されます。このルーティング・メカニズムの利点は、分散キュー・メンバーへのルートがすばやく計算され、クラスタ内の永続ストレージを必要としない点です。
メッセージ順序単位とハッシュ・ベースのルーティングを実装する際には、以下のことに留意してください。
順序単位が関連付けられている分散キュー・メンバーが分散キューから削除されると、新しいメッセージは別の分散キュー・メンバーに送信され、古いメッセージとそのメッセージとの継続性は失われます。
順序単位が関連付けられている分散キュー・メンバーにアクセスできない場合は、メッセージを送信しているプロデューサがJMSOrderException
をスローし、メッセージは別の分散キュー・メンバーにはルーティングされません。この例外がスローされるのは、JMSメッセージ・システムが必要なサービス品質を満たすことができないからです。特定の順序単位に対しては、1つの分散宛先メンバーだけがメッセージを消費できます。
順序単位を割り当てても、同じトピック上の2つのサブスクライバによるメッセージの並行処理は可能です。トピックの個々のサブスクライバには独自の宛先とメッセージ・リストがあるため、コンシューマが1つのキューと同様に、メッセージは本番時に割り当てられた順序単位に従ってすべてのサブスクライバによって処理されます。
アプリケーションが分散トピックのメンバーに直接送信を行う場合、物理的トピック間のメッセージのルーティングが、順序単位に影響を与える可能性があります。処理の順序が正しくなるようにするには、メッセージが論理分散トピックを介して送信される(つまり、宛先が分散トピックのJNDI名を使用して取得される)ことをアプリケーションで保証する必要があります。その結果、WebLogic Serverでは、同じ順序単位を持つメッセージであれば、その分散トピック・メンバーへのパスが同じであることが保証されます。
WebLogic ServerメッセージドリブンBeanの実装は、単一のトピック・サブスクリプションおよびJMSセッションの着信メッセージ・ストリームの並行処理を可能にするため、EJBおよびJMS仕様の要件に準拠していません。この並行処理では、順序単位は考慮されないため、処理が正しく順序付けられていることを保証する必要があります。正しく順序付けするには、2つの方法があります。1つは各メッセージをそれ専用のJTAトランザクション内で処理する方法で、もう1つはプール・サイズを1に設定して並行処理を無効にする方法です。
トピックおよびメッセージドリブンBeanで順序単位を使用する場合は、以下のいずれかを行う必要があります。
まず、JTAトランザクションを使用するようMDBを構成します。万一トランザクションのオーバーヘッドが許容できない場合は、プール・サイズを1に設定します。
最も簡単な方法は、JTAトランザクションを使用することです。この方法は、処理オーバーヘッドが生じますが、WebLogic Serverには高度に最適化されたトランザクション・エンジンが存在するため通常は低く抑えられ、アプリケーションは順序単位が異なるメッセージを並行処理することでメリットを得ることができます。アプリケーションの使用例によっては、JTAトランザクションが有効な場合があります。たとえば、JMSメッセージの送信やデータベースの更新など、他の操作との原子性を維持した相互作用を保証することが必要な場合です。
プール・サイズを1に設定すると、より効率的な非トランザクション・メッセージングを使用できますが、並行処理では非常に大きな効果をもたらします。
JMSメッセージ管理を使用すると、JMSの管理者は実行中のJMSサーバー内のほとんどのメッセージを移動したり削除したりできます。つまり、管理者は「順序単位によるメッセージ配信」に示した配信規則を侵害することができます。
たとえば、順序単位fooに属すメッセージA、B、C、およびDが生成されて宛先D1に送信された場合、以下の点に留意してください。
メッセージCおよびDを宛先D2に移動すると、両方の宛先からのメッセージが並行して処理される可能性があります。
メッセージBおよびCを宛先D2に移動すると、メッセージAとメッセージBおよびCが並行して処理される可能性があります。メッセージAが処理された後に、メッセージDが配信可能になります。
メッセージ順序の維持に依存するアプリケーションでは、1つの順序単位内のすべてのメッセージを単一のグループとして移動するのがベスト・プラクティスです。
順序単位の配信規則が維持されるようにするには、次の手順を使用します:
ソース宛先とターゲット宛先を休止させます。
移動する順序単位内のすべてのメッセージを選択します。
選択したメッセージをターゲット宛先に移動します。必要に応じて、メッセージを処理したい順序にソートします。
ソース宛先とターゲット宛先を再開します。
詳細は、『Oracle Fusion Middleware Oracle WebLogic Server JMSの構成と管理』の「WebLogic JMSのトラブルシューティング」を参照してください。
WebLogicストア・アンド・フォワードでは、メッセージ順序単位がサポートされます。たとえば、Fooという順序単位のメッセージを送信するストア・アンド・フォワード・プロデューサがあるとします。このプロデューサは、切断して別の接続で再接続すると、Fooという順序単位を作成してメッセージの送信を継続します。再接続の前と後に送信されたすべてのメッセージは、同じストア・アンド・フォワード・エージェントを介して転送されます。『Oracle Fusion Middleware Oracle WebLogic Serverストア・アンド・フォワードの構成と管理』を参照してください。
ソース宛先とターゲット宛先の両方がWebLogic Server 9.0以降のメッセージング・ブリッジ・インスタンスである場合は、メッセージング・ブリッジのPreserveMsgProperty
を有効にすると、順序単位名を維持してプロデューサの順序単位を設定できます。Oracle Fusion Middleware Oracle WebLogic Server WebLogic Tuxedo Connector管理ガイドを参照してください。
この節では、順序単位を使用する際に考慮すべきその他の一般情報を示します。
ブラウザの列挙値には、現在のキュー・メッセージがブラウザによって受信されるべき順序で格納されます。ここでいう「現在」とは、配信可能になっているメッセージを指します。通常は、順序単位内の最初のメッセージが配信可能になっています。同じ順序単位内の後続のメッセージは配信可能にはなっていません。
順序単位機能の組合せによっては、競合する順序単位メッセージ・ストリームが不足することがあります。これには、順序単位名が異なる処理中メッセージの数よりコンシューマの数が多くなったために、リソースが十分に利用されなくなった場合も含まれます。システムのパフォーマンスを最適化し、リソースが十分に利用されない状態を防ぐには、最大の負荷でアプリケーションをテストする必要があります。
このリリースのWebLogic Serverメッセージ順序単位では、順序単位非対応のJMSプロバイダ(WebLogic 9.0より前のリリースやWebLogic以外のJMSプロバイダ)に接続されているクライアントはサポートされません。