ヘッダーをスキップ
Oracle® Databaseアドバンスト・キューイング・ユーザーズ・ガイド
12c リリース1 (12.1)
B71332-03
  目次へ移動
目次
索引へ移動
索引

前
 
次
 

11 Oracle Java Message Serviceの概要

この章では、Oracle Database Advanced Queuing (AQ)へのOracle Java Message Service (JMS)インタフェースについて説明します。

内容は次のとおりです。

JMSおよびOracle JMSの一般的な機能

この項の内容は次のとおりです。

JMSコネクションおよびセッション

この項の内容は次のとおりです。

ConnectionFactoryオブジェクト

ConnectionFactoryは、管理者によって定義された接続構成パラメータの集合をカプセル化します。クライアントはこれを使用してJMSプロバイダとの接続を確立します。この場合、Oracle Databaseの一部であるOracle JMSがJMSプロバイダです。

ConnectionFactoryオブジェクトには、次の3種類があります。

  • ConnectionFactory

  • QueueConnectionFactory

  • TopicConnectionFactory

AQjmsFactoryを使用したConnectionFactoryオブジェクトの取得

AQjmsFactoryクラスを使用して、ConnectionFactoryQueueConnectionFactoryまたはTopicConnectionFactoryオブジェクトに対するハンドルを取得できます。

Point-to-Point操作とパブリッシュ・サブスクライブ操作の両方をサポートしているConnectionFactoryを取得するには、AQjmsFactory.getConnectionFactory()を使用します。QueueConnectionFactoryを取得するには、AQjmsFactory.getQueueConnectionFactory()を使用します。TopicConnectionFactoryを取得するには、AQjmsFactory.getTopicConnectionFactory()を使用します。

ConnectionFactoryQueueConnectionFactoryまたはTopicConnectionFactoryは、ホスト名、ポート番号、SIDドライバまたはJDBC URLおよびプロパティを使用して作成できます。

JNDIを使用したConnectionFactoryオブジェクトの検索

JMS管理者は、Lightweight Directory Access Protocol(LDAP)サーバーにConnectionFactoryオブジェクトを登録できます。JMSでJava Naming and Directory Interface(JNDI)の検索を使用可能にするには、次の設定が必要です。

  1. データベースの登録

    Oracle Databaseサーバーのインストール時に、データベースをLDAPサーバーに登録する必要があります。これは、Database Configuration Assistant (DBCA)を使用して実行できます。図11-1に、LDAPサーバー内のOracle Database Advanced Queuingエントリの構造を示します。ConnectionFactory情報は<cn=OracleDBConnections>の下に格納され、トピックおよびキューは<cn=OracleDBQueues>の下に格納されます。

    図11-1 LDAPサーバー内のOracle Database Advanced Queuingエントリの構造

    図11-1の説明は次にあります。
    「図11-1 LDAPサーバー内のOracle Database Advanced Queuingエントリの構造」の説明

  2. パラメータGLOBAL_TOPIC_ENABLEDを設定します。

    データベースのGLOBAL_TOPIC_ENABLEDシステム・パラメータをTRUEに設定する必要があります。これによって、Oracle Database Advanced Queuingで作成されたすべてのキューおよびトピックが自動的にLDAPサーバーに登録されます。このパラメータは、ALTER SYSTEM SET GLOBAL_TOPIC_ENABLED = TRUEを使用して設定できます。

  3. ConnectionFactoryオブジェクトの登録

    データベースを設定してLDAPサーバーが使用できるようになると、JMS管理者はAQjmsFactory.registerConnectionFactory()を使用して、LDAPにConnectionFactoryQueueConnectionFactoryおよびTopicConnectionFactoryの各オブジェクトを登録できます。

    登録には次のいずれかの方法を使用します。

    • 直接LDAPサーバーに接続

      LDAPにコネクション・ファクトリを登録するには、ユーザーにGLOBAL_AQ_USER_ROLEが必要です。

      LDAPに直接接続するには、registerConnectionFactoryメソッドのパラメータに、LDAPコンテキスト、ConnectionFactoryの名前、QueueConnectionFactoryの名前、TopicConnectionFactoryの名前、ホスト名、データベースSID、ポート番号、JDBCドライバ(ThinまたはOCI8)およびファクトリ・タイプ(キューまたはトピック)を含める必要があります。

    • データベース・サーバーを介してLDAPに接続

      ユーザーはOracle Databaseにログインしてから、データベースによるLDAPエントリの更新ができます。ユーザーが、データベースにログインしてこの操作を実行するには、AQ_ADMINISTRATOR_ROLEを取得する必要があります。

      データベースを介してLDAPに接続するには、registerConnectionFactoryメソッドのパラメータに、AQ_ADMINISTRATOR_ROLEを持つユーザーへのJDBCコネクション、ConnectionFactoryの名前、QueueConnectionFactoryの名前、TopicConnectionFactoryの名前、ホスト名、データベースSID、ポート番号、JDBCドライバ(ThinまたはOCI8)およびファクトリ・タイプ(キューまたはトピック)を含める必要があります。

JMSコネクション

JMSコネクションは、クライアントとJMSプロバイダの間のアクティブなコネクションを表します。JMSコネクションによって、次に示すいくつかの重要なサービスが実行されます。

  • JMSプロバイダとのオープン・コネクションまたはコネクション・プールのいずれかをカプセル化します。

  • クライアントとプロバイダのサービス・デーモン間のオープンなTCP/IPソケットを表します。

  • コネクション確立時に、クライアントを認証するための構造を提供します。

  • Sessionsを作成します。

  • コネクション・メタデータを提供します。

  • オプションのExceptionListenerをサポートします。

データベースへのJMSコネクションは、createConnection()createQueueConnection()またはcreateTopicConnection()を起動し、ConnectionFactoryオブジェクト、QueueConnectionFactoryオブジェクトまたはTopicConnectionFactoryオブジェクトにそれぞれパラメータusernameおよびpasswordを渡して作成できます。

次に、Connectionオブジェクトでサポートされているメソッドのいくつかを示します。

  • start()

    このメソッドは、着信メッセージの配信を開始または再開します。

  • stop()

    このメソッドは、着信メッセージの配信を一時停止します。Connectionオブジェクトが停止すると、すべてのメッセージ・コンシューマへの配信は禁止されます。また、同期受信のブロックおよびメッセージは、メッセージ・リスナーに配信されません。

  • close()

    このメソッドは、JMSセッションをクローズして、関連付けられたすべてのリソースを解放します。

  • createSession(true, 0)

    このメソッドは、JMS Connectionインスタンスを使用してJMS Sessionを作成します。

  • createQueueSession(true, 0)

    このメソッドはQueueSessionを作成します。

  • createTopicSession(true, 0)

    このメソッドはTopicSessionを作成します。

  • setExceptionListener(ExceptionListener)

    このメソッドは、Connectionの例外リスナーを設定します。問題が非同期でクライアントに通知されます。メッセージを処理するのみのConnectionの場合、その失敗を確認する他の方法はありません。

  • getExceptionListener()

    このメソッドは、このConnectionExceptionListenerを取得します。

JMSクライアントは、通常1つのConnection、1つのSession、複数のMessageProducerおよびMessageConsumerオブジェクトを作成します。現在のバージョンでは、次の場合を除いて、1つのConnectionにつき1つのオープンSessionのみが許可されています。

  • JDBC OCI8ドライバを使用してJMSコネクションを作成する場合

  • ユーザーが、JMSコネクションの作成時にOracleOCIConnectionPoolインスタンスを提供する場合

Connectionは停止モードで作成されます。この状態では、メッセージを受信できません。通常、設定が完了するまで、Connectionを停止モードにしておきます。その時点でConnection start()メソッドがコールされ、メッセージがConnectionコンシューマに配信され始めます。このような設定規則を確立することにより、クライアントが設定されている最中の非同期メッセージ配信の結果、発生するクライアントの混乱を最小限に止められます。

Connectionを起動し、続けて設定を実行できます。これを実行するクライアントは、設定処理中に非同期メッセージの配信処理の準備をする必要があります。MessageProducerは、Connectionが停止中でもメッセージを送信できます。

JMSセッション

JMS Sessionは、メッセージの作成および処理用の単一スレッドのコンテキストです。これは、Java Virtual Machine(JVM)の外でプロバイダ・リソースを割り当てますが、軽量なJMSオブジェクトとみなされます。

Sessionには、次の役割があります。

  • MessageProducerおよびMessageConsumerオブジェクトのファクトリを構成します。

  • 宛先オブジェクト(キュー/トピック)に対するハンドルの取得方法を提供します。

  • プロバイダが最適化したメッセージ・ファクトリを提供します。

  • セッションのMessageProducerおよびMessageConsumerオブジェクトにまたがる作業を組み合せる一連のトランザクションをサポートし、これらを単位に構成します。

  • セッションが処理および作成するメッセージのシリアル順序を定義します。

  • セッションに登録されたMessageListenerオブジェクトの実行をシリアル化します。

Oracle Database 10gでは、JDBC thinまたはJDBC thick(OCI)ドライバのいずれかを使用すると、単一のJMS Connectionを使用して、リソースが許すかぎり多くのJMS Sessionを作成できます。

プロバイダが、JVM外のSessionのためのリソースを割り当てることができるため、クライアントはリソースが必要ないときはこれらを閉じる必要があります。ガベージ・コレクションによる最終的なリソースの解放を待つ必要はありません。Sessionが作成したMessageProducerおよびMessageConsumerオブジェクトについても同様です。

Sessionオブジェクトのメソッドには、次のものが含まれます。

  • commit()

    このメソッドは、トランザクションで実行されるすべてのメッセージをコミットして、現在保持されているロックを解放します。

  • rollback()

    このメソッドは、トランザクションで実行されたすべてのメッセージをロールバックして、現在保持されているロックを解放します。

  • close()

    このメソッドはSessionをクローズします。

  • getDBConnection()

    このメソッドは、基礎となるJDBCコネクションに対するハンドルを取得します。このハンドルを使用して、他のSQL DML操作を同じSessionの一部として実行できます。このメソッドは、Oracle JMSに固有です。

  • acknowledge()

    このメソッドは、非トランザクション・セッションでメッセージの受信を承認します。

  • recover()

    このメソッドは、非トランザクション・セッションでメッセージの配信を再開します。セッション中に配信された一連のメッセージは、最後に承認されたメッセージの後でリセットされます。

Oracle JMSの拡張例は、次のとおりです。

  • createQueueTable()

    このメソッドはキュー表を作成します。

  • getQueueTable()

    このメソッドは既存のキュー表に対するハンドルを取得します。

  • createQueue()

    このメソッドはキューを作成します。

  • getQueue()

    このメソッドは既存のキューに対するハンドルを取得します。

  • createTopic()

    このメソッドはトピックを作成します。

  • getTopic()

    このメソッドは既存のトピックに対するハンドルを取得します。

どの拡張機能を使用する場合も、SessionオブジェクトをAQjmsSessionにキャストする必要があります。


注意:

JMS仕様では、開始されていないJMS Connectionインスタンスで受信が完了したとき、プロバイダによりNULLメッセージが返されることを要求します。

javax.jms.Connectionインスタンスの作成後、start()メソッドをそのインスタンスにコールしてメッセージを受信できるようにする必要があります。コネクション確立後で実際に受信する前に、t_conn.start();などの行を追加するとメッセージを受信できます。


JMS宛先

Destinationは、クライアントがメッセージの送信先および受信元の指定に使用するオブジェクトです。DestinationオブジェクトはQueueまたはTopicに指定できます。Oracle Database Advanced Queuingでは、特定のデータベースのschema.queueにマップされます。Queueは単一コンシューマ・キューに、Topicはマルチ・コンシューマ・キューにマップします。

JMSセッションを使用したDestinationオブジェクトの取得

Destinationオブジェクトは、Sessionオブジェクトからドメイン固有の次のSessionメソッドを使用して作成されます。

  • AQjmsSession.getQueue(queue_owner, queue_name)

    このメソッドはJMSキューに対するハンドルを取得します。

  • AQjmsSession.getTopic(topic_owner, topic_name)

    このメソッドはJMSトピックに対するハンドルを取得します。

JNDIを使用したDestinationオブジェクトの検索

LDAPサーバーにスキーマ・オブジェクトを登録するようにデータベースを設定できます。データベースがLDAPを使用できるように設定され、GLOBAL_TOPIC_ENABLEDパラメータがTRUEに設定されている場合、すべてのJMSキューおよびトピックは、作成時に自動的にLDAPサーバーに登録されます。また、管理者は、LDAPに登録されているキューおよびトピックの別名を作成することもできます。LDAPに登録されているキューおよびトピックは、キュー/トピック名またはその別名を使用してJNDIを介して検索できます。

JMS宛先メソッド

Destinationオブジェクトのメソッドには、次のものが含まれます。

  • alter()

    このメソッドはキューまたはトピックを変更します。

  • schedulePropagation()

    このメソッドは、ソースから宛先への伝播をスケジューリングします。

  • unschedulePropagation()

    このメソッドは、スケジュール済伝播のスケジュールを解除します。

  • enablePropagationSchedule()

    このメソッドは、伝播スケジュールを有効化します。

  • disablePropagationSchedule()

    このメソッドは、伝播スケジュールを無効化します。

  • start()

    このメソッドはキューまたはトピックを開始します。キューは、エンキューまたはデキューを可能にするために開始されます。トピックは、パブリッシュまたはサブスクライブを可能にするために開始できます。

  • stop()

    このメソッドはキューまたはトピックを停止します。キューは、エンキューまたはデキューを実行不可にするために停止できます。トピックは、パブリッシュまたはサブスクライブを実行不可にするために停止できます。

  • drop()

    このメソッドはキューまたはトピックを削除します。

JMSでのシステム・レベルのアクセス制御

Oracle8i以上では、すべてのキューイング操作に対してシステム・レベルのアクセス制御をサポートします。この機能によって、アプリケーション設計者またはDBAは、ユーザーをキュー管理者にできます。キュー管理者は、データベースのどのキューに対してもJMSインタフェース(管理および操作)を起動できます。これによって、データベース上のキュー全体に対するすべての管理スクリプトを1つのスキーマで管理できるため、管理作業が容易になります。

メッセージが宛先キューに届くと、ソース・キューのスキーマ名に基づいたセッションによって、新しく届いたメッセージが宛先キューにエンキューされます。つまり、ソース・キューのスキーマに宛先キューに対するエンキュー権限を付与する必要があります。

リモートの宛先キューに伝播するために、エージェント構造体のアドレス・フィールドのデータベース・リンクに指定されたログイン・ユーザーには、ENQUEUE_ANY権限を付与するか、または宛先キューに対するエンキュー権限を付与する必要があります。ただし、データベース・リンクのログイン・ユーザーが宛先のキュー表を所有している場合はどのような明示的な権限も付与する必要はありません。

JMSでの宛先レベルのアクセス制御

Oracle8i以上では、エンキューおよびデキュー操作に対してキュー・レベルまたはトピック・レベルのアクセス制御をサポートしています。この機能によって、アプリケーション設計者は、あるスキーマに作成されたキューおよびトピックを他のスキーマで実行中のアプリケーションから保護できます。そのキューまたはトピックが属するスキーマの外で実行しているアプリケーションには、最小限のアクセス権限のみを付与できます。キューまたはトピックに対するアクセス権限として、ENQUEUEDEQUEUEおよびALLがサポートされています。

JMSでの保存およびメッセージ履歴

メッセージは、相互に関連していることがよくあります。たとえば、あるメッセージを処理した結果として他のメッセージが生成された場合、両者は関連付けられています。アプリケーション設計者としては、そのような関連を追跡することが必要な場合があります。Oracle Database Advanced Queuingでは、ユーザーがメッセージをキュー表に保持し、分析のためにSQLで問合せできます。

保存機能およびメッセージ識別子とともに、メッセージ・ジャーナルがOracle Database Advanced Queuingによって自動作成され、追跡ジャーナルまたはイベント・ジャーナルをコールできます。保存、メッセージ識別子およびSQL問合せの協調によって、強力なメッセージ・ウェアハウスを構築できます。

JMSでのOracle Real Application Clustersのサポート

Oracle Database 12cリリース1 (12.1)では、Advanced Queuingに、高性能でスケーラブルなJMSシャード・キューが導入されました。シャード・キューとは、システムで管理されているパーティション化を使用して、独立した複数の物理キューに分割される1つの論理キューです。シャード・キューは、Oracle RACインスタンス全体で使用されるキュー、エンキュー率またはデキュー率の高いキュー、またはサブスクライバの多いキューについて推奨されるJMSキューです。詳細は、「JMSシャード・キューおよびOracle Real Application Clusters (Oracle RAC)」を参照してください。

非シャード・キューの場合は、Oracle Real Application Clusters (Oracle RAC)を使用して、各インスタンスを別々のキューで管理できるようにすることで、Oracle Database Advanced Queuingのパフォーマンスを向上できます。このためには、キューを格納するキュー表に様々なインスタンス・アフィニティ(作業環境)を指定します。これによって、様々なキュー/トピックに対するキュー操作(エンキューまたはデキュー)またはトピック操作(パブリッシュ・サブスクライブ)を並行して行うことができるようになります。

Oracle Database Advanced Queuingのキュー・モニター・プロセスは、キュー表のインスタンス・アフィニティを継続的に監視します。キュー・モニターは指定されたプライマリ・インスタンスが使用可能な場合はそれにキュー表の所有権を割り当て、失敗した場合は指定されたセカンダリ・インスタンスに割り当てます。

キュー表を所有しているインスタンスが終了すると、キュー・モニターはセカンダリ・インスタンスなどの適切なインスタンスに所有者を変更します。

Oracle Database Advanced Queuingの伝播はOracle Real Application Clustersでも使用できますが、これはユーザーに対して透過的です。伝播スケジュールのジョブ・アフィニティは、それぞれのキュー表のアフィニティと同じ値に設定されます。このように、キュー表を所有するインスタンスに対応付けられたjob_queue_processは、そのキュー表に格納されているキューからの伝播を処理し、ping操作を最小限に抑えます。


関連項目:


JMSでの統計ビューのサポート

各インスタンスは、それぞれのOracle Database Advanced Queuing統計情報をシステム・グローバル領域(SGA)に所有し、他のインスタンスによって収集された統計については認識しません。そのため、インスタンスがGV$AQビューを問い合せると、その他のすべてのインスタンスからそれぞれのその時点の統計情報が問合せ元のインスタンスに集まります。

GV$AQビューは、待機中、準備完了または期限切れの各メッセージ数を必要なときにいつでも問い合せることができます。また、メッセージが処理されるまでの平均待機秒数も表示します。

JMSでの構造化ペイロード/メッセージの型

JMSメッセージは、ヘッダー、プロパティおよび本体で構成されています。

ヘッダーは、クライアントおよびプロバイダの両方でメッセージの識別およびルーティングに使用される値が含まれるヘッダー・フィールドで構成されています。すべてのメッセージは、同じ一連のヘッダー・フィールドをサポートしています。

プロパティは、オプションのヘッダー・フィールドです。JMSによって定義された標準プロパティの他に、プロバイダ固有およびアプリケーション固有のプロパティを含めることもできます。

本体はメッセージ・ペイロードです。JMSは、様々な型のメッセージ・ペイロードおよびJMSで指定されたメッセージ型のJMSメッセージを格納できる型を定義します。

この項の内容は次のとおりです。

JMSメッセージ・ヘッダー

JMSメッセージ・ヘッダーには、次のフィールドが含まれます。

  • JMSDestination

    このフィールドには、メッセージの送信先が含まれます。Oracle Database Advanced Queuingでは、これは送信先キューまたはトピックに相当します。Sendメソッドの完了後にJMSによって設定されるDestination型です。

  • JMSDeliveryMode

    このフィールドは、メッセージのログが記録されるかどうかを決定します。JMSでは、PERSISTENT送信(メッセージが決まった記憶域にロギングされる)およびNONPERSISTENT送信(メッセージがロギングされない)をサポートしています。Sendメソッドの完了後にJMSによって設定されるINTEGERです。JMSでは、クライアントが指定したJMSDeliveryModeの値をオーバーライドするよう管理者がJMSを構成することが可能です。

  • JMSMessageID

    このフィールドは、プロバイダ内のメッセージを一意に識別します。すべてのメッセージIDは先頭に文字列ID:を使用する必要があります。Sendメソッドの完了後にJMSによって設定されるString型です。

  • JMSTimeStamp

    このフィールドには、送信先のプロバイダにメッセージが渡された時間が含まれます。Oracle Database Advanced Queuingのメッセージのエンキュー時間にマッピングされます。Sendメソッドの完了後にJMSによって設定されるLong型です。

  • JMSCorrelationID

    このフィールドは、クライアントがメッセージを別のメッセージにリンクするために使用できます。JMSクライアントによって設定されるString型です。

  • JMSReplyTo

    このフィールドには、メッセージ送信時にクライアントが指定するDestination型が含まれます。クライアントはoracle.jms.AQjmsAgentjavax.jms.Queueまたはjavax.jms.Topicを使用できます。

  • JMSType

    このフィールドには、送信時にクライアントが指定するメッセージ・タイプの識別子が含まれます。これはString型です。移植性を高めるために、JMSTypeに記号値を使用することをお薦めします。

  • JMSExpiration

    このフィールドは、非Java EE準拠モードでは、エンキュー時間とTimeToLiveの合計です。準拠モードでは、デキューされたメッセージのJMSExpirationヘッダー値は、メッセージのエンキュー時のJMSTimeStamp (ミリ秒単位のグリニッジ標準時)とTimeToLive (ミリ秒単位)の合計です。Sendメソッドの完了後にJMSによって設定されるLong型です。JMSでは、クライアントが指定したJMSExpirationの値をオーバーライドするよう管理者がJMSを構成することが可能です。

  • JMSPriority

    このフィールドには、メッセージの優先度が含まれます。Sendメソッドの完了後にJMSによって設定されるINTEGERです。Java EE準拠モードでは、優先度に使用できる値は0から9で、9が優先度が最も高く、4がデフォルトで、Sun Microsystem JMS 1.1標準に準拠しています。デフォルトは非準拠モードです。JMSでは、クライアントが指定したJMSPriorityの値をオーバーライドするよう管理者がJMSを構成することが可能です。

  • JMSRedelivered

    このフィールドは、JMSプロバイダによって設定されたブールです。

JMSメッセージ・プロパティ

JMSプロパティは、クライアントによって明示的に設定されるか、またはJMSプロバイダによって自動的に設定されます(通常、これらは読取り専用です)。JMSプロパティには、SendおよびReceive操作に指定されたパラメータを使用して設定されるものもあります。

プロパティで、メッセージにオプションのヘッダー・フィールドを追加できます。プロパティによって、クライアントは、messageSelectorを使用して、クライアントのかわりにJMSプロバイダにアプリケーション固有基準を使用してメッセージを選択させることができます。プロパティ名は文字列で、サポートされている値はBooleanByteShortIntegerLongFloatDoubleおよびStringです。

JMS定義のプロパティは、すべてJMSXで始まります。次のものがあります。

  • JMSXUserID

    このフィールドは、メッセージの送信元ユーザーの識別情報です。Sendメソッドの完了後にJMSによって設定されるString型です。

  • JMSXAppID

    このフィールドは、メッセージの送信元アプリケーションの識別情報です。Sendメソッドの完了後にJMSによって設定されるString型です。

  • JMSXDeliveryCount

    このフィールドは、メッセージの送信試行回数です。Sendメソッドの完了後にJMSによって設定されるIntegerです。

  • JMSXGroupid

    このフィールドは、メッセージが属するメッセージ・グループの識別情報です。JMSクライアントによって設定されるString型です。

  • JMSXGroupSeq

    このフィールドは、グループ内のメッセージの順序番号です。JMSクライアントによって設定されるInteger型です。

  • JMSXRcvTimeStamp

    このフィールドは、コンシューマにメッセージが配信された時間(デキュー時間)です。Receiveメソッドの完了後にJMSによって設定されるString型です。

  • JMSXState

    このフィールドは、プロバイダによって設定されたメッセージ状態です。メッセージ状態は、WAITINGREADYEXPIREDまたはRETAINEDです。

Oracle固有のJMSプロパティは、すべてJMS_Oracleで始まります。次のものがあります。

  • JMS_OracleExcpQ

    このフィールドは、元の宛先に配信できないメッセージを送信するキュー名です。JMSクライアントによって設定されるString型です。EXCEPTIONタイプの宛先のみをJMS_OracleExcpQプロパティで指定できます。

  • JMS_OracleDelay

    このフィールドは、メッセージの配信を遅延する時間(秒単位)です。JMSクライアントによって設定されるInteger型です。これは、メッセージの配信順序に影響を与える可能性があります。

  • JMS_OracleOriginalMessageId

    このフィールドは、メッセージがある宛先から別の宛先に伝播された場合に、ソースのメッセージのメッセージ識別子に設定されます。JMSプロバイダによって設定されるString型です。メッセージが伝播されていない場合、このプロパティはJMSMessageIdと同じ値です。

クライアントは、プロパティを定義することによって、メッセージにヘッダー・フィールドを追加できます。これらのプロパティをmessageSelectorで使用して特定のメッセージを選択できます。

JMSメッセージ本体

JMSでは、次の5つのフォーマットのメッセージ本体が提供されます。

StreamMessage

StreamMessageオブジェクトは、Javaプリミティブのストリームの送信に使用されます。このオブジェクトの入力および読取りは順次実行されます。これはMessageから継承し、StreamMessage本文を追加します。このメソッドは、主にjava.io.DataInputStreamおよびjava.io.DataOutputStreamのメソッドに基づいています。

基本データ型の値は、それぞれの型のメソッドを使用して、明示的に読込みまたは書込みできます。抽象的なオブジェクトとして読込みまたは書込みすることもできます。StreamMessageオブジェクトを使用するには、SYS.AQ$_JMS_STREAM_MESSAGEまたはAQ$_JMS_MESSAGEペイロード型を持つキュー表を作成します。

StreamMessageオブジェクトは、表11-1に示す変換をサポートします。行の型として書き込まれる値は、列の型として読み込むことができます。

表11-1 StreamMessageの変換

入力 Boolean Byte Short Char Int Long Float Double String Byte[]

Boolean

X

-

-

-

-

-

-

-

X

-

Byte

-

X

X

-

X

X

-

-

X

-

Short

-

-

X

-

X

X

-

-

X

-

Char

-

-

-

X

-

-

-

-

X

-

Int

-

-

-

-

X

X

-

-

X

-

Long

-

-

-

-

-

X

-

-

X

-

Float

-

-

-

-

-

-

X

X

X

-

Double

-

-

-

-

-

-

-

X

X

-

String

X

X

X

X

X

X

X

X

X

-

Byte[]

-

-

-

-

-

-

-

-

-

X


BytesMessage

BytesMessageオブジェクトは、1つの未解釈バイトのストリームを含むメッセージを送信する場合に使用します。これはMessageから継承し、BytesMessage本文を追加します。メッセージの受信者が、そのバイト列を解析します。このメソッドは、主にjava.io.DataInputStreamおよびjava.io.DataOutputStreamのメソッドに基づいています。

これは、クライアントが既存のメッセージ・フォーマットをコード化するためのメッセージ型です。可能であれば、かわりに他の自己定義メッセージ型を使用してください。

Javaの基本データ型の値は、それぞれの型のメソッドを使用して、明示的に書込みができます。また、抽象的なオブジェクトとして書き込むこともできます。BytesMessageオブジェクトを使用するには、SYS.AQ$_JMS_BYTES_MESSAGEまたはAQ$_JMS_MESSAGEペイロード型を持つキュー表を作成します。

MapMessage

MapMessageオブジェクトは、名前がString型で値がJava基本データ型である名前/値ペアの集合を送信する場合に使用します。エントリには、名前で順次またはランダムにアクセスできます。エントリの順序は未定義です。これはMessageから継承し、MapMessage本文を追加します。基本データ型の値は、それぞれの型のメソッドを使用して、明示的に読込みまたは書込みできます。抽象的なオブジェクトとして読込みまたは書込みすることもできます。

MapMessageオブジェクトを使用するには、SYS.AQ$_JMS_MAP_MESSAGEまたはAQ$_JMS_MESSAGEペイロード型を持つキュー表を作成します。MapMessageオブジェクトは、表11-2に示す変換をサポートします。この表の「X」は、行の型として書き込まれる値を列の型として読み取ることができることを意味します。

表11-2 MapMessageの変換

入力 Boolean Byte Short Char Int Long Float Double String Byte[]

Boolean

X

-

-

-

-

-

-

-

X

-

Byte

-

X

X

-

X

X

-

-

X

-

Short

-

-

X

-

X

X

-

-

X

-

Char

-

-

-

X

-

-

-

-

X

-

Int

-

-

-

-

X

X

-

-

X

-

Long

-

-

-

-

-

X

-

-

X

-

Float

-

-

-

-

-

-

X

X

X

-

Double

-

-

-

-

-

-

-

X

X

-

String

X

X

X

X

X

X

X

X

X

-

Byte[]

-

-

-

-

-

-

-

-

-

X


TextMessage

TextMessageオブジェクトは、java.lang.StringBufferを含むメッセージを送信する場合に使用します。これはMessageから継承し、TextMessage本文を追加します。テキスト情報は、getText()およびsetText(...)メソッドを使用して読込みまたは書込みができます。TextMessageオブジェクトを使用するには、SYS.AQ$_JMS_TEXT_MESSAGEまたはAQ$_JMS_MESSAGEペイロード型を持つキュー表を作成します。

ObjectMessage

ObjectMessageオブジェクトは、シリアライズ可能なJavaオブジェクトを含むメッセージを送信する場合に使用します。これはMessageから継承し、単一のJava参照を含む本文を追加します。シリアライズ可能なJavaオブジェクトのみ使用できます。Javaオブジェクトのコレクションを送信する必要がある場合、JDK 1.4で提供されているコレクション・クラスのいずれかを使用できます。オブジェクトは、getObject()メソッドおよびsetObject(...)メソッドを使用して読込みまたは書込みできます。ObjectMessageオブジェクトを使用する場合、SYS.AQ$_JMS_OBJECT_MESSAGEまたはAQ$_JMS_MESSAGEペイロード型でキュー表を作成します。

AdtMessage

AdtMessageオブジェクトは、Oracleのオブジェクト型に対応するJavaオブジェクトを含むメッセージを送信する場合に使用します。これらのオブジェクトはMessageから継承され、CustomDatumまたはORADataインタフェースを実装するJavaオブジェクトを含む本体を追加します。


関連項目:

CustomDatumインタフェースおよびORADataインタフェースの詳細は、『Oracle Database Java開発者ガイド』を参照してください。

AdtMessageオブジェクトを使用するには、Oracleのオブジェクト型としてのペイロード型を持つキュー表を作成します。AdtMessageのペイロードは、getAdtPayloadおよびsetAdtPayloadメソッドを使用して、読取りおよび書込みができます。

AdtMessageオブジェクトを使用してSYS.XMLType型のキューへメッセージを送信することもできます。oracle.xdb.XMLTypeクラスを使用してメッセージを作成する必要があります。

AdtMessageオブジェクトの場合、クライアントが次を取得できます。

  • JMSXDeliveryCount

  • JMSXRecvTimeStamp

  • JMSXState

  • JMS_OracleExcpQ

  • JMS_OracleDelay

異なるメッセージ型でのメッセージ・プロパティの使用

次のメッセージ・プロパティは、クライアントがsetPropertyコールを使用して設定できます。StreamMessageBytesMessageObjectMessageTextMessageおよびMapMessageオブジェクトの場合、クライアントによって次の設定ができます。

  • JMSXAppID

  • JMSXGroupID

  • JMSXGroupSeq

  • JMS_OracleExcpQ

  • JMS_OracleDelay

AdtMessageオブジェクトの場合、クライアントによって次の設定ができます。

  • JMS_OracleExcpQ

  • JMS_OracleDelay

次のメッセージ・プロパティは、クライアントがgetPropertyコールを使用して取得できます。StreamMessageBytesMessageObjectMessageTextMessageおよびMapMessageオブジェクトの場合、クライアントが次を取得できます。

  • JMSXuserID

  • JMSXAppID

  • JMSXDeliveryCount

  • JMSXGroupID

  • JMSXGroupSeq

  • JMSXRecvTimeStamp

  • JMSXState

  • JMS_OracleExcpQ

  • JMS_OracleDelay

  • JMS_OracleOriginalMessageId

Oracle JMSを使用したバッファ済メッセージ

メッセージの送信時にdeliveryModeとしてNON_PERSISTENTを指定すると、非永続JMSメッセージを送信できます。JMS非永続メッセージは決まった記憶域に記録する必要がないため、JMSシステム障害が発生すると消失する可能性があります。JMS非永続メッセージはOracle Database Advanced Queuingで使用可能になったバッファ済メッセージに類似していますが、両者には重要な相違点も存在します。


注意:

Oracle JMSの非永続メッセージを、Oracle Database 10gリリース2(10.2)で非推奨になったOracle Database Advanced Queuingの非永続キューと混同しないでください。

トランザクションのコミットとクライアントの確認

JMSのdeliveryModeは、メッセージのトランザクション属性と直交します。JMS非永続メッセージは、処理済セッションまたは非処理済セッションで送受信できます。JMS非永続メッセージを処理済セッションで送受信する場合、JMS操作の効果は処理済セッションのコミット後にのみ参照可能です。CLIENT_ACKNOWLEDGE確認モードの非処理済セッションで受信する場合、このメッセージの受信による効果は、クライアントがメッセージを確認した後にのみ参照可能です。確認されない場合、メッセージは削除されず、クライアントがSession.recoverをコールすると再配信されます。

これに対して、Oracle Database Advanced Queuingのバッファ済メッセージでは、このようなトランザクションまたは確認の概念はサポートされません。バッファ済メッセージの送受信は、どちらもIMMEDIATE可視性モードで実行する必要があります。したがって、セッションがコミットされたかどうかやメッセージが確認されたかどうかは関係なく、ユーザーは送受信操作の効果を即時に参照できます。

各種API

通常のJMS送信およびパブリッシュ・メソッドで送信されるメッセージは、Oracle Database Advanced Queuingでは永続メッセージとして扱われます。通常のJMS受信メソッドは、AQ永続メッセージのみを受信します。バッファ済メッセージを送受信するには、Oracle拡張APIであるbufferSendbufferPublishおよびbufferReceiveを使用する必要があります。


関連項目:

bufferSendbufferPublishおよびbufferReceiveの詳細は、Oracle Databaseアドバンスト・キューイングJava APIリファレンスを参照してください

ペイロード制限

バッファ済メッセージのOracle Database Advanced Queuing実装では、LOB属性はサポートされていません。このため、5種類の標準JMSメッセージのペイロードには次の制限が適用されます。

  • JMS TextMessageのペイロードは4000バイト以内です。

    Oracle JMSのキャラクタ・セット変換時には、テキスト・ペイロードをデータベースに格納するためにVARCHARのかわりにCLOBを使用するように控え目な選択が必要になる場合があるため、データベース・キャラクタ・セットによってはこの上限値がさらに低くなる場合があります。

  • JMS BytesMessageのペイロードは2000バイト以内です。

  • JavaでシリアライズされたJMS ObjectMessageStreamMessageおよびMapMessageデータは、2000バイト以内である必要があります。

  • 他のすべてのOracle JMS ADTメッセージの場合、対応するOracleデータベースADTにLOB属性を含めることはできません。

各種定数

表11-3に示すように、Oracle Database Advanced QueuingとOracle JMSのAPIでは、バッファ済メッセージと永続メッセージの指定に使用される数値が異なります。

表11-3 Oracle Database AQとOracle JMSのバッファ済メッセージ定数

API 永続メッセージ バッファ済メッセージ

Oracle Database Advanced Queuing


PERSISTENT := 1

BUFFERED :=2

Oracle JMS

PERSISTENT := 2

NON_PERSISTENT := 1


JMS Point-to-Pointモデル機能

Point-to-Pointモデルでは、クライアントは、1つのポイントから別のポイントへメッセージを交換します。メッセージのプロデューサとコンシューマは、シングル・コンシューマ・キューを使用してメッセージを送受信します。管理者は、AQjmsSessioncreateQueueメソッドを使用して、シングル・コンシューマ・キューを作成します。キューを使用する前に、AQjmsDestinationstartコールを使用して、キューをエンキュー/デキューに対して有効にする必要があります。クライアントは、AQjmsSessiongetQueueメソッドを使用して事前に作成されたキューに対するハンドルを取得します。

シングル・コンシューマ・キューの場合、メッセージは1つのコンシューマが1度のみ処理できます。同じキューから同時にデキューするプロセスまたはオペレーティング・システム・スレッドが複数存在する場合、各プロセスはキューの先頭にあるロックされていない最初のメッセージをデキューします。ロックを作成したプロセス以外のプロセスは、ロックされたメッセージをデキューできません。

処理が済むと、キューの保存期間が0(ゼロ)の場合はそのメッセージは削除され、そうでない場合は指定された期間保存されます。メッセージが保存されている間は、キュー表ビューに対してSQLを使用して問い合せたり、QueueBrowserで処理済メッセージのメッセージ識別子を指定してデキューできます。

QueueSender

クライアントは、QueueSenderを使用して、キューにメッセージを送信します。これは、クライアントのSessionでキューをcreateSenderメソッドに渡すことによって作成されます。また、クライアントにはキューを指定しないで、QueueSenderを作成するオプションがあります。この場合、キューを送信操作のたびに指定する必要があります。

クライアントは、QueueSenderによって送信されたすべてのメッセージのデフォルト配信モード、優先順位およびTimeToLiveを指定できます。または、クライアントはこれらのオプションを各メッセージに対して定義できます。

QueueReceiver

クライアントはQueueReceiverを使用してキューからメッセージを受信します。これは、クライアントのSessioncreateQueueReceiverを使用して作成されます。messageSelectorがあってもなくても作成できます。

QueueBrowser

QueueBrowserを使用すると、クライアントはメッセージを削除しないで、キュー上でメッセージを参照できます。このブラウズ用メソッドは、キュー内のメッセージをスキャンするために使用されるjava.util.Enumerationを戻します。nextElementに対する最初のコールが、キューのスナップショットを取得します。QueueBrowserは、messageSelectorを使用して作成しても、使用せずに作成してもかまいません。

QueueBrowserも、メッセージをスキャン中にオプションでロックできます。これは、メッセージに対するSELECT...for UPDATEコマンドの場合と似ています。これによって、他のコンシューマがスキャン中のメッセージを削除することはなくなります。

MessageSelector

messageSelectorによって、クライアントは、コンシューマに配信されるメッセージをmessageSelector式と一致するメッセージに制限できるようになります。TextMessage型、StreamMessage型、BytesMessage型、ObjectMessage型またはMapMessage型のペイロードを含むキューのmessageSelectorには、次の1つ以上を持つ任意の式を含めることができます。

  • 接頭辞「ID:」が付いたJMSメッセージ識別子

    JMSMessageID ='ID:23452345'
    
  • JMSメッセージ・ヘッダー・フィールドまたはプロパティ

    JMSPriority < 3 AND JMSCorrelationID = 'Fiction'
    
    JMSCorrelationID LIKE 'RE%'
    
  • ユーザー定義のメッセージ・プロパティ

    color IN ('RED', BLUE', 'GREEN') AND price < 30000 
    

AdtMessage型のペイロードを含むキューのmessageSelectorには、次の1つ以上を持つ任意の式を含めることができます。

  • 接頭辞「ID:」なしのメッセージ識別子

    msgid = '23434556566767676'
    
  • 優先順位または相関識別子、あるいはその両方

    priority < 3 AND corrid = 'Fiction'
    
  • メッセージ・ペイロード

    tab.user_data.color = 'GREEN' AND tab.user_data.price < 30000
    

JMSパブリッシュ・サブスクライブ・モデル機能

この項の内容は次のとおりです。

JMSパブリッシュ・サブスクライブの概要

JMSでは、パブリッシャ(出版者)の機能を持つアプリケーションとサブスクライバ(購読者)の役割を果すアプリケーションとの間の柔軟で動的な通信が可能です。アプリケーションが結合されることはなく、メッセージとその内容に基づいて相互に作用します。

メッセージの配信では、パブリッシャ・アプリケーションが明示的にメッセージ受信者を処理または管理する必要はありません。このため、パブリッシャ・アプリケーションの論理を変更しなくても、新しいサブスクライバ・アプリケーションを動的に追加できます。

同様にサブスクライバ・アプリケーションは、メッセージを送信しているパブリッシャ・アプリケーションに関係なく、メッセージの内容に基づいてメッセージを受信します。このため、サブスクライバ・アプリケーションの論理を変更しなくても、新しいパブリッシャ・アプリケーションを動的に追加できます。

サブスクライバ・アプリケーションは、メッセージ・プロパティまたはトピックのメッセージ内容に対してルールベースのサブスクリプション(予約購読)を定義することで、どのようなメッセージに関心があるのかを指定できます。システムは、ルールベースのサブスクリプションを使用して、パブリッシュされたメッセージの受信者を計算し、自動的にルーティングします。

パブリッシュ・サブスクライブ・モデルでは、メッセージはトピックに対してパブリッシュされ、トピックから受信されます。トピックは、AQjmsSessionCreateTopic()メソッドを使用して作成されます。クライアントは、AQjmsSessiongetTopic()メソッドを使用して事前に作成されたトピックに対するハンドルを取得できます。

DurableSubscriber

クライアントはDurableSubscriberを、クライアントのSession内でcreateDurableSubscriber()メソッドを使用して作成します。messageSelectorがあってもなくても作成できます。

messageSelectorによって、クライアントは、サブスクライバに配信されるメッセージをセレクタにマッチするメッセージに制限できます。セレクタ構文の詳細は、Oracle Databaseアドバンスト・キューイングJava APIリファレンスcreateDurableSubscriberに関する項を参照してください。


関連項目:

「MessageSelector」

永続サブスクライバが同じ名前を使用するときのアクションは、実行時にOracle Java Message Service (Oracle JMS)クライアントに設定されるJava EE準拠モードによって異なります。

非準拠モードでは、同じ名前の2つの永続的なTopicSubscriberオブジェクトが、2つの異なるトピックに対してアクティブになることができます。準拠モードでは、複数の永続サブスクライバが同じ名前を持つことは許可されません。同じトピックに対して作成された2つのサブスクライバが同じ名前を使用する場合、各サブスクライバに使用されるセレクタが異なると、DBMS_AQJMS.ALTER_SUBSCRIBER()の内部コールを使用して、基になるOracle Database Advanced Queuingサブスクリプションが変更されます。

2つのサブスクライバが同じ名前を使用し、2つの異なるトピックに対して作成される場合、同じサブスクリプション名を使用するクライアントがそれぞれサブスクリプション名を作成すると、既存のサブスクリプションは削除され新しいサブスクリプションが作成されます。

2つのサブスクライバが同じ名前を使用し、2つの異なるトピックに対して作成される場合、別のクライアント(最初にそのサブスクリプション名を作成したクライアントではない)が既存のサブスクリプション名を使用すると、サブスクリプションは削除されずにエラーが発生します。サブスクリプションがJMSまたはPL/SQLのどちらで作成されたかが不明であるため、その他のトピックについてのサブスクリプションは削除しないでください。

RemoteSubscriber

リモート・サブスクライバは、createRemoteSubscriberコールを使用して定義されます。リモート・サブスクライバは、リモート・トピックでの特定のコンシューマ、またはリモート・トピックでのすべてのサブスクライバになることができます。

リモート・サブスクライバは、AQjmsAgent構造を使用して定義されます。AQjmsAgentは、名前およびアドレスで構成されます。名前は、リモート・トピックのconsumer_nameを参照します。アドレスは、次のようにしてリモート・トピックを参照します。

schema.topic_name[@dblink]

リモート・トピックで特定のコンシューマに対してメッセージをパブリッシュするには、リモート・トピックでの受信者subscription_nameが、AQjmsAgentの名前フィールドに指定されている必要があります。リモート・トピックは、AQjmsAgentのaddressフィールドに指定される必要があります。

リモート・トピックのすべてのサブスクライバに対してメッセージをパブリッシュするには、AQjmsAgentのnameフィールドをNULLに設定する必要があります。リモート・トピックは、AQjmsAgentのaddressフィールドに指定される必要があります。

TopicPublisher

メッセージはTopicPublisherを使用してパブリッシュされます。これは、TopiccreatePublisherメソッドに渡すことによって作成されます。また、クライアントにはTopicを指定しないで、TopicPublisherを作成するオプションがあります。この場合、Topicをパブリッシュ操作のたびに指定する必要があります。クライアントは、TopicPublisherによって送信されるすべてのメッセージのデフォルト配信モード、優先順位およびTimeToLiveを指定できます。また、各メッセージごとに、これらのオプションを指定することもできます。

受信者リスト

JMSパブリッシュ・サブスクライブ・モデルでは、クライアントは、トピックのすべてのサブスクライバにメッセージを送信するのではなく、明示的な受信者リストを指定できます。これらの受信者は、トピックの既存のサブスクライバである場合もあれば、そうでない場合もあります。受信者リストは、このメッセージのトピックのサブスクリプション・リストをオーバーライドします。受信者リスト機能は、JMSに対するOracleの拡張です。

TopicReceiver

受信者名が受信者リストに明示的に指定されていても、その受信者がキューのサブスクライバではない場合、その受信者に送信されるメッセージは、TopicReceiverを作成することによって受信できます。サブスクライバ名が指定されていない場合、クライアントがメッセージを受信するには、リモート・サイトで永続サブスクライバを使用する必要があります。TopicReceiverは、JMSに対するOracleの拡張です。

TopicReceiverは、messageSelectorを使用して作成できます。これによって、クライアントは、受信者に配信されるメッセージをセレクタにマッチするメッセージに制限できます。


関連項目:

「MessageSelector」

TopicBrowser

TopicBrowserを使用すると、クライアントはメッセージを削除しないでトピック上でメッセージを参照できます。このブラウズ用メソッドは、トピック・メッセージをスキャンするために使用されるjava.util.Enumerationを戻します。TopicBrowserを作成できるのは、永続サブスクライバのみです。nextElementに対する最初のコールが、トピックのスナップショットを取得します。

TopicBrowserは、メッセージをスキャン中にオプションでロックできます。これは、メッセージに対するSELECT...for UPDATEコマンドの場合と類似しています。これによって、他のコンシューマがスキャン中のメッセージを削除することはなくなります。

TopicBrowserは、messageSelectorを使用して作成できます。これによって、クライアントは、コンシューマに配信されるメッセージをセレクタにマッチするメッセージに制限できるようになります。


関連項目:

「MessageSelector」

TopicBrowserは、パージ機能をサポートしています。これによって、TopicBrowserを使用するクライアントは、トピックの現行のブラウズ操作中に参照されたすべてのメッセージを廃棄できます。パージとは、参照済のすべてのメッセージを破壊的に受信することと同じです(TopicSubscriberを使用して削除した場合と似ています)。

パージでは、メッセージがTopicBrowserjava.lang.EnumerationnextElement()操作へのコールを使用してクライアントに戻された場合、そのメッセージは参照済とみなされます。クライアントがまだ参照していないメッセージは、パージ中には廃棄されません。パージ操作は、同じTopicBrowserに対して何度も実行できます。

TopicBrowserの作成に使用したJMS Sessionがコミットされると、パージは正常に実行されます。セッションに対する操作がロールバックされた場合、パージ操作も取り消されます。

JMSパブリッシュ・サブスクライバ操作の設定

JMSでパブリッシュ・サブスクライブ・モデルの通信を使用する手順は、次のとおりです。

  1. メッセージを保持するために1つ以上のトピックを設定します。これらのトピックは、関心がある領域またはサブジェクトを表します。たとえば、トピックで請求済注文情報を表すことができます。

  2. AQjmsDestinationstartコールを使用して、トピックに対するエンキュー/デキューを有効にします。

  3. 永続サブスクライバのセットを作成します。各サブスクライバは、受信を希望するメッセージを選択するmessageSelectorを指定できます。NULLのmessageSelectorは、そのトピックに対してパブリッシュされたすべてのメッセージの受信をサブスクライバが希望していることを示します。

    サブスクライバはローカルでもリモートでもかまいません。ローカル・サブスクライバは、メッセージがパブリッシュされるトピックと同じトピックに対して定義された永続サブスクライバです。リモート・サブスクライバは、特定のキューのサブスクライバとして定義された別のトピックまたはそのトピックに対する受信者です。リモート・サブスクライバを使用するには、ソース・トピックと宛先トピック間の伝播を設定する必要があります。リモート・サブスクライバと伝播は、JMSに対するOracleの拡張です。


    関連項目:

    「伝播の管理」

  4. パブリッシャのSessioncreatePublisher()メソッドを使用してTopicPublisherオブジェクトを作成します。メッセージは、publishコールを使用してパブリッシュされます。メッセージは、トピックのすべてのサブスクライバ、またはトピックに対する指定された受信者のサブセットに対してパブリッシュできます。

  5. サブスクライバは、receiveメソッドを使用してトピックに関するメッセージを受信します。

  6. サブスクライバは、メッセージ・リスナーを使用して、非同期にメッセージを受信することもできます。

JMSメッセージ・プロデューサの機能

メッセージの優先順位および順序付け

メッセージの順序付けは、メッセージがキューまたはトピックから受信される順序を決定します。キューまたはトピックのキュー表の作成時に順序づけの方式が指定されます。現在は、Oracle Database Advanced Queuingでは、メッセージの優先順位とエンキュー時間に基づいた順序づけをサポートしており、これによって順序づけの方法が4種類あります。

  • First-In, First-Out(FIFO)

    エンキュー時刻が順序付け基準として選択されると、メッセージはエンキュー時刻の順序で受信されます。エンキュー時刻は、メッセージのパブリッシュ/送信時にOracle Database Advanced Queuingによってメッセージに割り当てられます。これはデフォルトの順序付けです。

  • 優先順位による順序付け

    優先順位による順序付けが選択されると、各メッセージに優先順位が割り当てられます。優先順位は、パブリッシュ/送信時にメッセージ・プロデューサによってメッセージ・プロパティとして指定できます。メッセージは、割り当てられた優先順位の順序で受信されます。

  • FIFO優先順位

    FIFO優先順位による順序付けが選択されると、トピックまたはキューは優先順位による順序付けの場合と同様に機能します。2つのメッセージに同じ優先順位が割り当てられた場合、両者はエンキュー時刻の順に受信されます。

  • エンキュー時刻に続く優先順位による順序付け

    同じエンキュー時刻のメッセージは、そのメッセージの優先順位に従って受信されます。2つのメッセージの順序付け基準が同じ場合、受信される順序は予想できません。ただし、1つのセッション中に特定の順序付け基準で生成されたメッセージは、送信された順序で受信されることがOracle Database Advanced Queuingにより保証されます。

メッセージ遅延の指定

メッセージをキュー/トピックに対して送信/パブリッシュするときに、遅延を指定できます。遅延は、そのメッセージがメッセージ・コンシューマに対して使用可能になるまでの時間を表します。遅延指定されたメッセージは、遅延の期限が切れるまで待機状態になります。遅延指定は、メッセージ識別子による受信でオーバーライドされます。

遅延は、JMSメッセージ・プロパティに対するOracle Database Advanced Queuingの拡張機能です。Oracle Database Advanced Queuingのバックグラウンド・プロセスのキュー・モニターが起動される必要があります。

メッセージ期限切れの指定

メッセージのプロデューサは、メッセージの期限切れまたはTimeToLiveを指定できます。これによって、そのメッセージがメッセージ・コンシューマに対して使用可能な期間が定義されます。

TimeToLiveは、送信/パブリッシュ時に指定するか、MessageProducerの設定済TimeToLiveメソッドを使用して指定することが可能で、前者が後者よりも優先されます。TimeToLiveを実装するには、Oracle Database Advanced Queuingのバックグラウンド・プロセスのキュー・モニターが実行されている必要があります。

メッセージのグループ化

1つのキューまたはトピックに属するメッセージをグループ化してセットを形成し、一度に1人のユーザーのみによって消費されるように設定できます。そのためには、トランザクション処理によるメッセージのグループ化が可能なキュー表にキューまたはトピックを作成する必要があります。同じグループに属するメッセージはすべて同じトランザクション内に作成する必要があり、同じトランザクション内に作成されたメッセージはすべて同じグループに属します。

メッセージのグループ化は、JMS仕様に対するOracle Database Advanced Queuingの拡張機能です。

この機能を使用すると、複雑なメッセージを、リンクされた一連の単純なメッセージに分割できます。たとえば、請求書キュー宛ての請求書は、ヘッダーのメッセージ、詳細情報の複数のメッセージ、フッターのメッセージの順に分割できます。

小さいオブジェクトに分割できるイメージやビデオなどの複合LOBがメッセージ・ペイロードにある場合は、メッセージのグループ化が非常に有効です。

グループに含まれるメッセージの優先順位、遅延および期限切れの各プロパティは、単にグループの最初のメッセージ(ヘッダー)のプロパティによってのみ判断されます。グループの他のメッセージのプロパティは無視されます。

メッセージ・グループは、伝播中も保持されます。宛先トピックは、トランザクション処理のグループ化に対して使用可能にしておく必要があります。


関連項目:

トランザクション処理でグループ化可能なキューからメッセージをデキューするときにメッセージ・グループを保持する場合、注意する必要がある制限については、「デキュー機能」を参照してください。

JMSメッセージ・コンシューマ機能

この項の内容は次のとおりです。

メッセージの受信

JMSアプリケーションは、メッセージ・コンシューマを作成することによって、メッセージを受信できます。メッセージは、receiveコールを使用して同期的に受信するか、メッセージ・リスナーを使用して非同期的に受信できます。

受信モードには次の3つがあります。

  • メッセージがコンシューマに届くまでブロック

  • 指定最大時間までブロック

  • 非ブロック

受信におけるメッセージのナビゲーション

コンシューマがナビゲーション・モードを指定しない場合、セッションの最初のreceiveはキューまたはトピックの最初のメッセージを取り出し、第2のreceiveは次のメッセージを取得します。優先順位が高いメッセージがコンシューマに届く場合、すでに届いているメッセージを削除するまで、コンシューマはこのメッセージを受信しません。

コンシューマが、メッセージに対してより効率的にキューのナビゲーションを制御できるように、Oracle Database Advanced QueuingにはJMS拡張機能として複数のナビゲーション・モードが用意されています。これらのモードは、TopicSubscriberQueueReceiverまたはTopicReceiverで設定できます。

グループ化されていないメッセージには、次の2つのモードを使用できます。

  • FIRST_MESSAGE

    このモードでは、位置がキューの先頭にリセットされます。コンシューマがキューの最上位にあるメッセージを削除できるため、優先順位に基づくキューで役立ちます。

  • NEXT_MESSAGE

    このモードは、コンシューマの確立された位置の後のメッセージを取得します。たとえば、4番目のメッセージの位置で適用されたNEXT_MESSAGEは、そのキューの5番目のメッセージを取得します。これはデフォルトのアクションです。

グループ化メッセージには、次の3つのモードを使用できます。

  • FIRST_MESSAGE

    このモードでは、位置がキューの先頭にリセットされます。

  • NEXT_MESSAGE

    このモードでは、位置が同一トランザクションの次のメッセージに設定されます。

  • NEXT_TRANSACTION

    このモードでは、位置が次のトランザクションの最初のメッセージに設定されます。


注意:

JMSシャード・キューは、前述の3つのモードをサポートしていません。

次の方法でメッセージが受信される場合、グループ化トランザクションのプロパティを無効にできます。

  • セレクタに相関識別子を指定して受信

  • セレクタにメッセージ識別子を指定して受信

  • トランザクション・グループのメッセージがすべて受信される前にコミット

NEXT_MESSAGEまたはNEXT_TRANSACTIONオプションの使用中にコンシューマがキューの最後に到達したとします。ブロッキングreceive()を指定していた場合は、ナビゲート位置は自動的にそのキューの先頭に変更されます。

デフォルトでは、QueueReceiverTopicReceiverまたはTopicSubscriberは、最初のreceiveコールにFIRST_MESSAGEを、以降のreceive()コールにNEXT_MESSAGEを使用します。

メッセージのブラウズ

デキューするクライアントがキューからメッセージを削除できる通常のreceiveの他に、JMSでは、JMSクライアントがキューで自身のメッセージをブラウズできるようにするインタフェースを提供しています。QueueBrowserは、QueueSessionからcreateBrowserメソッドを使用して作成できます。

メッセージが参照されると、そのメッセージは引き続き処理できます。メッセージがブラウズされた後は、同時セッションからreceiveコールがそのメッセージを削除する場合があるため、JMSセッションに引き続き使用できるとはかぎりません。

一度参照したメッセージが同時JMSクライアントによって削除されないようにするために、ロック・モードでメッセージを参照できます。そのためには、JMSインタフェースに対するOracle Database Advanced Queuingの拡張機能を使用して、ロック・モードを持つQueueBrowserを作成する必要があります。メッセージのロックは、セッションがコミットまたはロールバックを実行すると解放されます。

QueueBrowserによって参照されたメッセージを削除するには、セッションがQueueReceiverを作成し、JMSmesssageIDをセレクタとして使用する必要があります。

取出しを伴わないメッセージの削除

コンシューマは、receiveNoDataコールを使用してキューまたはトピックからメッセージを取得することなく、メッセージを削除できます。アプリケーションがQueueBrowserなどを使用してメッセージをすでに確認した場合に役立ちます。このモードを使用すると、JMSクライアントがペイロードをデータベースから取得するオーバーヘッドを回避できます(メッセージが大きい場合、オーバーヘッドが顕著である可能性があります)。

遅延間隔をおいた後の再試行

キュー/トピックからメッセージを受信するトランザクションが失敗した場合、そのメッセージを削除する試行に失敗したとみなされます。Oracle Database Advanced Queuingは、メッセージ削除の試行に失敗した回数をメッセージ履歴に記録します。

アプリケーションでは、メッセージに対する再試行の最大回数をキュー/トピック・レベルで指定できます。メッセージ削除がこの数より多く失敗した場合、メッセージは例外キューに移動されます。

Oracle Database Advanced Queuingでは、ユーザーはmax_retriesとともにretry_delayも指定できます。これは、受信の試行に失敗したメッセージを、retry_delay間隔後に引き続きキューで参照し、デキューできることを意味します。それまでこのメッセージはWAITING状態になります。Oracle Database Advanced Queuingのバックグラウンド・プロセスのタイム・マネージャは、再試行遅延プロパティを強制的に適用します。

再試行の最大回数および再試行の遅延は、キュー/トピックのプロパティです。このプロパティは、キュー/トピックの作成時、またはキュー/トピックに対する変更メソッドを使用して設定できます。MAX_RETRIESのデフォルト値は5です。


注意:

JMSシャード・キューは、再試行の遅延をサポートしていません。

MessageListenerを使用したメッセージの非同期受信

JMSクライアントは、setMessageListenerメソッドを使用してMessageListenerを設定することによって、メッセージを非同期的に受信できます。

コンシューマにメッセージが届いた場合、メッセージ・リスナーのonMessageメソッドがそのメッセージで起動されます。メッセージ・リスナーは、メッセージの受信をコミットまたは異常終了できます。メッセージ・リスナーは、JMS Connectionが停止されている場合、メッセージを受信しません。一度メッセージ・リスナーがコンシューマに対して設定されると、メッセージの受信にreceiveコールを使用することはできません。

JMSクライアントは、セッションでMessageListenerを設定することによって、そのセッションのすべてのコンシューマに対してメッセージを非同期的に受信できます。一度メッセージ・リスナーが設定されると、そのセッションでは、その他のメッセージ受信モードを使用できません。

例外キュー

例外キューは、期限切れまたは処理できないすべてのメッセージのリポジトリになります。アプリケーションから例外キューには直接エンキューできません。ただし、期限切れまたは処理できないメッセージを処理するアプリケーションは、例外キューからこれらのメッセージを受信または削除できます。

例外キューからメッセージを取り出すには、JMSクライアントはPoint-to-Pointインタフェースを使用する必要があります。トピック用のメッセージの例外キューは、使用可能な複数のコンシューマでキュー表に作成する必要があります。他のキューと同様に、例外キューもAQOracleQueueクラスでstartメソッドを使用して、メッセージを受信できる必要があります。例外キューをエンキュー可能に設定しようとすると、例外が発生します。


注意:

JMSシャード・キューは、例外キューをサポートしていません。

例外キューは、"JMS_OracleExcpQ"と呼ばれるOracle固有のメッセージ・プロパティで、メッセージの送信/パブリッシュ前に設定できます。例外キューが指定されていないと、デフォルトの例外キューが使用されます。デフォルトの例外キューはキュー表の作成時に自動的に作成され、AQ$_queue_table_name_Eと命名されます。

メッセージは、次の条件が成立するときに例外キューに移されます。

  • そのメッセージが、指定されたtimeToLive内にデキューされなかった場合。

    複数のサブスクライバを指定したメッセージの場合、指定されたtimeToLive内にそのメッセージをデキューできない受信者が1つ以上あると、メッセージは例外キューに移されます。

  • メッセージが正常に受信されたが、メッセージ処理中のエラーのためアプリケーションがreceiveを実行したトランザクションを異常終了した場合。そのメッセージはキュー/トピックに戻され、メッセージ受信のために待機中のどのアプリケーションでも使用可能になります。

    アプリケーションがトランザクション全体を異常終了するか、receive前のセーブポイントまでロールバックしたときは、receiveがロールバックまたはUNDOされたとみなされます。

    これは失敗したメッセージ受信の試行であるため、その再試行回数は更新されます。メッセージの再試行回数が、メッセージが常駐するキュー/トピックに指定された最大値を超える場合、そのメッセージは例外キューに移されます。

    メッセージが複数のサブスクライバを持つ場合、そのメッセージは、すべての受信者が再試行制限を超えたときにのみ、例外キューに移されます。


注意:

サーバー・プロセスがインスタンスで停止した(ALTER SYSTEM KILL SESSIONまたはSHUTDOWN ABORTなど)ためにデキュー・トランザクションが失敗した場合、RETRY_COUNTは増分されません。

JMS伝播

この項の内容は次のとおりです。


注意:

JMSシャード・キューは、RemoteSubscriber、伝播のスケジューリング、拡張伝播スケジュール機能および伝播中の例外処理をサポートしていません。

RemoteSubscriber

Oracle Database Advanced Queuingによって、他のデータベースにあるサブスクライバをトピックにサブスクライブできます。トピックに対してパブリッシュされたメッセージがリモート・サブスクライバの基準を満たしている場合は、リモート・サブスクライバに指定されているリモート・データベースにあるキュー/トピックに自動的に伝播します。伝播は、データベース・リンクおよびOracle Net Servicesを使用して実行されます。これによって、同じデータベースに接続しなくても、アプリケーション同士が互いに通信できます。

リモート・サブスクライバを実装するには、次の2つの方法があります。

  • createRemoteSubscriberメソッドは、トピック上またはトピックに対してリモート・サブスクライバを作成するために使用します。このリモート・サブスクライバは、クラスAQjmsAgentのインスタンスとして指定されます。

  • AQjmsAgentには、名前およびアドレスがあります。アドレスは、キュー/トピックおよびサブスクライバのデータベースへのデータベース・リンクで構成されています。

リモート・サブスクライバには、次の2種類があります。

  • リモート・サブスクライバがトピックである場合。

    これは、AQjmsAgentオブジェクトのリモート・サブスクライバに名前が指定されず、アドレスがトピックである場合に発生します。サブスクライバのサブスクリプションを満たすメッセージが、リモート・トピックに伝播されます。伝播されたメッセージは、それが満たすリモート・トピックのすべてのサブスクリプションに対して使用可能になります。

  • メッセージに対して特定のリモート受信者を指定する場合。

    リモート・サブスクリプションは、リモート・データベースにある特定のコンシューマに対して指定できます。リモート受信者の名前が(AQjmsAgentオブジェクトに)指定される場合、サブスクリプションを満たすメッセージが、その受信者専用のリモート・データベースに伝播されます。リモート・データベースにある受信者は、TopicReceiverインタフェースを使用してメッセージを取り出します。リモート・サブスクリプションは、Point-to-Pointキューに対して指定することもできます。

伝播スケジュール

伝播は、メッセージがターゲットの接続先データベースに伝播されるすべてのトピックについて、schedule_propagationメソッドを使用してスケジューリングされる必要があります。

スケジュールは時間の枠を示し、メッセージはその枠内でソース・トピックから伝播されます。この時間枠は、ネットワーク通信量、ソース・データベースの負荷、接続先データベースの負荷などの複数の要因に左右されます。したがって、スケジュールは特定のソースおよび宛先にあわせて調整する必要があります。スケジュールが作成されると、ジョブは自動的にjob_queue機能に発行され、伝播が処理されます。

伝播スケジュールのための運用管理コールによって、スケジュール管理を柔軟に行うことができます。あるスケジュールの存続時間または伝播枠パラメータによって、伝播が開始される時間枠が指定されます。存続時間が指定されない場合、時間枠は無制限の単一枠になります。枠を定期的に繰り返す必要がある場合、連続する枠の間の周期的間隔を定義するnext_time機能を使用して有限の存続時間を指定します。

あるキューに定義された伝播スケジュールは、そのキューの有効期間中いつでも変更または削除できます。さらに、(スケジュールを削除するかわりに)一時的に使用不可にするコール、および使用不可のスケジュールを使用可能にするコールがあります。メッセージがスケジュール内で伝播されているとき、そのスケジュールはアクティブです。すべての管理コールは、スケジュールがアクティブかどうかに関係なく実行されます。スケジュールがアクティブの場合、コールが実行されるまでに数秒かかります。

伝播が開始されるには、ジョブ・キュー・プロセスを起動する必要があります。少なくとも2つのジョブ・キュー・プロセスを起動する必要があります。接続先データベースへのデータベース・リンクも有効にする必要があります。伝播のソースおよび宛先トピックは、同じメッセージ型である必要があります。リモート・トピックは、エンキューできる必要があります。データベース・リンクのユーザーもリモート・トピックに対するエンキュー権限を持つ必要があります。

拡張伝播スケジュール機能

伝播のために定義されたカタログ・ビューは、アクティブ・スケジュールに関する次の情報を提供します。

  • そのスケジュールを処理しているバックグラウンド・プロセスの名前

  • 伝播を処理しているセッションのSID(セッションおよびシリアル番号)

  • スケジュールを処理しているインスタンス(Oracle RACを使用している場合)

  • 先行して正常に実行されたスケジュール

  • 次に実行予定のスケジュール

スケジュールごとに次の伝播統計が保持され、キュー管理者がスケジュール調整に役立てることができます。

  • スケジュールの中で伝播されたメッセージ合計数

  • スケジュールの中で伝播されたバイト合計数

  • 伝播枠の中で伝播されたメッセージの最大数

  • 伝播枠の中で伝播されたバイトの最大値

  • 伝播枠の中で伝播されたメッセージの平均数

  • 伝播済メッセージの平均サイズ

  • 伝播済メッセージの平均時間

伝播機能には、障害対処およびエラー・レポートが組み込まれています。たとえば、指定されたデータベース・リンクが無効な場合、リモート・データベースが使用できない場合、またはリモート・トピック/キューにエンキューできない場合、適切なエラー・メッセージがレポートされます。伝播は指数バックオフ・スキームを使用して、障害が発生したスケジュールからの伝播を再試行します。あるスケジュールで続けて障害が発生したときは、最初の再試行は30秒後、次の再試行は60秒後、3回目の再試行は120秒後、というように続きます。再試行時間が現行の伝播枠の期限切れ時刻を超える場合は、次の再試行は、次の伝播枠の開始時刻に行われます。最大16回の再試行が行われた後、そのスケジュールは自動的に使用不可能になります。


注意:

再試行が次の伝播ウィンドウに移動されると、常に移動されるようになり、指数バックオフ・スキームは再試行のスケジュールを管理しません。DBMS_AQADM.SCHEDULE_PROPAGATION()next_timeパラメータで指定された日付関数の結果、ウィンドウ間の間隔が短くなると、再試行の失敗数はすぐに16に達し、スケジュールが無効になります。

障害のためにスケジュールが自動的に使用不可になると、関連情報がアラート・ログに書き込まれます。スケジュールで失敗が発生したか、その場合は何回連続して失敗が発生したか、失敗の原因を示すエラー・メッセージ、および最後の失敗が発生した時刻を、いつでも確認できます。この情報を調べることで、管理者は障害を回復し、スケジュールを使用可能にできます。

再試行の間に伝播が成功したときは、障害の数は0(ゼロ)にリセットされます。

伝播機能にはOracle Real Application Clustersサポートが組み込まれていますが、ユーザーおよび管理者には透過的です。伝播を処理するジョブは、ソース・トピックが常駐しているキュー表の所有者と同じインスタンスに送られます。あるインスタンスに障害が発生してトピックを保存しているキュー表が他のインスタンスに移される場合は、伝播ジョブも必ず自動的に新しいインスタンスに移行されます。これによって、インスタンス間のping操作は最小限に抑えられ、パフォーマンスが向上します。伝播は、同時スケジュールをいくつでも処理できるように設計されています。

job_queue_processesの最大数は1000で、その一部は伝播に関連しないジョブの処理に使用できます。このために、伝播にはマルチタスキングおよびロード・バランシングのサポートが組み込まれています。伝播アルゴリズムは、複数スケジュールが単一スナップショット(job_queue)のプロセスによって処理できるように設計されています。job_queueプロセスに対する伝播の負荷は、異なるソース・トピックからのメッセージ到着の割合に基づいて偏りが発生する場合があります。あるプロセスが数個のアクティブ・スケジュールによって過負荷になっている一方で、別のプロセスは受動的なスケジュールが多いために余力があるというとき、伝播はプロセス間で負荷が均等になるようにスケジュールを自動的に再分配します。

伝播中の例外処理

ネットワーク障害のようなシステム・エラーが発生した場合、Oracle Database Advanced Queuingは指数バックオフ・アルゴリズムを使用してメッセージを伝播する試みを継続します。キューからデータベース・リンクへの伝播中のアプリケーション・エラーを示している状況では、Oracle Database Advanced QueuingはそのメッセージにUNDELIVERABLEというマークを付けてalert.logに記録します。このようなエラーは、リモート・キューが存在しない場合、またはソース・キューおよびリモート・キューの型が一致しない場合に発生します。background_dump_destディレクトリのトレース・ファイルには、そのエラーに関する追加情報があります。

新規のジョブ・キュー・プロセスが開始すると、型を再検証できるように型の不一致エラーを消去します。ジョブ・キュー・プロセス数に上限を設定して、伝播のビジー状態が続く場合、ジョブ・キュー・プロセスが終了して再開するまで待つ必要はありません。キューの型は、必要に応じてDBMS_AQADM.VERIFY_QUEUE_TYPESを使用して再検証できます。


注意:

キューからキューへの伝播中に型の不一致が検出されると、伝播は停止してエラーが発生します。このような場合は、DBA_SCHEDULESビューを問い合せて、特定の宛先への伝播中に発生した最後のエラーを判断する必要があります。このメッセージには、UNDELIVERABLEマークは付いていません。

JMS AQのメッセージ変換

あるフォーマットのメッセージを別のフォーマットのメッセージにマップするために変換を定義できます。変換は、同一の情報を異なるフォーマットで表現するアプリケーションを統合する必要がある場合に有効です。変換はSQL式およびPL/SQLファンクションです。メッセージ変換は、標準JMSインタフェースに対するOracle Database Advanced Queuingの拡張機能です。

変換は、DBMS_TRANSFORM.create_transformationプロシージャを使用して作成できます。変換は、次の操作を行う場合に指定できます。

  • キューまたはトピックへのメッセージの送信

  • キューまたはトピックからのメッセージの受信。

  • TopicSubscriberの作成

  • RemoteSubscriberの作成。これによって、異なるフォーマットのトピック間でメッセージを伝播できます。


注意:

JMSシャード・キューは、メッセージ変換をサポートしていません。

JMSシャード・キュー

Oracle Database 12cリリース1 (12.1)にはJMSシャード・キューが導入されており、最適化されたデータベース・キューイング実装を含むJMS機能が提供されています。JMSシャード・キューは、次のような場合に、Oracle Advanced Queuingの優先JMS構成です。

  • 複数のOracle RACインスタンスにエンキュー元またはデキュー元のあるJMSキュー

  • スループットの高いJMSキュー

  • 大量のシステム・リソースを消費する非シャードJMSキュー

  • 多数のサブスクライバを持つJMSキュー

シャード・キューは、システムで管理されているパーティション化を使用して、独立した複数の物理キューに透過的に分割される1つの論理キューです。シャード・キューにより、異なるキュー・シャードにある2つのメッセージ間の順序付けがベスト・エフォートで実行されるため、エンキューおよびデキューのスループットが、特にOracle RACインスタンスで向上します。各シャードは、セッション内のエンキュー時刻に基づいて順序付けされます。シャード・キューは、エンキュー元およびデキュー元がそれら同士で競合しないように、表のパーティションを自動的に管理します。また、シャード・キューは、インメモリーのメッセージ・キャッシュを使用して、パフォーマンスを最適化し、AQ-JMSのエンキューおよびデキューのディスクおよびCPUのオーバーヘッドを削減します。

この項の内容は次のとおりです。

JMSシャード・キューおよびメッセージ・キャッシュ

シャード・キューは、専用のメッセージ・キャッシュを導入しており、これを使用すると、SGAの使用量をトレードオフでき、スループットの向上、待ち時間の削減、同時処理の向上を図れます。パーティション化と組み合せると、メッセージ・キャッシュで、一部の問合せ、DML操作および索引に対する必要性が低くなります。メッセージ・キャッシュは、デキュー元の処理がエンキュー元に追いついている場合、およびメッセージ・キャッシュが、各シャード・キューのエンキュー元およびデキュー元に対して、メッセージ(ペイロードを含む)を十分に格納できる大きさである場合に最も効果的です。メッセージ・キャッシュでは、Streamsプールが使用されます。JMSシャード・キューが、Streamsのレプリケーション機能と同じインスタンスでStreamsプールを共有する場合、SET_MIN_STREAMS_POOLおよびSET_MAX_STREAMS_POOLなどのDBMS_AQADMプロシージャを使用して、Streamsプールのメモリー割当てを微調整できます。


関連項目:

詳細は、『Oracle Database PL/SQLパッケージ・プロシージャおよびタイプ・リファレンス』を参照してください。

JMSシャード・キューおよびエンキュー/デキュー・メッセージ

スループットを向上させ、オーバーヘッドおよび待ち時間を削減するために、エンキューおよびデキューは、メッセージ・キャッシュ、ルール・エンジン、および可能な場合はバックグラウンド処理を使用するように最適化されています。次に例を示します。

  • シャード・キューは、新しいルール・エンジンの改善点を利用します。

  • メッセージ・キャッシュ内にペイロードのあるメッセージは、デキュー中にディスクから再読取りする必要がありません。

  • 相関IDによるデキューまたはその他のJMSプロパティは、ディスクにアクセスすることなく頻繁に評価できます。

  • シャード・キューにおけるパーティション操作により、効率的な一括処理が実装されます。

JMSシャード・キューおよびネイティブJMSサポート

JMSシャード・キューは、次のネイティブ・サポートを有しています。

  • 非永続サブスクライバ

  • JMSペイロード

  • 優先順位

JMSシャード・キューでは、永続メッセージと非永続メッセージの両方がサポートされます。非永続メッセージはメッセージ・キャッシュ内のメモリーに格納され、ディスクには格納されません。そのため、非永続メッセージは、インスタンスのクラッシュ時や停止時に失われます。

JMSシャード・キューは、JMS要件を満たす2種類のサブスクライバをネイティブにサポートしています。

  • 非永続サブスクライバ: これらのサブスクライバは、サブスクライバがアクティブ中にメッセージがパブリッシュされた場合のみ、選択されたトピックについてのメッセージを受信します。このサブスクリプションは、異なるセッション間で共有できません。

  • 永続サブスクライバ: これらのサブスクライバは、サブスクライバが非アクティブ中にパブリッシュされたメッセージを含めて、トピックについてパブリッシュされたすべてのメッセージを受信します。複数のデータベース・セッションで、同じサブスクリプションを共有できます。

JMSシャード・キューは、ADTを使用してJMSペイロードを格納しません。JMSメッセージは、データベースのスカラー列に格納されます。TEXTBYTESMAPSTREAMOBJECTなどのJMSメッセージ・タイプは、ペイロードのサイズとタイプに応じて、キュー表のTEXT/RAWまたはCLOB/BLOBのスカラー列にJMSペイロードを格納します。JMSメッセージ・プロパティは、ユーザー定義プロパティに属性アクセス機能が定義されているキュー表のCLOB (SecureFile)列に格納されます。ペイロードおよびユーザー・プロパティは、ADTとして格納されずに、RAWVARCHAR2または保護ファイル列に格納されます。JMSヘッダー・プロパティおよびJMSプロバイダ情報は、それ自体のスカラー列に格納されます。

JMSシャード・キューでは、0 (最も低い優先度)から9 (最も高い優先度)の範囲で整数の優先順位の値がサポートされており、JMS標準で定義されているように、デフォルトは4です。

JMSシャード・キューおよびパーティション化

JMSシャード・キューは、キュー表に使用される、基礎となるパーティション化された表を自動的に管理します。このようなパーティション管理は、フォアグラウンドまたはバックグラウンドで実行されます。各シャードは、エンキューされたメッセージのセッションレベルの順序付けを提供します。各エンキュー・セッションにはシャードが割り当てられます。各シャードは、一連のサブシャードで構成されます。各サブシャードは、1つのパーティションにマップされます。JMSメッセージは、エンキュー時に表パーティションに自動的に割り当てられます。

新しいパーティションは、デキュー元がエンキュー元の処理に追いついておらず、キュー表を大きくする必要がある場合など、必要に応じて自動的に作成されます。パーティション内のすべてのメッセージがデキューされて必要がなくなった場合、パーティションは切り捨てられ再利用されます。メッセージ・キャッシュは、デキュー元による要求に応じて、メッセージをパーティションからメモリーに自動的にロードします。グローバル索引は、JMSシャード・キューの基礎となる、パーティション化された表に作成できません。ローカル索引も、パーティション化された表では通常推奨されません。これらの索引が必要であるがパフォーマンスが低下する場合は、非シャード・キューの使用を検討してください。

JMSシャード・キューおよびOracle Real Application Clusters (Oracle RAC)

JMSシャード・キューは、可能な場合にはインスタンス間通信を回避しながら、自動的にエンキュー・セッションの順序付けを行います。インスタンス間通信が必要な場合もあります。たとえば、JMSシャード・キューで、1つのOracleインスタンス上に単一のエンキュー・セッションがあり、別のインスタンスに単一のデキュー・セッションがある場合、JMSシャード・キューはOracle RACインスタンス間でメッセージを転送します。パフォーマンスを向上させるため、メッセージの転送は、エンキュー・トランザクションに対してアトミックではありません。シャードにメッセージがないインスタンスに接続している場合、デキュー元でORA-25228が発生する場合があります。

ほとんどの場合、スループットを改善し、インスタンス間のオーバーヘッドを削減するために、各サブスクライバに対し複数のデキュー元を持つか、各Oracle RACインスタンスに単一のコンシューマ・キューを持つことを検討します。単一メッセージを指定するデキュー・セレクタを使用している場合は例外です。Oracle RACデータベースのメッセージ識別子により、共有キューからメッセージをデキューする場合、メッセージを含む共有キューのデキュー所有権を割り当てられたインスタンスに接続する必要があります。そうしないと、メッセージはデキュー・セッションへのデキューで使用できません。すべてのデキューが単一インスタンスで実行される場合、メッセージはこのインスタンスに自動的に転送されます。そのため、メッセージIDで広くデキューする共有単一コンシューマ・キューの場合は、共有キューのすべてのデキュー・セッションが単一インスタンスに接続することを検討してください。同様に、メッセージIDで広くデキューする共有複数コンシューマ・キューの場合は、各サブスクライバのすべてのデキュー・セッションが単一インスタンスに接続することを検討してください。サービスを使用してデキュー・セッションの特定のインスタンスへの接続を簡略化することができます。

JMSシャード・キューの制限事項

現在、JMSシャード・キューでは、次のOracle Database Advanced Queuingの機能はサポートされていません。

  • メッセージの保存

  • メッセージの遅延

  • グループ化トランザクション

  • 配列のエンキュー

  • 配列のデキュー

  • メッセージのエクスポートおよびインポート

  • サブスクライバの通知の転送

  • メッセージ・ゲートウェイ

  • 例外キュー

  • JMS以外のエンキューまたはデキュー。たとえば、PL/SQLおよびOCIのエンキューとデキューは、JMSシャード・キューではサポートされていません

  • JMS伝播およびリモート・サブスクライバなど、JMSのOracle拡張機能

  • 1つのキュー表に複数のキュー。シャード・キューは、CREATE_SHARDED_QUEUEインタフェースを介して作成されます。

  • JMS標準で指定されているメッセージ優先順位、エンキュー時刻の順以外の順序付け。

  • JDBC thick (OCI)ドライバ。

JMSシャード・キューのチューニング

JMSシャード・キューのパフォーマンスが最大になるのは次の場合です。

  • 各サブスクライバのデキュー元が各インスタンス内にあります。

  • サブスクライバがエンキュー元の速度に追いついています。各Oracle RACインスタンス上の各サブスクライバに対して複数のデキュー元を設定することを検討してください。

メッセージ・キャッシュは、デキュー元の処理がエンキュー元に追いついている場合、およびキャッシュが、各JMSシャード・キューのエンキュー元およびデキュー元に対して、メッセージ(ペイロードを含む)を十分に格納できる大きさである場合に最も効果的です。JMSシャード・キューを使用する場合、次のいずれかを行う必要があります。

  • パラメータSTREAMS_POOL_SIZEの設定

    このパラメータは、Oracle DatabaseでJMSシャード・キュー・メッセージ・キャッシュに使用可能な共有メモリーのサイズを制御します。指定されていない場合は、共有プール・サイズの最大10%までがStreamsプールに割り当てられます。

    SGA_TARGET初期化パラメータに0以外の値を設定すると、Oracleの自動共有メモリー管理機能によってStreamsプールのサイズが管理されます。STREAMS_POOL_SIZE初期化パラメータにも0以外の値を設定した場合、この値は、Streamsプールの最小値として自動共有メモリー管理によって使用されます。

    STREAMS_POOL_SIZE初期化パラメータが0以外の値に設定され、SGA_TARGETパラメータが0に設定されている場合、StreamsプールのサイズはSTREAMS_POOL_SIZEパラメータで指定される値(バイト単位)になります。

    STREAMS_POOL_SIZESGA_TARGETの初期化パラメータがどちらも0に設定されている場合は、デフォルトにより、データベースで最初にStreamsプールを使用したときに、バッファ・キャッシュから共有プールの10%に相当する容量のメモリーがStreamsプールに割り当てられます。


    関連項目:

    • Streams処理を使用したSTREAMS_POOL共有の詳細な制御は、『Oracle Database PL/SQLパッケージ・プロシージャおよびタイプ・リファレンス』DBMS_AQADM.set_min_streams_pool()およびDBMS_AQADM.set_max_streams_pool( )に関する項を参照してください。


  • SGA自動チューニングの有効化

    Streamsプールの使用量およびSGAを使用するその他のコンポーネントの使用量に基づいて、SGAからStreamsプールに適切な量のメモリーが自動的に割り当てられます。その他のコンポーネントには、バッファ・キャッシュ、ライブラリ・キャッシュなどがあります。STREAMS_POOL_SIZEを指定した場合は、下限として使用されます。

JMSストリーミング

AQ JMSは、大量のメッセージ・データまたはペイロードを送受信するアプリケーション用に、AQjmsBytesMessageおよびAQjmsStreamMessageを介した共有キューのエンキューおよびデキューでのストリーミングをサポートするようになりました。

JMSストリーミングは、大きい連続したバイトの配列を送受信するのではなく、メッセージ・ペイロードを小さいチャンクに分割することにより、大きいメッセージを扱うときのメモリー要件を緩和します。JMS標準にストリーミング・メカニズムは含まれないため、AQ JMSはAQストリーミング・エンキューおよびデキュー機能を示すための固有のインタフェースを提供します。これにより、ユーザーは既存のjava入出力ストリームを使用してメッセージ・データまたはペイロードを簡単に送受信できます。

データベースのRDBMS 12.1.0.2へのアップグレード時に既存のアプリケーションが変更なしで動作できるように、デフォルトではストリーミングAPIは無効化されます。

クライアント・アプリケーションはシステム・プロパティoracle.jms.useJmsStreamingtrueに設定して使用することにより、JMSストリーミングを有効化できます。


注意:

JMSストリーミングはThinドライバの場合のみサポートされます。

エンキューでのJMSストリーミング

AQ JMSではAQjmsBytesMessageおよびAQjmsStreamMessageの新しいAPI setInputStream(java.io.InputStream)が提供され、メッセージ・データ用の入力ストリームを設定します。

    /**
     * @param inputStream - InputStream to read the message payload
     * @throws JMSException - if the JMS provided fails to read the payload due to
     *                        some internal error
     */
    public void setInputStream(InputStream inputStream) throws JMSException

次のコード・スニペットでは、AQjmsBytesMessageタイプのメッセージが作成され、メッセージ・データ用のFileInputStreamが設定されます。

    Session session = connection.createSession(false, Session.CLIENT_ACKNOWLEDGE);
    Destination destination = session.createQueue("queueName");
    MessageProducer producer = session.createProducer(destination);
 
     AQjmsBytesMessage bytesMessage = (AQjmsBytesMessage)session.createBytesMessage();
     InputStream input = new FileInputStream("somefile.data");
     bytesMessage.setInputStream(input);
     producer.send(bytesMessage);

注意:

  • BytesMessageおよびStreamMessageのメソッドはjava.io.DataInputStreamおよびjava.io.DataOutputStreamで検出されるメソッドに基づいているため、様々なread*()およびwrite*()メソッドの意味のある変換はストリームでは不可能です。次の使用例では例外が発生します。

    • bytesMessage.setInputStream(input);

      bytesMessage.writeInt(99);

    • bytesMessage.writeInt(99);

      bytesMessage.setInputStream(input);

  • 通常のエンキュー操作と同様に、ストリーミングを使用したエンキューは同期操作となり、エンキューが完了した後でのみ、制御がクライアントに戻されます。

  • これらのAPIが明示的にクライアントにより使用される場合にのみ、ストリーミングがエンキューで使用されます。AQ JMSはメッセージ・データのサイズと関係なく、通常のエンキューではストリーミングを使用しません。


デキューでのJMSストリーミング

ストリーミングを使用したデキュー操作は、2つの手順で実行されます。サーバーでは、メッセージ本文のサイズに基づき、メッセージ本文をストリーミングするかどうかが決定されます。デフォルトのしきい値制限は10MBです。そのため、メッセージ本文が10MBよりも大きく、システム・プロパティoracle.jms.useJmsStreamingを使用して、ストリーミングがクライアントで有効な場合、サーバーはデキューでストリーミングを使用します。

  1. これはクライアントがreceive()メソッドを呼び出す場合の通常のデキュー・プロセスです。

    Destination destination = session.createQueue ("queueName");             
    AQjmsConsumer consumer = (AQjmsConsumer) session.createConsumer(destination);             
    Message message = consumer.receive(10000);
    
  2. クライアントがペイロードなしのメッセージを受信する場合、クライアントは受信メッセージでのisLargeBody()の呼び出しにより、ストリーミングがデキューで使用されるかどうかを特定します。

      /**
       * This method can be used by the client applications to check whether the message
       * contains large messaege body and hence requires streaming with dequeue.
       * 
       * @return true when the message body is large and server decides to stream
       *         the payload with dequeue
       */
      public boolean isLargeBody() 
    

    isLargeBody()により戻されたtrueの値は、デキューでのストリーミングを示します。デキューでストリーミングを使用する場合、AQ JMSはAQjmsStreamMessageAQjmsBytesMessageに対して正確にメッセージ本文の長さを移入します。そのため、クライアント・アプリケーションはメッセージでgetBodyLength()を呼び出し、ペイロードのサイズを判断することができます。

     public long getBodyLength()
    

クライアントがデキューでのストリーミングについて理解したら、受信メッセージで次のAPIのいずれかを使用してメッセージ・データをフェッチできます。

クライアント・アプリケーションは、AQjmsBytesMessageおよびAQjmsStreamMessageで使用可能な次のAPIを使用して、メッセージ・データを受信できます。

 /**
     * Writes the message body to the OutputStream specified.
     * 
     * @param outputStream - the OutputStream to which message body can be written
     * @return the OutputStream containing the message body.
     * @throws JMSException - if the JMS provided fails to receive the message body 
     *                        due to some internal error
     */
    public OutputStream getBody(OutputStream outputStream) throws JMSException
 
    /**
     * Writes the message body to the OutputStream specified, with chunkSize bytes 
     * written at a time.
     * 
     * @param outputStream - the OutputStream to which message body can be written
     * @param chunkSize - the number of bytes to be written at a time, default value 
     *                    8192 (ie. 8KB)
     * @return the OutputStream containing the message body.
     * @throws JMSException - if the JMS provided fails to receive the message body 
     *                        due to some internal error
     */
    public OutputStream getBody(OutputStream outputStream, int chunkSize)throws JMSException
    
 
    /**
     * Writes the message body to the OutputStream specified. This method waits until 
     * the message body is written completely to the OutputStream or the timeout expires.
     * 
     * A timeout of zero never expires, and a timeout of negative value is ignored.
     * 
     * @param outputStream - the OutputStream to which message body can be written
     * @param timeout - the timeout value (in milliseconds)
     * @return the OutputStream containing the message body.
     * @throws JMSException - if the JMS provided fails to receive the message body 
     *                        due to some internal error
     */   
    public OutputStream getBody(OutputStream outputStream, long timeout) throws JMSException 
 
 
    /**
     * Writes the message body to the OutputStream specified, chunkSize bytes at a time. 
     * This method waits until the message body is written completely to the OutputStream
     * or the timeout expires.
     * 
     * A timeout of zero never expires, and a timeout of negative value is ignored.
     * 
     * @param outputStream - the OutputStream to which message body can be written
     * @param chunkSize - the number of bytes to be written at a time, 
     *                    default value 8192 (ie. 8KB)
     * @param timeout - the timeout value (in milliseconds)
     * @return the OutputStream containing the message body.
     * @throws JMSException - if the JMS provided fails to receive the message body 
     *                        due to some internal error
     */   
    public OutputStream getBody(OutputStream outputStream, int chunkSize, long timeout) throws JMSException

次のコード・スニペットは、ストリーミングがデキューで使用され、受信したペイロードがFileOutputStreamに書き込まれるかどうかをチェックします。

     if (message instanceof BytesMessage && (AQjmsBytesMessage)message.isLargeBody()){
         // optional : check the size of the payload and take appropriate action before 
         // receiving the payload.
          (AQjmsBytesMessage) message.getBody(new FileOutputStream(new File("…")));
     } else {
          // normal dequeue
     }

通常、両方の手順が完了すると、メッセージは完全に消費されたとみなされます。AQサーバーにより、手順1の後でメッセージでのロックは保持され、手順2の後でのみ解除されます。

メッセージ・コンシューマによりメッセージが部分的に消費されることにより発生する可能性のある問題を考慮して、確認モードCLIENT_ACKNOWLEDGEおよびSESSION_TRANSACTEDでのセッション用のストリーミングAPIは制限されました。

そのため、部分的に消費されたメッセージを含む、すべてのメッセージは、次の時点で完全に消費されたとみなされます。

  • message.acknowledge()CLIENT_ACKNOWLEDGEセッションで呼び出されます。

  • セッションのcommit()はトランザクション・セッションで呼び出されます。

通常の場合、セッションrollback()は、そのセッションで受信したメッセージをロールバックします。

JMSストリーミングは使用可能ですが、次の制限があります。

  • ストリーミングはデフォルトで無効化されており、システム・プロパティoracle.jms.useJmsStreamingを使用してクライアント・アプリケーションにより有効化できる

  • メッセージ・データのサイズがしきい値よりも大きい場合に、デキューでストリーミングが使用されます。デフォルトのしきい値は10MBです。

  • ストリーミング・サポートはAQjmsBytesMessageおよびAQjmsStreamMessageで使用可能

  • ストリーミング・サポートは共有キューでのみ使用可能

  • ストリーミング・サポートはThinドライバでのみ使用可能

  • ストリーミング・サポートは、メッセージ・プロデューサがメッセージ配信モードにNON_PERSISTENTを使用しているときは使用できない

  • ストリーミングはメッセージ・リスナーではサポートされません。そのため、MessageConsumerにメッセージ・リスナー・セットがある場合、およびメッセージ・データがしきい値制限を超えている場合は、内部的に通常のデキューが使用されます。

  • ストリーミング・サポートは、確認モードCLIENT_ACKNOWLEDGEおよびSESSION_TRANSACTEDを使用してセッションで使用可能です。

Java EEコンプライアンス

Oracle Database 12cリリース1 (12.1)では、Oracle JMSはオラクル社のSun JMS 1.1標準に準拠しています。実行時に、Oracle Java Message Service (Oracle JMS)クライアントに対してJava EE準拠モードを定義できます。準拠モードにするには、コマンドライン・オプションとしてJavaプロパティ oracle.jms.j2eeCompliantTRUEに設定します。非準拠モードにする場合は何もしません。FALSEがデフォルト値です。

Java EE準拠をサポートし、非準拠モードでも使用できるOracle Database Advanced Queuingの機能は次のとおりです。

  • 非トランザクション・セッション

  • 永続サブスクライバ

  • 一時キューおよびトピック

  • 非永続配信モード

  • AQ$_JMS_MESSAGE型のOracle Database Advanced Queuingキューを使用した単一のJMSキューまたはトピックに対する複数のJMSメッセージ・タイプ

  • 永続サブスクライバに対するnoLocalオプション

  • JMSシャード・キューはJMSでネイティブにサポートされており、Java EEコンプライアンスに準拠しています


関連項目

  • 『Java Message Service Specification』、バージョン1.1、2002年3月18日、Sun Microsystems, Inc.

  • JMSPriorityおよびJMSExpirationに対するJavaプロパティoracle.jms.j2eeCompliantの影響の詳細は、「JMSメッセージ・ヘッダー」を参照してください。

  • 永続サブスクライバに対するJavaプロパティoracle.jms.j2eeCompliantの影響の詳細は、「DurableSubscriber」を参照してください。