Oracle® Fusion Middleware Oracle WebLogic Server JMSのプログラミング 11g リリース1(10.3.3) B61629-01 |
|
![]() 前 |
次の項では、宛先が使用可能または使用不可の場合に通知を取得する手段を提供するJMSDestinationAvailabilityHelper
APIの使用方法について説明します。
注意: このガイドには、経験豊富なJMS開発者向けの高度な情報が記載されています。分散キューと相互運用する際はメッセージドリブンBeanを使用することをお薦めします。MDBコンテナは、分散キューのすべてのメンバー間で内部コンシューマを必要に応じて自動的に作成して閉じます。また、セキュリティ、スレッド化、プーリング、アプリケーション・ライフサイクル、自動再接続、トランザクションのリスト化も処理します。MDBを使用できない場合、より簡単な回避策(分散キューでコンシューマをリバランスするようにコンシューマを定期的に再起動したり、メッセージの順序付けやパフォーマンスを気にしない場合は、分散キューの転送オプションを有効にしたりするなど)も検討できます。 |
分散キュー(DQ)は、単一の論理宛先としてアクセスされるJMS物理キューのグループです。メッセージはメンバー間でロード・バランシングされ、クライアントはメンバー宛先間でフェイルオーバーできます。
MDBを利用しない分散宛先ユーザーの場合、コンシューマ・アプリケーションに関する問題が生じることがあります。たとえば、次のような問題があります。
すべてのDQメンバーをコンシューマで確実に処理できません。
コンシューマのないDQメンバーに未処理のメッセージが蓄積されます。
JMSサーバーの移行時、WebLogic Serverの再起動時、あるいはDQメンバーに変更が生じるイベントの際にDQコンシューマが自動的にリバランスしません。
こうした使用事例を解決するために、WebLogic Serverには、JMS宛先可用性ヘルパーAPIが用意されています。
コンシューマ・ロード・バランシングについて説明する前に、プロデューサ・ロード・バランシングの基本事項とベスト・プラクティスを最初に確認しておくと便利です。
JMSプログラムは、次の3つの段階でメッセージ送信を設定します。
クライアントは、JMS接続ファクトリを使用してWebLogicへのJMS接続を作成します。
クライアントはこの接続を使用して、JMSのセッションとセンダーを作成します。
クライアントは、このセンダーを使用してメッセージを送信します。
WebLogic JMSでは、クライアントが接続するWebLogicサーバーはクライアントの接続ホストと呼ばれ、メッセージは常にセンダーからその接続ホストを介して、接続ホストと同じクラスタ内の宛先にルーティングします。接続は、その有効期間中は接続ホストに固定されます。
WebLogic接続ファクトリは、1つ以上のWebLogicサーバーでターゲット指定できます。接続ファクトリがターゲット指定される同じWebLogicサーバーでクライアントが実行している場合、ファクトリは常に、クライアントと同じサーバーの接続ホスト(接続はローカル)で接続を返します。一方で、接続ファクトリのターゲットに含まれるWebLogicサーバーでクライアントが実行していない場合、ファクトリはターゲット間で自動的にロード・バランシングして、そのいずれかに接続を返します。
センダーが分散宛先で機能する場合、各メンバーのJNDI名に送信するのではなく、DQのJNDI名(その論理名)に常に送信します。これにより、ロード・バランシング動作の自動化が可能になります。
DQに対するセンダーのデフォルト動作では、メンバーがセンダーの接続ホストで実行する場合、すべての送信メッセージはいずれかのローカル・メンバーに送信されます。それ以外の場合、メッセージはすべてのメンバー間でラウンドロビンします。
ローカル・メンバーがセンダーの接続ホストに存在する場合でも、同じDQセンダーのメッセージをすべてのアクティブなメンバー間でラウンドロビンするようにするには、Server Affinity
をfalse
に、Load Balance
をtrue
に設定してカスタム接続ファクトリを使用します。
次の項では、JMSDestinationAvailabilityHelper
APIの使用方法について説明します。
クライアントのjavax.jms
APIを使用してコンシューマを作成し、DQ論理JNDI名を指定した場合、コンシューマはアクティブなDQメンバーにロード・バランシングされ、その存続期間中は該当メンバーに固定されます。すべてのコンシューマの作成後に新しいメンバーがアクティブになる場合、新しいメンバーにコンシューマはありません。
JMSDestinationAvailabilityHelper
APIにより、宛先が使用可能または使用不可になる場合に通知を取得する手段が提供されます。これらの通知は、アプリケーションを初期化したときに使用不可のメンバーが存在する場合でもすべてのDQメンバーでアプリケーションがコンシューマを作成する際に役立ちます。同じメカニズムを使用して、他のタイプの宛先(WebLogic分散宛先のみではなく、通常の宛先や外部ベンダーの宛先)の可用性を検出することもできます。
アプリケーションは、JNDIコンテキスト・パラメータと宛先のJNDI名を指定して、ヘルパーに通知リスナーを登録します。DQについては、メンバーが使用可能および使用不可になる場合、アンデプロイされる場合、新しいメンバーとして追加される場合、移行、停止、再起動する場合に、ヘルパーによってリスナーに通知されます。
WebLogic ServerのMDBは、両方のローカルMDB (DQと同じクラスタにデプロイされたMDB)とリモートMDB (DQをホストするクラスタとは別のクラスタにデプロイされたMDB)に同じメカニズムを内部で使用することに注意してください。MDBには、JMSDestinationAvailabilityHelper
APIが提供する同じ動的適応性をDQトポロジ変更に対して実現する即時利用可能なソリューションがあります。
JMSDestinationAvailabilityHelper
APIを使用するアプリケーションは、次の一般的なステップに従います。
下記のステップ3の動作を実現するため、weblogic.jms.extensions.DestinationAvailableListener
インタフェースを実装します。
JNDIコンテキスト・プロパティ(通常はURLとコンテキスト・ファクトリのみ)、宛先のJNDI名、リスナー・インスタンスを指定して、ヘルパーに関連事項を登録します。クライアントがDQと同じクラスタで実行している場合はURLを指定しないでください。
import java.util.Hashtable; import javax.naming.Context; import weblogic.jms.extensions.JMSDestinationAvailabilityHelper; Hashtable contextProps = new Hashtable(); contextProps.put(javax.naming.Context.PROVIDER_URL, myURL); contextProps.put(Context.INITIAL_CONTEXT_FACTORY, "weblogic.jndi.WLInitialContextFactory"); JMSDestinationAvailabilityHelper dah = JMSDestinationAvailabilityHelper.getInstance(); RegistrationHandler rh = dah.register( contextProperties, destinationJNDIName, myDestinationAvailableListener )
リスナー・コールバックを処理します。コールバックは単一スレッド化されるため、2つのコールバックが同時に生じることはありません。
onDestinationsAvailable()
- 通常は最初の通知。このコールバックの実装は、指定の各宛先でゼロ以上のコンシューマを作成すると反応するのが一般的です。これが失敗した場合、定期的に再試行します。
onDestinationsUnavailable()
- このコールバックは、通常、宛先で既存のコンシューマを破棄する場合に使用されます。
onFailure()
- このコールバックは、通常、生じた失敗のログを記録する場合に使用されます。ヘルパーは引き続き内部で再試行し、以降のコールバックを行いますが、管理者は失敗を確認する必要があります。ヘルパーは、最善を尽くして、繰り返される同じ失敗に対してonFailure()
を一度呼び出します。
完了したら、rh.unregister()
を呼び出して宛先の関連事項の登録を解除します。
前述のように、onDestinationsAvailable()
通知は、スタンドアロンの宛先、外部宛先、分散宛先のメンバーが使用可能になることを示します。通知はDestinationDetail
インスタンスのリストで構成され、キー情報は各DetailでgetDestinationType()
、getJNDIName()
、isLocalWLSServer()
、isLocalCluster()
を呼び出すことで取得されます。
宛先の詳細は、呼出し元が行うアクションの決定に役立ちます。宛先のタイプがDD_QUEUE
の場合、詳細のgetJNDIName()
メソッドにより、特定のDQメンバーのJNDI名が返されます。呼出し元はアプリケーション・コンシューマのインスタンスをメンバーにデプロイできる場合とできない場合があります。宛先のタイプがPHYSICAL
またはFOREIGN
の場合、アプリケーションは宛先を通常の宛先として扱います。
特にDQで使用する場合、DestinationDetail
のコロケーション・フラグを利用することを強くお薦めします。宛先のコロケーションの性質を判断するには、isLocalWLSServer()
とisLocalCluster()
を呼び出します。「ローカル・サーバー・コンシューマのベスト・プラクティス」を参照してください。
APIとそのメソッドの詳細は、Oracle Fusion Middleware Oracle WebLogic Server APIリファレンスのDestinationDetailに関する項を参照してください。
次の項では、コンシューマ・コンテナのベスト・プラクティスのガイドラインを示します。
アプリケーションのデプロイメント時にJMSDestinationAvailabilityHelper
に登録します。ヘルパーがリスナーでonFailure()
コールバックを呼び出す場合、デプロイメントを失敗しないでください(断続的な失敗になると想定されます)。
アプリケーションのアンデプロイメント時にJMSDestinationAvailabilityHelper
への登録を解除します。
クライアントが宛先と同じサーバーまたは同じクラスタで実行している場合、ヘルパーへの登録やJNDIコンテキストの作成時にURLを指定しないでください。これにより、ヘルパーは確実にローカル・コンテキストを作成します。
isLocalCluster()
またはisLocalServer()
がtrue
を返しても、URLを指定した場合(この場合URLは不要)、1つの警告ログと見なします。
onFailure()
通知で報告されるエラーのログを記録するため、アプリケーションの開発者は、構成/アプリケーションのエラーを修正することができます。同じ例外のログを繰り返し記録することは避けてください。ヘルパーは引き続き内部で再試行し、成功または異なるタイプの失敗に対して以降のコールバックを行いますが、管理者は失敗を確認する必要があります。エラーは、不正なURL、無効なセキュリティ情報、存在しない宛先などのアプリケーションまたは管理上のエラーが原因で発生します。また、JNDIコンテキストのホストまたは宛先が一時的に使用不可になる場合にも発生します。
JMS呼出しが例外をスローするか、JMS接続例外リスナーが接続の失敗を報告した場合、接続を閉じます。すべてのリソースの誤りが修正されたら、すべてのリソースを定期的に再初期化します。再初期化には、通常、コンテキストの作成、JNDIルックアップの実行、接続、セッション、コンシューマの作成が必要です。
失敗後すぐに再試行することは避けてください。かわりに数秒ごとに定期的に再試行して、サーバーがオーバーロードしないようにします。
JNDIルックアップの複数のスレッドで同じJNDIコンテキストを共有します。
アンデプロイ時にコンテキストでclose()
を呼び出して、メモリー・リークを防止します。
コンテキストでclose()
を呼び出して、失敗時(ルックアップの失敗を含む)に再作成します。
JMS接続の場合、標準のJMS接続「例外リスナー」を必ず登録します。
onException()で接続を閉じてJNDIルックアップを定期的に再試行し、JMS接続を再作成して別のスレッドでコンシューマを設定します。
アンデプロイ時に接続を閉じて、メモリー・リークを防止します。
複数のセッション間でWebLogic Server接続を共有するのではなく、セッションにつき1つの接続を作成することを検討します。WebLogic Serverでは、複数の接続によりロード・バランシング機能が向上します。WebLogic Serverを使用する場合、パフォーマンス・ペナルティはありませんが、一部の外部ベンダーは接続ごとにTCP/IPソケットや同様の高価なリソースを作成するため、外部ベンダーによる予想外のオーバーヘッドが生じる場合があります。
Oracle Fusion Middleware Oracle WebLogic Server APIリファレンスのJMSDestinationAvailabilityHelperには、使用可能な各種メソッドの使用法や動作に関する詳細があります(次の項で説明する相互運用性ガイドラインに関する詳細を含む)。
パブリックJMS宛先可用性ヘルパーAPIは、AS11gR1PS2(WebLogic Serverバージョン10.3.3)以降のクライアントとサーバーで利用できます。
DAヘルパーに通知リスナーを登録する際に指定するコンテキスト・プロパティは、外部ベンダーや旧バージョンのWebLogic Serverのコンテキストを含む有効なJNDIコンテキストに解決できます。
外部(WebLogic以外の)コンテキストの場合、外部JNDIベンダーのクラスは現在のクラスパス内に存在する必要があります。また、Context.INITIAL_CONTEXT_FACTORY
プロパティは、外部ベンダーのJNDIコンテキスト・ファクトリのクラス名を参照する必要があります。
JMSDestinationAvailabilityHelper
APIは、JNDIコンテキストに登録できるどのタイプの宛先(非分散宛先、外部ベンダーの宛先など)でも機能します。ただし、使用不可の通知は、DQメンバーに対してのみ生成され、DestinationDetail
の特定のフィールドはDQメンバーにのみ適用されます。使用不可の通知は、外部宛先には適用されません。
使用不可の通知は、DQタイプの宛先にのみ適用されます。
DAヘルパーがWebLogic Server 9.0以降のDQと相互運用する場合、DQのメンバーごとに通知が生成されますが、9.0以前のバージョンと使用する場合、DQ宛先の論理JNDI名を含む単一のDestinationDetail
通知のみが生成され、getDestinationType()
はPHYSICAL
を返します。
したがって、WebLogic Server 9.0以前のDQは通常の宛先として扱われるため、冒頭で示した問題が結果的に生じます。
コンシューマ・アプリケーションは、WebLogic Serverの同じJVMで実行する場合とそうではない場合があります。これらは、それぞれサーバー側コンシューマおよびスタンドアロン・コンシューマと呼ばれます。
JMS UDQコンシューマがWebLogic Serverまたはクラスタにデプロイされる場合、アプリケーションはUDQと同じクラスタ/サーバー、または別のクラスタで実行できます。これら2つの異なるアプリケーション構成を、それぞれローカル・ケースおよびリモート・ケースと言います。
サーバー側アプリケーションでは可能なかぎりWebLogic Server MDBを使用することを強くお薦めします。
なんらかの理由によりアプリケーション・アーキテクチャでMDBを使用できないアプリケーションの場合、次のガイドラインに従ってください。
UDQに送信されるすべてのメッセージをアプリケーションで受信するには、アプリケーションがメンバーJNDI名を使用してUDQのメンバーごとに1つのコンシューマを作成する必要があります。このためには、アプリケーションがドメインのトポロジとUDQ構成を把握する必要があります。この場合、JMSDestinationAvailabilityHelperが役立ちます。
一般的な戦略では、特定のアプリケーションの各デプロイメント・インスタンスはJMSDestinationAvailabilityHelper
に登録する必要があります。リスナーはメンバーの可用性に関する通知を受け取ります。
onDestinationsAvailable()
通知を受け取ると、アプリケーションは使用可能なすべてのメンバーのDestinationDetail
インスタンスのリストを取得します。その後、リストのメンバーごとにメンバーのJNDI名を使用して1つ以上のコンシューマ・インスタンスを作成する必要があります。リモート・コンシューマの場合、アプリケーションの各インスタンスは、UDQのメンバーごとにコンシューマを作成する必要があります。ローカル・コンシューマの場合、ローカルUDQメンバーでのみコンシューマを作成します。詳細は、「ローカル・サーバー・コンシューマのベスト・プラクティス」を参照してください。
onDestinationsUnavailable()
通知を受け取ると、アプリケーションは、最後の通知以降に使用不可になるすべての宛先のDestinationDetail
インスタンスのリストを取得します。その後、リストのメンバー宛先ごとに、メンバー宛先に対して以前に作成されたコンシューマを探し、そのコンシューマを閉じます。
アプリケーションがJMS分散宛先と同じクラスタにデプロイされる場合、可能なかぎり、UDQをホストする同じセットのサーバーにアプリケーションをデプロイする必要があります。この構成のベスト・プラクティスとして、アプリケーションはローカル・メンバーからのメッセージのみを受け取り、DestinationDetail
isLocalWLSCluster()
呼出しとisLocalWLSServer()
呼出しを使用してローカル・メンバーを決定できます。この方法では、すべてのメッセージがローカルになり(ネットワーク呼出しでメッセージが転送されない)、すべてのメンバーがコンシューマで処理されるため、パフォーマンスが向上します。
一部の使用事例では、バランスの取れていないキューの負荷に関して、ローカル・サーバーの最適化ネットワークを節約するよりも、クラスタのすべてのJVM間でメッセージ処理を分散するメリットの方が上回ります。これは特に、メッセージのバックログがクラスタ全体で不規則に生じ、メッセージ処理に費用がかかる場合に関連します。このような使用事例では、リモート・コンシューマに対して一般的な戦略モデルを支持して最適化を回避してください。