WebLogic JMS プログラマーズ ガイド
![]() |
![]() |
![]() |
![]() |
以下の節では、可用性の高いアプリケーションを設計する上で必要となる分散送り先の概念と機能について説明します。
分散送り先は、クライアントから単一の論理的な送り先としてアクセスできる送り先 (キューまたはトピック) のセットです。分散送り先は、以下の特性を備えています。
分散送り先を使用するアプリケーションは、単純な送り先を使用するアプリケーションより可用性が高くなります。WebLogic JMS は、クラスタ内の分散送り先のメンバーのためのロード バランシングとフェイルオーバの機能を備えているからです。一度適切にコンフィグレーションすると、プロデューサとコンシューマがその分散送り先に対してメッセージを送受信できるようになります。WebLogic JMS は、分散送り先のすべてのメンバー間でメッセージングの負荷を分散します。サーバの障害で送り先メンバーがアクセスできなくなった場合、トラフィックはセット内の他のアクセス可能な送り先メンバーにリダイレクトされます。送り先メンバーのロード バランシングの詳細については、「分散送り先のコンフィグレーション」を参照してください。
分散送り先は、システム管理者が Administration Console を使用して作成します。詳細については、「分散送り先のコンフィグレーション」を参照してください。
WebLogic Server では、以下の 2 種類の分散送り先がサポートされます。
共通分散送り先 (UDD) では、各メンバーには、すべての分散送り先パラメータ (重み、セキュリティ、永続性、ページング、割り当てなどに関するパラメータ) の一貫したコンフィグレーションが設定されます。
BEA では、UDD を使用することを推奨しています。UDD を使用すると、送り先のメンバーを作成したり指定したりする必要がなくなるためです。代わりに、WebLogic Server によって、UDD の対象となる JMS サーバ上に必要なメンバーが均等に作成されます。この機能により、新しいメンバーを追加したりメンバーを削除したりしたときに、UDD が動的に更新されます。
たとえば、UDD をクラスタに対象指定した場合、そのクラスタ内のすべての JMS サーバに UDD メンバーがコンフィグレーションされます。新しい JMS サーバを追加すると、UDD に新しい UDD メンバーが動的に追加されます。同様に、JMS サーバを削除すると、対応する UDD メンバーが UDD から削除されます。これにより、コンフィグレーション エラーによるボトルネックが解消され、アプリケーションの可用性を高めることができます。詳細については、「分散送り先のコンフィグレーション」を参照してください。
重み設定された分散送り先では、各メンバーには、すべての分散送り先パラメータ (重み、セキュリティ、永続性、ページング、割り当てなどに関するパラメータ) の一貫したコンフィグレーションが設定されません。
BEA では、重み設定された分散送り先を UDD に変換することを推奨しています。これは、重み設定によって追加のメッセージ負荷や容量をサポートするメンバーを作成すると、管理上の柔軟性が失われることがあるためです。重み設定された送り先は、メンバーのコンフィグレーションに一貫性がないためクラスタに矛盾なくデプロイすることができず、予期しない管理上の問題やアプリケーションの問題につながる可能性があります。
詳細については、「分散送り先のコンフィグレーション」を参照してください。
分散送り先は、物理的な JMS 送り先メンバー (キューまたはトピック) のセットで、単一の JNDI 名でアクセスされます。そのため、JNDI を使用することで分散送り先をルックアップできます。分散送り先には javax.jms.Destination インタフェースが実装されていて、プロデューサ、コンシューマ、およびブラウザの作成に使用できます。
分散送り先はクラスタ内の複数の WebLogic Server からサービスを受けることができるため、createQueue()
メソッドまたは createTopic()
メソッドのどちらかを使って分散送り先の参照を作成するときに提供される名前は、単純に JMSDistributedQueueMBean
または JMSDistributedTopicMBean
の名前の前に親モジュール名を付加し、感嘆符 (!) で区切ったものになります。JMS サーバ名や区切り用のフォワード スラッシュ (/
) は必要ありません。
たとえば、次のコードは、分散送り先トピックのルックアップ方法を示します。
topic = myTopicSession.createTopic("myModuel!myDistributedTopic");
注意 : createQueue()
メソッドまたは createTopic()
メソッドを呼び出す際、フォワード スラッシュ (/
) を含む文字列は、分散送り先の名前ではなく、分散送り先メンバーの名前であると見なされます。このような分散送り先メンバーが存在しない場合、呼び出しは InvalidDestinationException
で失敗します。「分散トピックへのメッセージ駆動型 Bean のデプロイ」を参照してください。
分散キューは、一連の物理的な JMS キューのメンバーです。したがって、分散キューは QueueSender
、QueueReceiver
、および QueueBrowser
を作成するために使用できます。分散キューが複数の物理的キューを表すという事実は、アプリケーションには全く意識されません。
キューのメンバーはどこにでも配置できますが、単一のサーバ クラスタ内にある JMS サーバからサービスを受ける必要があります。分散キューに送信されるメッセージは、分散キューの一連のメンバー内にある物理的キューの 1 つだけに送られます。キューのメンバーに届いたメッセージは、そのキューのメンバーのコンシューマのみが受信できるようになります。
キューのメンバーがメッセージをキューの他のメンバーに転送できるようにするには、Administration Console の [転送の遅延] 属性をコンフィグレーションします。この属性はデフォルトでは無効になっています。この属性は、コンシューマではなく、メッセージだけを持つ分散キューのメンバーが、コンシューマを持つキューの他のメンバーにメッセージを転送するときに待機する時間を秒単位で定義します。
キュー センダを作成した後、作成時に提供したキューが分散キューであった場合は、センダを使用してメッセージが作成されるたびに、どのキューのメンバーがそのメッセージを受信するかの判断が下されます。各メッセージは単一の物理的キューのメンバーに送信されます。
メッセージが複製されることは一切ありません。このため、メッセージは送信元のキューのメンバーのみから受信できます。メッセージの受信前にその物理的キューが使用できなくなった場合は、そのキューのメンバーがオンラインに復帰するまでこのメッセージを受信できなくなります。
メッセージを分散キューに送信して、その分散キューのキュー レシーバがメッセージを受信することを期待するだけでは十分とは言えません。メッセージは 1 つの物理的キューのメンバーだけに送信されるため、そのキューのメンバーで受信またはリスンするキュー レシーバが存在する必要があります。
注意 : コンシューマを持たない分散キューに対するロード バランシングのヒューリスティックについては、「分散送り先のコンフィグレーション」を参照してください。
キュー レシーバを作成する際は、提供したキューが分散キューの場合、単一の物理的キューのメンバーが作成時にレシーバとして選ばれます。作成された QueueReceiver
は、キュー レシーバがキュー メンバーのアクセスを失うまでそのキュー メンバーに固定されます。この時点で、コンシューマは次のように JMSException
を受信します。
ConsumerClosedException
の内部に配信され、それがコンシューマ セッションに定義されている ExceptionListener
(存在する場合) に配信されます。このような例外を受信した場合、アプリケーションは自分のキュー レシーバを終了し、再作成できます。分散キュー内で他のキュー メンバーを使用できる場合は、新しいキュー レシーバが作成され、これらのキュー メンバーのいずれかに固定されます。他のキュー メンバーを使用できない場合、キュー レシーバの再作成はできないため、後で作成を試みる必要があります。
注意 : コンシューマを持たない分散キューに対するロード バランシングのヒューリスティックについては、「分散送り先のコンフィグレーション」を参照してください。
キュー ブラウザを作成する際は、提供されているキューが分散キューの場合、単一の物理的キューのメンバーが作成時にブラウザとして選ばれます。作成されたキュー ブラウザは、レシーバがキュー メンバーのアクセスを失うまでそのキュー メンバーに固定されます。その時点でキュー ブラウザを呼び出した場合は、JMSException
が発行されます。列挙を呼び出した場合は、NoSuchElementException
が返されます。
注意 : キュー ブラウザは固定されているキュー メンバーのみを閲覧できます。分散キューが作成時に指定されている場合でも、キュー ブラウザが分散送り先内の他のキュー メンバーのメッセージを表示または閲覧することはできません。
分散トピックは、一連の物理的な JMS トピックのメンバーです。このため、分散トピックは TopicPublisher
と TopicSubscriber
を使用して作成できます。分散トピックが複数の物理的トピックを表すという事実は、アプリケーションには全く意識されません。
注意 : 恒久サブスクライバ (DurableTopicSubscriber
) は、分散トピックに対しては作成できません。ただし、分散トピックのメンバーに対して恒久サブスクリプションを作成することはできます。こうすると、他のトピック メンバーは、恒久サブスクリプションを持つトピック メンバーにメッセージを転送します。
トピック メンバーはどこにでも配置できますが、単一の WebLogic Server、またはクラスタ内の任意の数のサーバによってサービスを受ける必要があります。分散トピックに送信されたメッセージは、分散トピック セット内のトピック メンバーすべてに送信されます。このため、分散トピックのすべてのサブスクライバは、分散トピック用にパブリッシュされたメッセージを受信できます。
分散送り先のトピック メンバーに直接パブリッシュされたメッセージ (つまりパブリッシャが送り先を指定しなかったメッセージ) も、その分散トピックのメンバーすべてに転送されます。これには、最初に分散トピックをサブスクライブしたサブスクライバと、その特定のトピック メンバーにたまたま割り当てられているサブスクライバが含まれます。つまり、特定の分散トピックのメンバーにメッセージをパブリッシュすると、それが分散トピックの他のメンバーすべてに自動的に転送されます。これは、分散トピックにメッセージをパブリッシュすると、その分散トピックのメンバーすべてにメッセージが自動的に転送されることと同じです。特定の分散送り先メンバーのルックアップについては、「分散送り先メンバーへのアクセス」を参照してください。
トピック パブリッシャを作成する際、提供されている送り先が分散送り先である場合には、その分散送り先に送信されるメッセージは次のように、分散トピックのアクセス可能なトピック メンバーすべてに送信されます。
注意 : 永続ストアを利用している分散メンバーに対しては、最初にメッセージを転送するためにあらゆる努力がなされます。ただし、分散メンバーがいずれもストアを利用していない場合でも、メッセージは「分散送り先のコンフィグレーション」で説明されるように、選択されているロード バランシング アルゴリズムに従って、いずれかのメンバーに送信されます。
JMSException
が発行されます。トピック サブスクライバを作成するとき、提供されているトピックが分散トピックの場合、トピック サブスクライバはその分散トピックにパブリッシュされたメッセージを受信します。トピック サブスクライバが分散トピックのトピック メンバーの 1 つまたは複数にアクセスできない場合は、メッセージが永続的であるか非永続的であるかに応じて次の事態が発生します。
注意 : JMS ストアが分散トピック メンバーをホストする JMS サーバ用にコンフィグレーションされている場合は、そのメンバーの送り先に関連付けられているすべての分散トピック システム サブスクライバが恒久サブスクリプションとして処理されます。これは、トピック メンバーに JMS ストアが明示的にコンフィグレーションされていない場合も同様です。したがって、これらの分散トピック サブスクライバに送信されるすべてのメッセージをメモリに保存すると、メモリやディスクが予想以上に消費されるおそれがあります。分散送り先をデプロイする場合のベスト プラクティスとしてお勧めする設計は、恒久メッセージ用の JMS ストアがある場合でも、非恒久メッセージ用の JMS ストアがない場合でも、すべてのメンバー送り先を同じようにコンフィグレーションすることです。たとえば、すべての分散トピック サブスクライバを非恒久にした上で、一部のメンバー送り先に暗黙的に JMS ストアをコンフィグレーションし、それらに関連付けられた JMS サーバが JMS ストアを使用するようにしたい場合は、各メンバー送り先の StoreEnabled 属性を明示的に False に設定して JMS サーバの設定をオーバーライドする必要があります。
最終的に、トピック サブスクライバは物理的なトピック メンバーに固定されます。そのトピック メンバーにアクセスできなくなった場合は、次のようにトピック サブスクライバに JMSException
が発行されます。
ConsumerClosedException
の内部に配信され、それがコンシューマ セッションに定義されている ExceptionListener
(存在する場合) に配信されます。このような例外を受信した場合、アプリケーションはトピック サブスクライバを終了して再作成できます。分散トピック内のその他のトピック メンバーにアクセス可能な場合は、新しいトピック サブスクライバが作成され、これらのトピック メンバーのいずれかに固定されます。他のトピック メンバーにアクセスできない場合、トピック サブスクライバの再作成はできないため、後で作成を再試行する必要があります。
MDB を分散トピックにデプロイし、JMS サーバ上の分散トピックの 2 つのメンバーをホストしているクラスタ内の WebLogic Server インスタンスを対象とした場合、MDB は分散トピックのいずれのメンバーにもデプロイされます。これは、MDB が分散トピックのメンバーの送り先名に固定されているからです。
したがって、WebLogic Server インスタンスにデプロイされている分散トピックのメンバー数に応じて、MDB ごとに [送信メッセージ数] * [分散トピックのメンバー数] のメッセージを受信することになります。たとえば、JMS サーバに 2 つの分散トピックのメンバーが含まれている場合、各メンバーに 1 つ、合わせて 2 つの MDB がデプロイされるので、2 倍の数のメッセージを受信することになります。
以下の節では、分散送り先のメンバーに直接アクセスする方法について説明します。
注意 : アプリケーションは、個別の物理的送り先に直接アクセスすることで、ロード バランシングを回避します。詳細については、「分散送り先のコンフィグレーション」を参照してください。
共通分散送り先内の共通送り先メンバーにアクセスするには、weblogic.jms.extensions.JMSModuleHelper クラスの uddMakeName または uddMemberJNDIName API を使用して、JNDI 名またはメンバー名をルックアップする必要があります。その後は、JNDI 名を使用するか、モジュール名 (その後ろに感嘆符 (!))、JMS サーバ名 (その後ろにスラッシュ (/
))、およびメンバー名を指定します。
たとえば、次のコードは、モジュール (myModule
) 内の JMS サーバ (myServer
) 上の共通分散キュー (myQueue
) の特定のメンバーをルックアップする方法を示します。
queue = myQueueSession.createQueue("
myModule!myServer/myQueue
");
注意 : createQueue()
メソッドまたは createTopic()
メソッドを呼び出す際、フォワード スラッシュ (/
) を含む文字列は、分散送り先ではなく、分散送り先メンバーの名前であると見なされます。このような分散送り先メンバーが存在しない場合、呼び出しは InvalidDestinationException
で失敗します。
この API は、共通分散送り先のメンバー名を返します。メンバーがデプロイされている (またはこれからデプロイする) 共通分散送り先の名前と JMS サーバを指定します。
public static String uddMemberName(String jmsServerName, String name) {
return(uddMakeName(jmsServerName, name));
}
jmsServerName
は、JMS サーバのコンフィグレーションされた名前です。name
は、共通分散送り先のコンフィグレーションされた名前です。String[] array
を返します。この API は、共通分散送り先メンバーの JNDI 名を返します。メンバーがデプロイされている (またはこれからデプロイする) 共通分散送り先の JNDI 名と JMS サーバを指定します。
public static String uddMemberJNDIName(String jmsServerName, String name) {
return(uddMakeName(jmsServerName, name));
}
jmsServerName
は、JMS サーバのコンフィグレーションされた名前です。name
は、共通分散送り先のコンフィグレーションされた名前です。String[] array
を返します。分散送り先内の重み設定された送り先メンバーにアクセスするには、コンフィグレーションされた JNDI 名を使用して送り先メンバーをルックアップするか、モジュール名 (その後ろに感嘆符 (!))、JMS サーバ名 (その後ろにスラッシュ (/
))、および JMSQueueMBean
または JMSTopicMBean
のコンフィグレーション MBean 名を指定します。
たとえば、次のコードは、モジュール (myModule
) 内の JMS サーバ (myServer
) 上の重み設定された分散キュー (myQueue
) の特定のメンバーをルックアップする方法を示します。
queue = myQueueSession.createQueue("
myModule!myServer/myQueue
");
注意 : createQueue()
メソッドまたは createTopic()
メソッドを呼び出す際、フォワード スラッシュ (/
) を含む文字列は、分散送り先ではなく、分散送り先メンバーの名前であると見なされます。このような分散送り先メンバーが存在しない場合、呼び出しは InvalidDestinationException
で失敗します。
注意 : キュー プロデューサが作成された分散キュー メンバーに障害が発生したが、プロデューサの JMS 接続が存在する WebLogic Server がまだ実行されている場合、プロデューサは閉じられず、WebLogic JMS はロード バランシング オプションが有効になっているかどうかに関係なく別の分散キュー メンバーにフェイルオーバします。たとえば、WebLogic クラスタに WLSServer1、WLSServer2、および WLSServer3 があり、WLServer2 に接続しているとします。サーバ WLSServer 2 に障害が発生すると、プロデューサは残りのクラスタ メンバーの 1 つにフェイルオーバします。詳細については、「分散送り先のコンフィグレーション」を参照してください。
障害が発生した分散送り先に接続されているクライアントをフェイルオーバさせる方法としては、クライアント コードに再接続ロジックを記述して、onException
を捕捉したら分散送り先に接続されるようにする方法が簡単です。
メッセージ駆動型 Bean (MDB) は、JMS メッセージ リスナ (イベントの代わりにメッセージを受信することを除いてイベント リスナと同様) として機能します。MDB の詳細については、以下を参照してください。
以下の節では、分散送り先を使用する場合の一般的な例を示します。
メッセージの生成を最大にするには、分散送り先の各メンバーをプロデューサとコンシューマに関連付けることをお勧めします。次の図は、ロード バランシングを使用せず、共通分散送り先を使用して効率的に最大のメッセージ生成と高可用性を実現する方法を示しています。
この場合、UDD1 は 2 つの物理的なメンバー、D1 および D2 で構成された共通分散送り先です。それぞれの物理的な送り先にはプロデューサとコンシューマのペアがあり、メッセージは実線のとおりに、効率的にプロデューサから送り先メンバーを介してコンシューマに渡されます。順序付けを使用している場合は、予期される順序単位ごとにプロデューサが必要です。『WebLogic JMS プログラマーズ ガイド』の「分散送り先で順序単位を使用する」を参照してください。
この節では、メッセージの可用性を最大にする方法について説明します。
プロデューサをコンシューマとペアにするのが理想的ですが、この方法が適切でない場合もあります。メッセージの消費速度は、アプリケーションのメッセージ スループットを決定する制約要因です。メンバー送り先間でロード バランシングを使用することにより、コンシューマの可用性を向上できます。この場合、コンシューマはプロデューサとペアになっていませんが、受信メッセージは次の使用可能なコンシューマにロード バランシング アルゴリズムに従ってロード バランシングされます。
注意 : 順序単位機能の組み合わせによっては、競合する順序単位メッセージ ストリームが不足することがあります。これには、順序単位名が異なる処理中メッセージの数よりコンシューマの数が多くなったために、リソースが十分に利用されなくなった場合も含まれます。システムのパフォーマンスを最適化し、リソースが十分に利用されない状態を防ぐには、最大の負荷でアプリケーションをテストする必要があります。
分散トピックを使用すると、各メンバー送り先はメッセージを分散トピックの他のすべてのメンバーに転送します。
この場合、UDD1 は 2 つの物理的なメンバー、D1 および D2 で構成された共通分散送り先です。それぞれの物理的な送り先にはプロデューサとコンシューマのペアがあります。各コンシューマはプロデューサ 1 およびプロデューサ 2 から送信されるメッセージを受信します。
この場合、プロデューサは UDD の 1 つのメンバーにメッセージを送信しますが、メッセージを受信できるコンシューマがありません。これは通常、プロデューサが送り先の 1 つ (D1) にメッセージを送信し、コンシューマが別の送り先 (D2) のメッセージをリスンしている場合に生じます。
UDD1 は 2 つの物理的なメンバー、D1 および D2 で構成された共通分散送り先です。D1 にはプロデューサがあり、D2 にはコンシューマがあります。プロデューサとコンシューマのペアを使用するか、または送り先で転送をコンフィグレーションして、このようなコンフィグレーションは回避してください。
![]() ![]() |
![]() |
![]() |