Sun Java System Message Queue 3.7 UR1 技術の概要

第 2 章 クライアントプログラミングモデル

この章では、Message Queue クライアントプログラミングの基本について説明します。次のトピックが含まれます。

この章では、Java クライアントの設計と実装を中心に説明します。概して、C クライアントの設計は、Java クライアントの設計とほぼ同じです。この章の最終節では、Java クライアントと C クライアントの相違点をまとめています。Message Queue クライアントのプログラミングの詳細は、『Sun Java System Message Queue 3.7 UR1 Developer’s Guide for Java Clients』および『Sun Java System Message Queue 3.7 UR1 Developer’s Guide for C Clients』を参照してください。

第 3 章「Message Queue サービス」では、Message Queue サービスを使用して、メッセージングパフォーマンスのサポート、管理、および調整を行う方法について説明します。

設計とパフォーマンス

Message Queue アプリケーションの動作は、多くの要因に左右されます。たとえば、クライアント設計、コネクション設定、ブローカ設定、ブローカの調整、リソース管理などです。一部の要因は開発者の扱う範囲ですが、ほかの要因は管理者の問題になります。ただし、理想的には、開発者は Message Queue サービスでのアプリケーション設計のサポートと拡張について意識し、管理者はアプリケーションを調整するときに設計目標を意識することが望まれます。メッセージングの動作は、再設計によっても、注意深い監視および調整によっても最適化できます。したがって、優れた Message Queue アプリケーションの作成における重要な点は、開発者と管理者が、アプリケーションのライフサイクルの各段階で実現できることを理解し、所期の動作と実際の動作に関する情報を共有することです。

メッセージングドメイン

メッセージングミドルウェアは、メッセージのプロデュースとコンシュームを行うことにより、コンポーネントおよびアプリケーションの通信を実現します。JMS API では、この通信を制御するパターン、すなわちメッセージングドメインとして、ポイントツーポイントメッセージングパブリッシュ / サブスクライブメッセージングの 2 つを規定しています。JMS API は、これらのパターンをサポートするように構成されています。基本的な JMS オブジェクト、つまりコネクション、セッション、プロデューサ、コンシューマ、送信先、メッセージが、両方のドメインでメッセージング動作を指定するために使用されます。

ポイントツーポイントメッセージング

ポイントツーポイントドメインでは、メッセージプロデューサは送信側と呼ばれ、コンシューマは受信側と呼ばれます。これらは、キューと呼ばれる送信先を使用してメッセージを交換します。送信側は、キューへメッセージをプロデュースし、受信側はキューからメッセージをコンシュームします。

図 2–1 に、ポイントツーポイントドメインでのもっとも単純なメッセージング操作を示します。MyQueueSender は、 Msg1 をキュー送信先 MyQueue1 に送信します。続いて、 MyQueueReceiverMyQueue1 からメッセージを取得します。

図 2–1 単純なポイントツーポイントメッセージング

メッセージは、キュー送信先を介して、送信側から受信側へ移動する。図は文字で説明される。

図 2–2 に、このドメインでの可能性を表すために、より複雑なポイントツーポイントメッセージングのイメージを示します。2 つの送信側、MyQSender1MyQSender2 は、同じコネクションを使用して、メッセージを MyQSender1 に送信します。 MyQSender3 は、別のコネクションを使用して、メッセージを MyQueue1 に送信します。受信側では、MyQReceiver1MyQueue1 からメッセージをコンシュームし、MyQReceiver2MyQReceiver3 は、コネクションを共有して、MyQueue1 からメッセージをコンシュームします。

図 2–2 複雑なポイントツーポイントメッセージング

2 つの送信側が、1 つのコネクションを使用して 1 つの受信側にメッセージを送信している。2 つのコンシューマが同じキューからメッセージを取得している。図は文字で説明される。

この複雑な図では、ポイントツーポイントメッセージングに関するその他の要点が多数示されています。

ポイントツーポイントモデルには、次のような多くのメリットがあります。

パブリッシュ / サブスクライブメッセージング

パブリッシュ / サブスクライブドメインでは、メッセージプロデューサはパブリッシャーと呼ばれ、メッセージコンシューマはサブスクライバと呼ばれます。これらは、トピックと呼ばれる送信先を使用してメッセージを交換します。パブリッシャーは、トピックへメッセージをプロデュースし、サブスクライバはトピックへサブスクライブして、トピックからメッセージをコンシュームします。

図 2–3 に、パブリッシュ / サブスクライブドメインの単純なメッセージング操作を示します。MyTopicPublisher は、Msg1 を送信先 MyTopic へパブリッシュします。続いて、MyTopicSubscriber1 MyTopicSubscriber2 はそれぞれ、 MyTopic から Msg1 のコピーを受信します。

図 2–3 単純なパブリッシュ / サブスクライブメッセージング

図では、1 つのパブリッシャーが、トピック送信先を介して、同じメッセージを 2 つのサブスクライバに送信している。図は文字で説明される。

パブリッシュ / サブスクライブモデルでは、複数のサブスクライバが必要になるわけではありませんが、このドメインが複数のメッセージをブロードキャストできることを強調するために、図では 2 つのサブスクライバを示しています。トピックに対応するすべてのサブスクライバが、このトピックへパブリッシュされた任意のメッセージのコピーを取得します。

サブスクライバは、非永続でも永続でもかまいません。ブローカは、すべてのアクティブなサブスクライバのメッセージを保持しますが、非アクティブなサブスクライバのメッセージは、これらのサブスクライバが永続である場合にのみ保持します。

図 2–4 に、このパターンによって実現する可能性を表すために、より複雑なパブリッシュ / サブスクライブメッセージングのイメージを示します。複数のプロデューサがメッセージを Topic1 送信先にパブリッシュします。複数のサブスクライバが、Topic1 送信先からメッセージをコンシュームします。サブスクライバがセレクタを使用してメッセージをフィルタ処理しないかぎり、各サブスクライバは、選択したトピックへパブリッシュされたすべてのメッセージを取得します。図 2–4 では、MyTSubscriber2Msg2 をフィルタで除外しています。

図 2–4 複雑なパブリッシュ / サブスクライブメッセージング

図では、3 つのパブリッシャーが、1 つのトピック送信先を介して 3 つのサブスクライバへメッセージを送信している。図は文字で説明される。

この複雑な図では、パブリッシュ / サブスクライブメッセージングに関するその他の要点が多数示されています。

パブリッシュ / サブスクライブモデルの主要なメリットは、複数のサブスクライバへメッセージをブロードキャストできるという点です。

ドメイン固有 API と統合 API

JMS API では、ポイントツーポイントドメインまたはパブリッシュ / サブスクライブドメインのいずれかの実装に使用できるインタフェースとクラスを規定しています。これらは、表 2–1 の 2 列目と 3 列目に示したドメイン固有 API です。JMS API では、そのほかに統合ドメインを規定しており、これを使用すれば、汎用メッセージングクライアントをプログラムできます。このようなクライアントの動作は、メッセージのプロデュース先でありメッセージのコンシューム元である送信先のタイプによって決定されます。送信先がキューの場合、メッセージングはポイントツーポイントのパターンに従って動作します。送信先がトピックの場合、メッセージングはパブリッシュ / サブスクライブパターンに従って動作します。

表 2–1 JMS プログラミングドメインとオブジェクト

基本タイプ (統合ドメイン) 

ポイントツーポイントドメイン 

パブリッシュ / サブスクライブドメイン 

Destination (Queue または Topic)

Queue

Topic

ConnectionFactory

QueueConnectionFactory

TopicConnectionFactory

Connection

QueueConnection

TopicConnection

Session

QueueSession

TopicSession

MessageProducer

QueueSender

TopicPublisher

MessageConsumer

QueueReceiver

TopicSubscriber

統合ドメインは、JMS バージョン 1.1 から導入されています。以前の 1.02b 仕様に適合する必要がある場合は、ドメイン固有 API を使用できます。ドメイン固有 API を使用すると、特定のプログラミングエラーを防止するクリーンなプログラムインタフェースが得られます。たとえば、キュー送信先に対する永続サブスクライバの作成などです。ただしドメイン固有 API には、同じトランザクションまたは同じセッションにおいて、ポイントツーポイント操作とパブリッシュ / サブスクライブ操作を組み合わせることができないというマイナス面もあります。両方の操作を組み合わせる必要がある場合は、統合ドメイン API を選択してください。2 つのドメインの組み合わせ例については、「要求 / 応答パターン」を参照してください。

プログラミングオブジェクト

JMS メッセージングの実装に使用されるオブジェクトは、基本的にプログラミングドメイン全体で同じです。つまり、コネクションファクトリ、コネクション、セッション、プロデューサ、コンシューマ、メッセージ、および送信先が使用されます。図 2–5 に、この様子を示します。図の上から下に向かい、コネクションファクトリオブジェクトからどのようにオブジェクトが生成されるかを示しています。

これらのオブジェクトのうち、コネクションファクトリと送信先の 2 つは、1 つのオブジェクトストア内にあるように示されています。これは、これらのオブジェクトが通常、管理対象オブジェクトとして作成、設定、管理されるという点を強調するためです。この章を通じて、コネクションファクトリと送信先は、プログラムではなく管理操作によって作成されると想定しています。

図 2–5 JMS プログラミングオブジェクト

図は、コネクションファクトリ、コネクション、セッション、プロデューサ、コンシューマ、メッセージ、および送信先の関係を示す。図は文字で説明される。

表 2–2 は、メッセージの送受信に必要な手順をまとめています。手順 1 から 6 は、送信側と受信側で同じであることに注意してください。

表 2–2 メッセージのプロデュースとコンシューム

メッセージのプロデュース 

メッセージのコンシューム 

1. 管理者がコネクションファクトリ管理対象オブジェクトを作成します。

2. 管理者が、物理的な送信先と、それを参照する管理対象オブジェクトを作成します。

3. クライアントが、JNDI 検索を使用して、コネクションファクトリオブジェクトを取得します。

4. クライアントが、JNDI 検索を使用して、送信先オブジェクトを取得します。

5. クライアントが、コネクションを作成し、このコネクションに固有の任意のプロパティーを設定します。

6. クライアントが、セッションを作成し、メッセージングの信頼性を決定するプロパティーを設定します。

7. クライアントがメッセージプロデューサを作成します。 

クライアントがメッセージコンシューマを作成します。 

8. クライアントがメッセージを作成します。 

クライアントがコネクションを開始します。 

9. クライアントがメッセージを送信します。 

クライアントがメッセージを受信します。 

以降の節では、プロデューサとコンシューマが使用するオブジェクト、つまりコネクション、セッション、メッセージ、および送信先について説明します。続いて、メッセージのプロデュースとコンシュームについて説明し、JMS オブジェクトの説明を締めくくります。

コネクションファクトリとコネクション

クライアントは、コネクションファクトリオブジェクト (ConnectionFactory) を使用して、コネクションを作成します。コネクションオブジェクト ( Connection)は、ブローカへのクライアントのアクティブなコネクションを表します。デフォルトで起動されるか、このクライアントの管理者が明示的に起動する基礎となるコネクションサービスを使用します。

通信リソースの割り当てとクライアントの認証は、コネクションが作成されるときに行われます。このオブジェクトは比較的重いため、ほとんどのクライアントはメッセージングのすべてを 1 つのコネクションだけで行います。コネクションは同時使用をサポートするため、複数のプロデューサとコンシューマが 1 つのコネクションを共有できます。

コネクションファクトリを作成するときに、そのプロパティーを設定しておくことによって、コネクションファクトリから生成されるすべてのコネクションの動作を設定できます。Message Queue の場合、次の情報を指定します。

クライアントアプリケーションの起動に使用するコマンド行から、コネクションファクトリのプロパティーをオーバーライドできます。また、どのコネクションのプロパティーも、そのコネクションのプロパティーを設定することによってオーバーライドできます。

コネクションオブジェクトを使用して、セッションオブジェクトの作成、例外リスナーの設定、または JMS バージョンおよびプロバイダ情報の取得を行えます。

セッション

コネクションがクライアントとブローカ間の通信チャネルである場合、セッションは、クライアントとブローカ間の単一のやり取りをマークします。セッションオブジェクトは、主にメッセージ、メッセージプロデューサ、およびメッセージコンシューマの作成に使用します。セッションを作成するときには、多数の通知オプションまたはトランザクションを使用して、信頼性の高い配信を設定します。詳細は、「信頼性の高いメッセージング」を参照してください。

JMS 仕様によれば、セッションは、シングルスレッドコンテキストで、メッセージのプロデュースとコンシュームを実行します。単一のセッションに対して複数のメッセージプロデューサとコンシューマを作成できますが、順番に使用するという制限があります。スレッド処理の実装は、Java クライアントと C クライアントでは少し異なります。スレッド処理の実装および制限の詳細は、該当する開発者ガイドを参照してください。

また、セッションオブジェクトを使用して、次の処理も行えます。

メッセージ

メッセージは、ヘッダー、プロパティー、および本体の 3 つの部分で構成されています。 メッセージを正しく作成し、特定のメッセージング動作を設定するために、この構造を理解する必要があります。

メッセージヘッダー

すべての JMS メッセージにはヘッダーが必要です。ヘッダーには、あらかじめ定義された 10 のフィールドがあります。これらについて、表 2–3 で説明します。

表 2–3 JMS 規定のメッセージヘッダー

ヘッダーフィールド 

説明 

JMSDestination

メッセージを送信する送信先オブジェクトの名前を指定します。(プロバイダが設定する)

JMSDeliveryMode

メッセージが持続かどうかを指定します。(デフォルトでプロバイダが設定するか、プロデューサまたは個々のメッセージごとにクライアントが明示的に設定する)

JMSExpiration

メッセージの有効期限を指定します。(デフォルトでプロバイダが設定するか、プロデューサまたは個々のメッセージごとにクライアントが設定する)

JMSPriority

0 (低) から 9 (高) の範囲内で、メッセージの優先度を指定します。(デフォルトでプロバイダが設定するか、プロデューサまたは個々のメッセージごとにクライアントが明示的に設定する)

JMSMessageID

プロバイダのインストールのコンテキスト内で、メッセージに対する一意の ID を指定します。(プロバイダが設定する)

JMSTimestamp

プロバイダがメッセージを受信した時間を指定します。(プロバイダが設定する)

JMSCorrelationID

クライアントが 2 つのメッセージのやりとりを定義できるようにするための値です。(必要に応じてクライアントが設定する)

JMSReplyTo

コンシューマが応答を送信すべき送信先を指定します。(必要に応じてクライアントが設定する)

JMSType

メッセージセレクタが評価できる値です。(必要に応じてクライアントが設定する)

JMSRedelivered

メッセージがすでに配信されたが通知されていないかどうかを指定します。(プロバイダが設定する)

この表からわかるように、メッセージヘッダーフィールドは、さまざまな目的に使用されます。たとえば、メッセージの識別、メッセージのルーティングの設定、メッセージ処理に関する情報の提供などです。

もっとも重要なフィールドの 1 つである JMSDeliveryMode によって、メッセージ配信の信頼性が決まります。このフィールドは、メッセージが持続かどうかを示します。

メッセージヘッダーフィールドにはプロバイダ (ブローカまたはクライアントランタイム) が設定するものも、クライアントが設定するものもあります。メッセージプロデューサは、特定のメッセージング動作を得るために、ヘッダー値を設定する必要が生じる場合があります。メッセージコンシューマは、メッセージがどのようにルーティングされ、どのような追加処理が必要かを認識するために、ヘッダー値を読み込む必要が生じる場合があります。

ヘッダーフィールド (JMSDeliveryMode JMSExpiration および JMSPriority) は、次の 3 つの異なるレベルに設定できます。

これらのフィールドを複数のレベルに設定した場合、コネクションファクトリに対して設定された値は、個々のメッセージに対して設定された値をオーバーライドします。特定のメッセージに対して設定された値は、メッセージのプロデューサに対して設定された値をオーバーライドします。

メッセージヘッダーフィールドに使用する定数名は、実装されている言語によって異なります。詳細は、『Sun Java System Message Queue 3.7 UR1 Developer’s Guide for Java Clients』または『Sun Java System Message Queue 3.7 UR1 Developer’s Guide for C Clients』を参照してください。

メッセージプロパティー

メッセージは、プロパティーと呼ばれるオプションのヘッダーフィールドも含めることができます。このフィールドは、プロパティー名とプロパティー値のペアとして指定されます。クライアントとプロバイダはプロパティーを使用して、メッセージヘッダーを拡張し、メッセージの識別と処理に役立つすべての情報を含めることができます。受信側クライアントは、メッセージプロパティーを使用して、指定された基準に適合したメッセージだけを配信するように要求できます。たとえば、コンシューミングクライアントは、ニュージャージーで働くパートタイム従業員の給与に関するメッセージが必要であることを示すことができます。プロバイダは、指定された基準に適合しないメッセージを配信しません。

JMS 仕様では、9 つの標準プロパティーが規定されています。クライアントが設定するプロパティーもあれば、プロバイダが設定するプロパティーもあります。その名前は予約文字「JMSX」で始まります。クライアントまたはプロバイダは、これらのプロパティーを使用して、メッセージの送信者、メッセージの状態、メッセージが配信された回数および時間を判断できます。これらのプロパティーは、プロバイダがメッセージをルーティングしたり、診断情報を提供したりする際に役立ちます。

Message Queue でもメッセージプロパティーが定義されています。これらのプロパティーは、圧縮されたメッセージを識別し、そのメッセージを配信できない場合の処理方法を識別するために使用されます。詳細は、『Sun Java System Message Queue 3.7 UR1 Developer’s Guide for Java Clients』「Managing Message Size」を参照してください。

メッセージ本体

メッセージ本体には、クライアントが交換しようとするデータが含まれます。

表 2–4 に示すように、JMS メッセージのタイプによって、本体に含まれる内容と、コンシューマによる処理方法が決まります。セッションオブジェクトには、メッセージ本体の各タイプに応じた作成メソッドが含まれます。

表 2–4 メッセージ本体のタイプ

タイプ 

説明 

StreamMessage

本体に Java プリミティブ値のストリームを含むメッセージです。順番に入力され、読み取られます。 

MapMessage

本体に名前値のペアを含むメッセージです。エントリの順番は定義されていません。 

TextMessage

本体に、XML メッセージなどの Java 文字列を含むメッセージです。 

ObjectMessage

本体にシリアライズされた Java オブジェクトを含むメッセージです。 

BytesMessage

本体に未解釈バイトのストリームを含むメッセージです。 

Message

ヘッダーとプロパティーは含むが、本体は含まないメッセージです。 

Java クライアントは、送信するメッセージの本体をクライアントランタイムで圧縮するように、プロパティーを設定することができます。コンシューマ側の Message Queue ランタイムは、メッセージを圧縮解除してから配信します。

メッセージのプロデュース

メッセージは、コネクションおよびセッションのコンテキスト内でメッセージプロデューサによって送信またはパブリッシュされます。メッセージのプロデュースは、とても簡単です。クライアントは、メッセージプロデューサオブジェクト (MessageProducer) を使用して、送信先オブジェクトにより API 内に示される物理的な送信先にメッセージを送信します。

プロデューサを作成するときに、すべてのプロデューサのメッセージが送信されるデフォルトの送信先を指定できます。また、持続性、優先度、および有効期間を制御するメッセージヘッダーフィールドのデフォルト値も指定できます。したがって、メッセージの送信時に代わりの送信先を指定したり、指定されたメッセージのヘッダーフィールドに代わりの値を設定したりすることによってオーバーライドしないかぎり、これらのデフォルト値は、そのプロデューサから出されるすべてのメッセージによって使用されます

メッセージプロデューサは、JMSReplyToメッセージヘッダーフィールドを設定することにより、要求 / 応答パターンも実装できます。詳細は、「要求 / 応答パターン」を参照してください。

メッセージのコンシューム

メッセージは、コネクションおよびセッションのコンテキスト内でメッセージコンシューマによって受信されます。クライアントは、メッセージコンシューマオブジェクト (MessageConsumer) を使用して、送信先オブジェクトとして API 内に示される指定された物理的な送信先からメッセージを受信します。

次の 3 つの要因は、ブローカがメッセージをコンシューマに配信する方法に影響します。

メッセージの配信およびクライアント設計に影響するその他の主要な要因は、コンシューマで必要となる信頼性の度合いです。「信頼性の高いメッセージング」を参照してください。

同期コンシューマと非同期コンシューマ

メッセージコンシューマは、同期または非同期のどちらかのメッセージのコンシュームをサポートしています。

セレクタを使用したメッセージのフィルタ処理

メッセージコンシューマは、メッセージセレクタを使用して、プロパティが特定の選択条件に一致するメッセージだけをメッセージサービスによって配信させることができます。コンシューマを作成するときに、この基準を指定します。

セレクタは SQL に似た構文を使用してメッセージプロパティーを照合します。たとえば次のようになります。

color = ”red’
size > 10

Java クライアントも、キューをブラウズしているときに、セレクタを指定できます。これにより、選択したメッセージのうちコンシュームされるのを待機しているメッセージを確認できます。

永続サブスクライバの使用

セッションオブジェクトを使用して、トピックへの永続サブスクライバを作成できます。ブローカは、このようなサブスクライバに対するメッセージを、このサブスクライバが非アクティブになった場合でも保持します。

ブローカは、サブスクライバの状態を保持し、サブスクライバが再度アクティブになったときにメッセージの配信を再開する必要があるので、サブスクライバの送受信全体から指定されたサブスクライバを識別できる必要があります。サブスクライバの識別情報は、サブスクライバを作成したコネクションの ClientID プロパティーと、サブスクライバを作成するときに指定したサブスクライバ名から構成されています。

要求 / 応答パターン

同じコネクション内で、または統合 API を使用しているときはセッション内でも、プロデューサとコンシューマを組み合わせることができます。さらに、JMS API では、一時送信先を使用することにより、メッセージング操作用の要求 / 応答パターンを実装できます。

要求 / 応答パターンを設定するために、次のタスクを実行する必要があります。

  1. コンシューマが応答を送信できる一時送信先を作成する。

  2. 送信するメッセージで、メッセージヘッダーの JMSReplyTo フィールドをその一時送信先に設定する。

メッセージコンシューマは、メッセージを処理するときに、メッセージの JMSReplyTo フィールドを調べ、応答が要求されているかどうかを判断し、指定された送信先へ応答を送信します。

要求応答メカニズムにより、プロデューサは、応答送信先用の管理対象オブジェクトを設定する必要がなくなり、コンシューマは、要求に対して簡単に応答できるようになります。このパターンは、プロデューサが、続行する前に要求が処理されていることを確認する必要があるときに役立ちます。

図 2–6 に、トピックへメッセージを送信し、一時キュー内の応答を受信する要求 / 応答パターンを示します。

図 2–6 要求 / 応答パターン

パブリッシャーがトピック送信先を介してメッセージを 2 つのサブスクライバに送信し、キューを介して応答を受信している。図は文字で説明される。

図に示すように、MyTopicPublisher は、 Msg1 を送信先 MyTopic へパブリッシュします。MyTopicSubsriber1 MyTopicSubscriber2 はメッセージを受信し、MyTempQueue へ応答を送信します。そこから MyTQReceiver が応答を取り出します。このパターンは、たとえば、多数のクライアントへ価格情報をパブリッシュし、順次処理を行うためにその (応答) 命令をキューに入れるアプリケーションに役立ちます。

一時送信先は、一時送信先を作成したコネクションが存在する間だけしか存続しません。どのプロデューサも一時送信先に送信できますが、一時送信先にアクセスできる唯一のコンシューマは、送信先を作成したコネクションと同じコネクションによって作成されたコンシューマです。

要求 / 応答パターンは一時送信先の作成によって決まるので、次の場合にはこのパターンを使用しないでください。

信頼性の高いメッセージング

メッセージ配信は 2 つのステップで行われます。最初のステップでは、プロデューサからブローカ上の物理的な送信先へメッセージが送られます。次のステップでは、その送信先からコンシューマへメッセージが送られます。このように、メッセージは、ブローカへの移動、ブローカに障害が発生した場合にブローカのメモリーに格納されている間、ブローカからコンシューマへの移動という 3 つのいずれかの段階で消失する可能性があります。信頼性の高い配信は、これらのどの段階でも配信が失敗しないように保証します。ブローカに障害が発生した場合、非持続メッセージは常に消失する可能性があるので、信頼性の高い配信は持続メッセージにのみ該当します。

信頼性の高い配信を確保するために、次の 2 つのメカニズムが使用されます。

次の節では、信頼性を確保する場合の 2 つの側面について説明します。

通知

通知は、信頼性の高いメッセージの配信を確実に行うために、クライアントとメッセージサービスの間で送信されるメッセージです。通知は、プロデューサとコンシューマとでは使用方法が異なります。

メッセージがプロデュースされる場合、ブローカは、メッセージを受信し、送信先に保管し、持続的に保存したことを通知します。プロデューサの send() メソッドは、通知を受信するまでブロックします。持続メッセージが送信されるとき、これらの通知はクライアントからは見えません。

メッセージがコンシュームされる場合、クライアントは、ブローカが送信先からメッセージを削除する前に、送信先から配信されたメッセージを受信し、コンシュームしたことを通知します。JMS では、違うレベルの信頼性を表す別の通知モードを規定しています。

信頼性よりもパフォーマンスを重視するクライアントの場合、Message Queue サービスでは、NO_ACKNOWLEDGE モードを用意することにより、JMS API を拡張しています。このモードでは、ブローカはクライアント通知を追跡しないので、メッセージがコンシューミングクライアントによって正常に処理されたかどうか保証されません。このモードを選択した場合、非永続サブスクライバへ送信される非持続メッセージのパフォーマンスが向上します。

トランザクション

トランザクションとは、1 つ以上のメッセージのプロデュースまたはコンシューム、あるいはその両方を 1 つの極小の単位にグループ化する方法です。前述のクライアントとブローカの通知プロセスは、トランザクションにも適用されます。この場合、クライアントランタイムおよびブローカ通知は、トランザクションのレベルで自動的に処理されます。トランザクションがコミットされると、ブローカの通知が自動的に送信されます。

セッションは処理済みとして設定でき、JMS API には、トランザクションの開始、コミット、またはロールバックを行うメソッドが用意されています。

メッセージがトランザクション内でプロデュースまたはコンシュームされるに従って、メッセージサービスがさまざまな送受信を追跡し、JMS クライアントが呼び出しを実行してトランザクションを確定したときにだけ、送受信の操作を完了させます。トランザクション内での特定の送信や受信の操作が失敗すると、例外が発生します。クライアントコードは、これを無視するか、操作を試行し直すか、またはトランザクション全体をロールバックして、例外を処理できます。トランザクションがコミットされると、すべての操作が完了します。トランザクションがロールバックされると、正常に行われたすべての操作が取り消されます。

トランザクションの範囲は、常に単一セッションです。つまり、単一セッションのコンテキストで実行された、1 つ以上のプロデューサまたはコンシューマの操作は、単一のトランザクションにグループ化されます。トランザクションは 1 つのセッション内で行われるので、1 つの終端間トランザクションでメッセージのプロデュースとコンシュームの両方を行うことはできません。

JMS 仕様では、分散トランザクションもサポートしています。つまり、メッセージのプロデュースとコンシュームは、データベースシステムなど、ほかのリソースマネージャーに関連した操作を含む大容量の分散トランザクションの一部となります。分散トランザクションをサポートするには、Java Systems Application Server が提供するトランザクションマネージャーなどを入手する必要があります。

分散トランザクションでは、Java Transaction API (JTA)、XA Resource API の仕様で定義された 2 フェーズコミットプロトコルを使用して、メッセージサービスやデータベースマネージャーといった複数のリソースマネージャーによって実行される操作を、分散トランザクションマネージャーが追跡および管理します。Java の世界では、リソースマネージャーと分散トランザクションマネージャー間の対話は、JTA の仕様で記述されます。

分散トランザクションのサポートとは、メッセージングクライアントが、JTA で定義される XAResource インタフェースを介して、分散トランザクションに加わることができるということです。このインタフェースでは、2 フェーズコミットを実装するための、数多くのメソッドが定義されます。API の呼び出しがクライアント側で行われている間、JMS メッセージサービスは分散トランザクション内のさまざまな送受信操作やトランザクションの状態を追跡し、Java Transaction Service (JTS) で提供される分散トランザクションマネージャーと一致したときにだけ、メッセージング操作を完了します。ローカルトランザクションに関しては、無視したり、操作を試行し直したり、分散トランザクション全体をロールバックしたりして、クライアントは例外を処理できます。


注 –

Message Queue では、Java Enterprise Edition プラットフォームで JMS プロバイダとして使用される場合にのみ、分散トランザクションをサポートします。分散トランザクションの使用方法について詳しくは、各 Application Server プロバイダによって提供されるマニュアルを参照してください。


持続ストレージ

信頼性のもう 1 つの側面は、ブローカが持続メッセージをコンシューマに配信する前に、その持続メッセージを失うことがないようにすることです。つまり、メッセージが物理的な送信先に到達したら、ブローカはそのメッセージを持続データストアに保管する必要があります。何かの理由でブローカが停止した場合、持続データストアはあとからメッセージを復元し、適切なコンシューマに配信します。

ブローカは、永続サブスクリプションも持続的に保存する必要があります。持続的に保存しないと、障害が発生した場合、ブローカは、メッセージがトピック送信先に届いたあとにアクティブになった永続サブスクライバにメッセージを配信できなくなります。

メッセージ配信を保証するメッセージングアプリケーションは、メッセージを持続的として指定し、永続サブスクリプション状態のトピック送信先またはキュー送信先のいずれかにメッセージを配信する必要があります。

第 3 章「Message Queue サービス」では、Message Queue サービスで用意されているデフォルトのメッセージストアと、管理者による代替ストアのセットアップおよび設定方法について説明します。

システム全体でのメッセージの流れ

これまで示してきた説明のまとめとして、ここでは、Message Queue サービスで、どのようにメッセージがプロデューサからコンシューマへ配信されているかついて説明します。全体像を理解するため、さらに説明する必要があります。配信の過程でシステムが処理するメッセージは、次の 2 つのカテゴリに分類されます。

図 2–7 に、メッセージ配信を示します。

図 2–7 メッセージ配信手順

図は、メッセージを持続的で信頼できる方法で配信する場合のメッセージ配信プロセスの手順を示す。図は文字で説明される。

信頼性の高い方法で、持続的に配信されるメッセージのメッセージ配信手順は次のとおりです。

メッセージのプロデュース

1. クライアントランタイムが、コネクションを使用して、メッセージプロデューサからブローカにメッセージを配信します。

メッセージの処理とルーティング

2. ブローカが、コネクションからメッセージを読み込み、適切な送信先に保管します。

3. ブローカが (持続) メッセージをデータストアに保管します。

4. ブローカが、メッセージを受信したことについて、メッセージプロデューサのクライアントランタイムに通知します。

5. ブローカが、メッセージのルーティングを決定します。

6. ブローカは、コンシューマの一意の識別子をメッセージに付けて、メッセージをその送信先から適切なコネクションへ書き出します。

メッセージのコンシューム

7. メッセージコンシューマのクライアントランタイムが、コネクションからメッセージコンシューマにメッセージを配信します。

8. メッセージコンシューマのクライアントランタイムが、メッセージをコンシュームしたことについて、ブローカに通知します。

メッセージの存続終了

9. ブローカはクライアント通知を処理し、すべての通知を受信したときに、(持続) メッセージを削除します。

10. ブローカは、コンシューマのクライアントランタイムに対して、クライアント通知が処理されたかどうかを確認します。

管理者がメッセージを送信先から削除した場合、または管理者が永続サブスクリプションを削除または再定義し、その結果、トピック送信先内のメッセージが配信されずに削除された場合、ブローカはメッセージがコンシュームされる前にメッセージを破棄できます。その他の状況では、ブローカにメッセージを破棄させるのではなく、デッドメッセージキューと呼ばれる特殊な送信先に保存させることができます。メッセージの有効期限が切れたとき、メモリーの制限のために削除されたとき、またはクライアントが例外をスローしたために配信が失敗したとき、メッセージはデッドメッセージキューに保管されます。メッセージをデッドメッセージキューに保存しておくと、システムの問題を解決し、特定の状況でメッセージを復元することができます。

SOAP メッセージの処理

SOAP (「Java クライアントでの SOAP サポート」を参照) を使用すると、分散環境にある 2 つのピア間で構造化データ (XML 方式で指定) を交換できます。Sun の SOAP の実装では、現在、信頼性の高い SOAP メッセージングをサポートしておらず、SOAP メッセージのパブリッシングもサポートしていません。ただし、Message Queue サービスを使用して、信頼性の高い SOAP メッセージングを取得し、必要な場合は、SOAP メッセージをパブリッシュできます。Message Queue サービスは、直接 SOAP メッセージを配信しませんが、SOAP メッセージを JMS メッセージにラップし、通常の JMS メッセージのようにこれらのメッセージをプロデュースおよびコンシュームして、JMS メッセージから SOAP メッセージを抽出できます。

Message Queue では、javax.xml.messaging com.sun.messaging.xml の 2 つのパッケージを使用して、SOAP サポートを提供します。これらのライブラリに実装されたクラスを使用して、SOAP メッセージを受信し、SOAP メッセージを JMS メッセージにラップし、JMS メッセージから SOAP メッセージを抽出できます。J2EE プラットフォームには、パッケージ java.xml.soap が用意されており、このパッケージを使用して、SOAP メッセージをアセンブルまたは逆アセンブルできます。

Procedure信頼性の高い SOAP メッセージングを取得するには

  1. java.xml.soap パッケージで定義されたオブジェクトを使用して SOAP メッセージを作成するか、javax.xml.messaging パッケージで定義されたサーブレットを使用して SOAP メッセージを受信するか、または JAX-RPC などの Web サービスを使用して SOAP メッセージを受信します。

  2. Message Transformer ユーティリティーを使用して、SOAP メッセージを JMS メッセージに変換します。

  3. 目的の送信先に JMS メッセージを送信します。

  4. JMS メッセージを非同期的または同期的にコンシュームします。

  5. JMS メッセージをコンシュームしたあと、Message Transformer ユーティリティーを使用して、SOAP メッセージに変換します。

  6. SAAJ API (java.xml.soap パッケージで定義) を使用して、SOAP メッセージを逆アセンブルします。

    SOAP メッセージとその処理に関する詳細な情報については、『Sun Java System Message Queue 3.7 UR1 Developer’s Guide for Java Clients』の第 5 章「Working with SOAP Messages」を参照してください。

Java クライアントと C クライアント

Message Queue では、そのメッセージングサービス用の C API を備えているため、旧バージョンの C アプリケーションと C++ アプリケーションを、JMS ベースのメッセージングに加えることができます。

JMS プログラミングモデルは、Message Queue C クライアントの設計の基盤です。『Sun Java System Message Queue 3.7 UR1 Developer’s Guide for C Clients』では、このモデルが C データタイプや関数によってどのように実装されているかについて説明しています。

Java インタフェースと同様に、C インタフェースは次の機能をサポートします。

ただし、Java Message Service 仕様は、Java クライアントに限定した標準であることに注意する必要があります。したがって、C Message Queue API は、Message Queue プロバイダ固有の機能であり、ほかの JMS プロバイダでは使用できません。C クライアントを含んだメッセージングアプリケーションは、別の JMS プロバイダでは処理できません。

C インタフェースでは、次の機能がサポートされません。