この章では、Oracle Database Advanced Queuing (AQ)へのOracle Java Message Service (JMS)インタフェースについて説明します。
内容は次のとおりです。
この項の内容は次のとおりです。
この項の内容は次のとおりです。
ConnectionFactory
は、管理者によって定義された接続構成パラメータの集合をカプセル化します。クライアントはこれを使用してJMSプロバイダとの接続を確立します。この場合、Oracle Databaseの一部であるOracle JMSがJMSプロバイダです。
ConnectionFactory
オブジェクトには、次の3種類があります。
ConnectionFactory
QueueConnectionFactory
TopicConnectionFactory
AQjmsFactory
クラスを使用して、ConnectionFactory
、QueueConnectionFactory
またはTopicConnectionFactory
オブジェクトに対するハンドルを取得できます。
Point-to-Point操作とパブリッシュ・サブスクライブ操作の両方をサポートしているConnectionFactory
を取得するには、AQjmsFactory.getConnectionFactory()
を使用します。QueueConnectionFactory
を取得するには、AQjmsFactory.getQueueConnectionFactory()
を使用します。TopicConnectionFactory
を取得するには、AQjmsFactory.getTopicConnectionFactory()
を使用します。
ConnectionFactory
、QueueConnectionFactory
またはTopicConnectionFactory
は、ホスト名、ポート番号、SIDドライバまたはJDBC URLおよびプロパティを使用して作成できます。
JMS管理者は、Lightweight Directory Access Protocol(LDAP)サーバーにConnectionFactory
オブジェクトを登録できます。JMSでJava Naming and Directory Interface(JNDI)の検索を使用可能にするには、次の設定が必要です。
データベースの登録
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エントリの構造
パラメータGLOBAL_TOPIC_ENABLED
を設定します。
データベースのGLOBAL_TOPIC_ENABLED
システム・パラメータをTRUE
に設定する必要があります。これによって、Oracle Database Advanced Queuingで作成されたすべてのキューおよびトピックが自動的にLDAPサーバーに登録されます。このパラメータは、ALTER SYSTEM SET GLOBAL_TOPIC_ENABLED = TRUE
を使用して設定できます。
ConnectionFactory
オブジェクトの登録
データベースを設定してLDAPサーバーが使用できるようになると、JMS管理者はAQjmsFactory.registerConnectionFactory()
を使用して、LDAPにConnectionFactory
、QueueConnectionFactory
および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プロバイダとのオープン・コネクションまたはコネクション・プールのいずれかをカプセル化します。
クライアントとプロバイダのサービス・デーモン間のオープンな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()
このメソッドは、このConnection
のExceptionListener
を取得します。
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 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仕様では、開始されていないJMSConnection インスタンスで受信が完了したとき、プロバイダによりNULLメッセージが返されることを要求します。
|
Destination
は、クライアントがメッセージの送信先および受信元の指定に使用するオブジェクトです。Destination
オブジェクトはQueue
またはTopic
に指定できます。Oracle Database Advanced Queuingでは、特定のデータベースのschema.queue
にマップされます。Queue
は単一コンシューマ・キューに、Topic
はマルチ・コンシューマ・キューにマップします。
Destination
オブジェクトは、Session
オブジェクトからドメイン固有の次のSession
メソッドを使用して作成されます。
AQjmsSession.getQueue(queue_owner, queue_name)
このメソッドはJMSキューに対するハンドルを取得します。
AQjmsSession.getTopic(topic_owner, topic_name)
このメソッドはJMSトピックに対するハンドルを取得します。
LDAPサーバーにスキーマ・オブジェクトを登録するようにデータベースを設定できます。データベースがLDAPを使用できるように設定され、GLOBAL_TOPIC_ENABLEDパラメータがTRUEに設定されている場合、すべてのJMSキューおよびトピックは、作成時に自動的にLDAPサーバーに登録されます。また、管理者は、LDAPに登録されているキューおよびトピックの別名を作成することもできます。LDAPに登録されているキューおよびトピックは、キュー/トピック名またはその別名を使用してJNDIを介して検索できます。
Destination
オブジェクトのメソッドには、次のものが含まれます。
alter()
このメソッドはキュー
またはトピック
を変更します。
schedulePropagation()
このメソッドは、ソースから宛先への伝播をスケジューリングします。
unschedulePropagation()
このメソッドは、スケジュール済伝播のスケジュールを解除します。
enablePropagationSchedule()
このメソッドは、伝播スケジュールを有効化します。
disablePropagationSchedule()
このメソッドは、伝播スケジュールを無効化します。
start()
このメソッドはキュー
またはトピック
を開始します。キューは、エンキューまたはデキューを可能にするために開始されます。トピックは、パブリッシュまたはサブスクライブを可能にするために開始できます。
stop()
このメソッドはキュー
またはトピック
を停止します。キューは、エンキューまたはデキューを実行不可にするために停止できます。トピックは、パブリッシュまたはサブスクライブを実行不可にするために停止できます。
drop()
このメソッドはキュー
またはトピック
を削除します。
Oracle8i以上では、すべてのキューイング操作に対してシステム・レベルのアクセス制御をサポートします。この機能によって、アプリケーション設計者またはDBAは、ユーザーをキュー管理者にできます。キュー管理者は、データベースのどのキューに対してもJMSインタフェース(管理および操作)を起動できます。これによって、データベース上のキュー全体に対するすべての管理スクリプトを1つのスキーマで管理できるため、管理作業が容易になります。
メッセージが宛先キューに届くと、ソース・キューのスキーマ名に基づいたセッションによって、新しく届いたメッセージが宛先キューにエンキューされます。つまり、ソース・キューのスキーマに宛先キューに対するエンキュー権限を付与する必要があります。
リモートの宛先キューに伝播するために、エージェント構造体のアドレス・フィールドのデータベース・リンクに指定されたログイン・ユーザーには、ENQUEUE_ANY
権限を付与するか、または宛先キューに対するエンキュー権限を付与する必要があります。ただし、データベース・リンクのログイン・ユーザーが宛先のキュー表を所有している場合はどのような明示的な権限も付与する必要はありません。
Oracle8i以上では、エンキューおよびデキュー操作に対してキュー・レベルまたはトピック・レベルのアクセス制御をサポートしています。この機能によって、アプリケーション設計者は、あるスキーマに作成されたキューおよびトピックを他のスキーマで実行中のアプリケーションから保護できます。そのキューまたはトピックが属するスキーマの外で実行しているアプリケーションには、最小限のアクセス権限のみを付与できます。キューまたはトピックに対するアクセス権限として、ENQUEUE
、DEQUEUE
およびALL
がサポートされています。
メッセージは、相互に関連していることがよくあります。たとえば、あるメッセージを処理した結果として他のメッセージが生成された場合、両者は関連付けられています。アプリケーション設計者としては、そのような関連を追跡することが必要な場合があります。Oracle Database Advanced Queuingでは、ユーザーがメッセージをキュー表に保持し、分析のためにSQLで問合せできます。
保存機能およびメッセージ識別子とともに、メッセージ・ジャーナルがOracle Database Advanced Queuingによって自動作成され、追跡ジャーナルまたはイベント・ジャーナルをコールできます。保存、メッセージ識別子およびSQL問合せの協調によって、強力なメッセージ・ウェアハウスを構築できます。
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操作を最小限に抑えます。
各インスタンスは、それぞれのOracle Database Advanced Queuing統計情報をシステム・グローバル領域(SGA)に所有し、他のインスタンスによって収集された統計については認識しません。そのため、インスタンスがGV$AQ
ビューを問い合せると、その他のすべてのインスタンスからそれぞれのその時点の統計情報が問合せ元のインスタンスに集まります。
GV$AQ
ビューは、待機中、準備完了または期限切れの各メッセージ数を必要なときにいつでも問い合せることができます。また、メッセージが処理されるまでの平均待機秒数も表示します。
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.AQjmsAgent
、javax.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プロパティには、Send
およびReceive
操作に指定されたパラメータを使用して設定されるものもあります。
プロパティで、メッセージにオプションのヘッダー・フィールドを追加できます。プロパティによって、クライアントは、messageSelector
を使用して、クライアントのかわりにJMSプロバイダにアプリケーション固有基準を使用してメッセージを選択させることができます。プロパティ名は文字列で、サポートされている値はBoolean
、Byte
、Short
、Integer
、Long
、Float
、Double
および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
このフィールドは、プロバイダによって設定されたメッセージ状態です。メッセージ状態は、WAITING
、READY
、EXPIRED
またはRETAINED
です。
Oracle固有のJMSプロパティは、すべてJMS_Oracle
で始まります。次のものがあります。
JMS_OracleExcpQ
このフィールドは、元の宛先に配信できないメッセージを送信するキュー名です。JMSクライアントによって設定されるString
型です。EXCEPTION
タイプの宛先のみをJMS_OracleExcpQ
プロパティで指定できます。
JMS_OracleDelay
このフィールドは、メッセージの配信を遅延する時間(秒単位)です。JMSクライアントによって設定されるInteger
型です。これは、メッセージの配信順序に影響を与える可能性があります。
JMS_OracleOriginalMessageId
このフィールドは、メッセージがある宛先から別の宛先に伝播された場合に、ソースのメッセージのメッセージ識別子に設定されます。JMSプロバイダによって設定されるString
型です。メッセージが伝播されていない場合、このプロパティはJMSMessageId
と同じ値です。
クライアントは、プロパティを定義することによって、メッセージにヘッダー・フィールドを追加できます。これらのプロパティをmessageSelector
で使用して特定のメッセージを選択できます。
JMSでは、次の5つのフォーマットのメッセージ本体が提供されます。
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[] |
---|---|---|---|---|---|---|---|---|---|---|
|
X |
- |
- |
- |
- |
- |
- |
- |
X |
- |
|
- |
X |
X |
- |
X |
X |
- |
- |
X |
- |
|
- |
- |
X |
- |
X |
X |
- |
- |
X |
- |
|
- |
- |
- |
X |
- |
- |
- |
- |
X |
- |
|
- |
- |
- |
- |
X |
X |
- |
- |
X |
- |
|
- |
- |
- |
- |
- |
X |
- |
- |
X |
- |
|
- |
- |
- |
- |
- |
- |
X |
X |
X |
- |
|
- |
- |
- |
- |
- |
- |
- |
X |
X |
- |
|
X |
X |
X |
X |
X |
X |
X |
X |
X |
- |
|
- |
- |
- |
- |
- |
- |
- |
- |
- |
X |
BytesMessage
オブジェクトは、1つの未解釈バイトのストリームを含むメッセージを送信する場合に使用します。これはMessage
から継承し、BytesMessage
本文を追加します。メッセージの受信者が、そのバイト列を解析します。このメソッドは、主にjava.io.DataInputStream
およびjava.io.DataOutputStream
のメソッドに基づいています。
これは、クライアントが既存のメッセージ・フォーマットをコード化するためのメッセージ型です。可能であれば、かわりに他の自己定義メッセージ型を使用してください。
Javaの基本データ型の値は、それぞれの型のメソッドを使用して、明示的に書込みができます。また、抽象的なオブジェクトとして書き込むこともできます。BytesMessage
オブジェクトを使用するには、SYS.AQ$_JMS_BYTES_MESSAGE
またはAQ$_JMS_MESSAGE
ペイロード型を持つキュー表を作成します。
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[] |
---|---|---|---|---|---|---|---|---|---|---|
|
X |
- |
- |
- |
- |
- |
- |
- |
X |
- |
|
- |
X |
X |
- |
X |
X |
- |
- |
X |
- |
|
- |
- |
X |
- |
X |
X |
- |
- |
X |
- |
|
- |
- |
- |
X |
- |
- |
- |
- |
X |
- |
|
- |
- |
- |
- |
X |
X |
- |
- |
X |
- |
|
- |
- |
- |
- |
- |
X |
- |
- |
X |
- |
|
- |
- |
- |
- |
- |
- |
X |
X |
X |
- |
|
- |
- |
- |
- |
- |
- |
- |
X |
X |
- |
|
X |
X |
X |
X |
X |
X |
X |
X |
X |
- |
|
- |
- |
- |
- |
- |
- |
- |
- |
- |
X |
TextMessage
オブジェクトは、java.lang.StringBuffer
を含むメッセージを送信する場合に使用します。これはMessage
から継承し、TextMessage
本文を追加します。テキスト情報は、getText()
およびsetText(
...)
メソッドを使用して読込みまたは書込みができます。TextMessage
オブジェクトを使用するには、SYS.AQ$_JMS_TEXT_MESSAGE
またはAQ$_JMS_MESSAGE
ペイロード型を持つキュー表を作成します。
ObjectMessage
オブジェクトは、シリアライズ可能なJavaオブジェクトを含むメッセージを送信する場合に使用します。これはMessageから継承し、単一のJava参照を含む本文を追加します。シリアライズ可能なJavaオブジェクトのみ使用できます。Javaオブジェクトのコレクションを送信する必要がある場合、JDK 1.4で提供されているコレクション・クラスのいずれかを使用できます。オブジェクトは、getObject()
メソッドおよびsetObject(
...)
メソッドを使用して読込みまたは書込みできます。ObjectMessage
オブジェクトを使用する場合、SYS.AQ$_JMS_OBJECT_MESSAGE
またはAQ$_JMS_MESSAGE
ペイロード型でキュー表を作成します。
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
コールを使用して設定できます。StreamMessage
、BytesMessage
、ObjectMessage
、TextMessage
およびMapMessage
オブジェクトの場合、クライアントによって次の設定ができます。
JMSXAppID
JMSXGroupID
JMSXGroupSeq
JMS_OracleExcpQ
JMS_OracleDelay
AdtMessage
オブジェクトの場合、クライアントによって次の設定ができます。
JMS_OracleExcpQ
JMS_OracleDelay
次のメッセージ・プロパティは、クライアントがgetProperty
コールを使用して取得できます。StreamMessage
、BytesMessage
、ObjectMessage
、TextMessage
およびMapMessage
オブジェクトの場合、クライアントが次を取得できます。
JMSXuserID
JMSXAppID
JMSXDeliveryCount
JMSXGroupID
JMSXGroupSeq
JMSXRecvTimeStamp
JMSXState
JMS_OracleExcpQ
JMS_OracleDelay
JMS_OracleOriginalMessageId
メッセージの送信時に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であるbufferSend
、bufferPublish
およびbufferReceive
を使用する必要があります。
関連項目: bufferSend 、bufferPublish およびbufferReceive の詳細は、Oracle Databaseアドバンスト・キューイングJava APIリファレンスを参照してください |
ペイロード制限
バッファ済メッセージのOracle Database Advanced Queuing実装では、LOB
属性はサポートされていません。このため、5種類の標準JMSメッセージのペイロードには次の制限が適用されます。
JMS TextMessage
のペイロードは4000バイト以内です。
Oracle JMSのキャラクタ・セット変換時には、テキスト・ペイロードをデータベースに格納するためにVARCHAR
のかわりにCLOB
を使用するように控え目な選択が必要になる場合があるため、データベース・キャラクタ・セットによってはこの上限値がさらに低くなる場合があります。
JMS BytesMessage
のペイロードは2000バイト以内です。
JavaでシリアライズされたJMS ObjectMessage
、StreamMessage
およびMapMessage
データは、2000バイト以内である必要があります。
他のすべてのOracle JMS ADTメッセージの場合、対応するOracleデータベースADTにLOB
属性を含めることはできません。
各種定数
表11-3に示すように、Oracle Database Advanced QueuingとOracle JMSのAPIでは、バッファ済メッセージと永続メッセージの指定に使用される数値が異なります。
Point-to-Pointモデルでは、クライアントは、1つのポイントから別のポイントへメッセージを交換します。メッセージのプロデューサとコンシューマは、シングル・コンシューマ・キューを使用してメッセージを送受信します。管理者は、AQjmsSession
のcreateQueue
メソッドを使用して、シングル・コンシューマ・キューを作成します。キューを使用する前に、AQjmsDestination
でstart
コールを使用して、キューをエンキュー/デキューに対して有効にする必要があります。クライアントは、AQjmsSession
のgetQueue
メソッドを使用して事前に作成されたキューに対するハンドルを取得します。
シングル・コンシューマ・キューの場合、メッセージは1つのコンシューマが1度のみ処理できます。同じキューから同時にデキューするプロセスまたはオペレーティング・システム・スレッドが複数存在する場合、各プロセスはキューの先頭にあるロックされていない最初のメッセージをデキューします。ロックを作成したプロセス以外のプロセスは、ロックされたメッセージをデキューできません。
処理が済むと、キューの保存期間が0(ゼロ)の場合はそのメッセージは削除され、そうでない場合は指定された期間保存されます。メッセージが保存されている間は、キュー表ビューに対してSQLを使用して問い合せたり、QueueBrowser
で処理済メッセージのメッセージ識別子を指定してデキューできます。
クライアントは、QueueSender
を使用して、キューにメッセージを送信します。これは、クライアントのSession
でキューをcreateSender
メソッドに渡すことによって作成されます。また、クライアントにはキューを指定しないで、QueueSender
を作成するオプションがあります。この場合、キューを送信操作のたびに指定する必要があります。
クライアントは、QueueSender
によって送信されたすべてのメッセージのデフォルト配信モード、優先順位およびTimeToLive
を指定できます。または、クライアントはこれらのオプションを各メッセージに対して定義できます。
クライアントはQueueReceiver
を使用してキューからメッセージを受信します。これは、クライアントのSession
でcreateQueueReceiver
を使用して作成されます。messageSelector
があってもなくても作成できます。
QueueBrowser
を使用すると、クライアントはメッセージを削除しないで、キュー上でメッセージを参照できます。このブラウズ用メソッドは、キュー内のメッセージをスキャンするために使用されるjava
.util
.Enumeration
を戻します。nextElement
に対する最初のコールが、キューのスナップショットを取得します。QueueBrowser
は、messageSelector
を使用して作成しても、使用せずに作成してもかまいません。
QueueBrowser
も、メッセージをスキャン中にオプションでロックできます。これは、メッセージに対するSELECT
...for
UPDATE
コマンドの場合と似ています。これによって、他のコンシューマがスキャン中のメッセージを削除することはなくなります。
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では、パブリッシャ(出版者)の機能を持つアプリケーションとサブスクライバ(購読者)の役割を果すアプリケーションとの間の柔軟で動的な通信が可能です。アプリケーションが結合されることはなく、メッセージとその内容に基づいて相互に作用します。
メッセージの配信では、パブリッシャ・アプリケーションが明示的にメッセージ受信者を処理または管理する必要はありません。このため、パブリッシャ・アプリケーションの論理を変更しなくても、新しいサブスクライバ・アプリケーションを動的に追加できます。
同様にサブスクライバ・アプリケーションは、メッセージを送信しているパブリッシャ・アプリケーションに関係なく、メッセージの内容に基づいてメッセージを受信します。このため、サブスクライバ・アプリケーションの論理を変更しなくても、新しいパブリッシャ・アプリケーションを動的に追加できます。
サブスクライバ・アプリケーションは、メッセージ・プロパティまたはトピックのメッセージ内容に対してルールベースのサブスクリプション(予約購読)を定義することで、どのようなメッセージに関心があるのかを指定できます。システムは、ルールベースのサブスクリプションを使用して、パブリッシュされたメッセージの受信者を計算し、自動的にルーティングします。
パブリッシュ・サブスクライブ・モデルでは、メッセージはトピックに対してパブリッシュされ、トピックから受信されます。トピックは、AQjmsSession
のCreateTopic()
メソッドを使用して作成されます。クライアントは、AQjmsSession
のgetTopic()
メソッドを使用して事前に作成されたトピックに対するハンドルを取得できます。
クライアントはDurableSubscriber
を、クライアントのSession
内でcreateDurableSubscriber()
メソッドを使用して作成します。messageSelector
があってもなくても作成できます。
messageSelector
によって、クライアントは、サブスクライバに配信されるメッセージをセレクタにマッチするメッセージに制限できます。セレクタ構文の詳細は、Oracle Databaseアドバンスト・キューイングJava APIリファレンスのcreateDurableSubscriber
に関する項を参照してください。
永続サブスクライバが同じ名前を使用するときのアクションは、実行時に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のどちらで作成されたかが不明であるため、その他のトピックについてのサブスクリプションは削除しないでください。
リモート・サブスクライバは、createRemoteSubscriber
コールを使用して定義されます。リモート・サブスクライバは、リモート・トピックでの特定のコンシューマ、またはリモート・トピックでのすべてのサブスクライバになることができます。
リモート・サブスクライバは、AQjmsAgent
構造を使用して定義されます。AQjmsAgent
は、名前およびアドレスで構成されます。名前は、リモート・トピックのconsumer_name
を参照します。アドレスは、次のようにしてリモート・トピックを参照します。
schema.topic_name[@dblink]
リモート・トピックで特定のコンシューマに対してメッセージをパブリッシュするには、リモート・トピックでの受信者のsubscription_name
が、AQjmsAgent
の名前フィールドに指定されている必要があります。リモート・トピックは、AQjmsAgent
のaddressフィールドに指定される必要があります。
リモート・トピックのすべてのサブスクライバに対してメッセージをパブリッシュするには、AQjmsAgent
のnameフィールドをNULLに設定する必要があります。リモート・トピックは、AQjmsAgent
のaddressフィールドに指定される必要があります。
メッセージはTopicPublisher
を使用してパブリッシュされます。これは、Topic
をcreatePublisher
メソッドに渡すことによって作成されます。また、クライアントにはTopic
を指定しないで、TopicPublisher
を作成するオプションがあります。この場合、Topic
をパブリッシュ操作のたびに指定する必要があります。クライアントは、TopicPublisher
によって送信されるすべてのメッセージのデフォルト配信モード、優先順位およびTimeToLive
を指定できます。また、各メッセージごとに、これらのオプションを指定することもできます。
JMSパブリッシュ・サブスクライブ・モデルでは、クライアントは、トピックのすべてのサブスクライバにメッセージを送信するのではなく、明示的な受信者リストを指定できます。これらの受信者は、トピックの既存のサブスクライバである場合もあれば、そうでない場合もあります。受信者リストは、このメッセージのトピックのサブスクリプション・リストをオーバーライドします。受信者リスト機能は、JMSに対するOracleの拡張です。
受信者名が受信者リストに明示的に指定されていても、その受信者がキューのサブスクライバではない場合、その受信者に送信されるメッセージは、TopicReceiver
を作成することによって受信できます。サブスクライバ名が指定されていない場合、クライアントがメッセージを受信するには、リモート・サイトで永続サブスクライバを使用する必要があります。TopicReceiver
は、JMSに対するOracleの拡張です。
TopicReceiver
は、messageSelector
を使用して作成できます。これによって、クライアントは、受信者に配信されるメッセージをセレクタにマッチするメッセージに制限できます。
TopicBrowser
を使用すると、クライアントはメッセージを削除しないでトピック上でメッセージを参照できます。このブラウズ用メソッドは、トピック・メッセージをスキャンするために使用されるjava.util.Enumeration
を戻します。TopicBrowser
を作成できるのは、永続サブスクライバのみです。nextElement
に対する最初のコールが、トピックのスナップショットを取得します。
TopicBrowser
は、メッセージをスキャン中にオプションでロックできます。これは、メッセージに対するSELECT
...for
UPDATE
コマンドの場合と類似しています。これによって、他のコンシューマがスキャン中のメッセージを削除することはなくなります。
TopicBrowser
は、messageSelector
を使用して作成できます。これによって、クライアントは、コンシューマに配信されるメッセージをセレクタにマッチするメッセージに制限できるようになります。
TopicBrowser
は、パージ機能をサポートしています。これによって、TopicBrowser
を使用するクライアントは、トピックの現行のブラウズ操作中に参照されたすべてのメッセージを廃棄できます。パージとは、参照済のすべてのメッセージを破壊的に受信することと同じです(TopicSubscriber
を使用して削除した場合と似ています)。
パージでは、メッセージがTopicBrowser
のjava.lang.Enumeration
のnextElement()
操作へのコールを使用してクライアントに戻された場合、そのメッセージは参照済とみなされます。クライアントがまだ参照していないメッセージは、パージ中には廃棄されません。パージ操作は、同じTopicBrowser
に対して何度も実行できます。
TopicBrowser
の作成に使用したJMS Session
がコミットされると、パージは正常に実行されます。セッションに対する操作がロールバックされた場合、パージ操作も取り消されます。
JMSでパブリッシュ・サブスクライブ・モデルの通信を使用する手順は、次のとおりです。
メッセージを保持するために1つ以上のトピックを設定します。これらのトピックは、関心がある領域またはサブジェクトを表します。たとえば、トピックで請求済注文情報を表すことができます。
AQjmsDestination
でstart
コールを使用して、トピックに対するエンキュー/デキューを有効にします。
永続サブスクライバのセットを作成します。各サブスクライバは、受信を希望するメッセージを選択するmessageSelector
を指定できます。NULLのmessageSelector
は、そのトピックに対してパブリッシュされたすべてのメッセージの受信をサブスクライバが希望していることを示します。
サブスクライバはローカルでもリモートでもかまいません。ローカル・サブスクライバは、メッセージがパブリッシュされるトピックと同じトピックに対して定義された永続サブスクライバです。リモート・サブスクライバは、特定のキューのサブスクライバとして定義された別のトピックまたはそのトピックに対する受信者です。リモート・サブスクライバを使用するには、ソース・トピックと宛先トピック間の伝播を設定する必要があります。リモート・サブスクライバと伝播は、JMSに対するOracleの拡張です。
パブリッシャのSession
でcreatePublisher()
メソッドを使用してTopicPublisher
オブジェクトを作成します。メッセージは、publish
コールを使用してパブリッシュされます。メッセージは、トピックのすべてのサブスクライバ、またはトピックに対する指定された受信者のサブセットに対してパブリッシュできます。
サブスクライバは、receive
メソッドを使用してトピックに関するメッセージを受信します。
サブスクライバは、メッセージ・リスナーを使用して、非同期にメッセージを受信することもできます。
メッセージの順序付けは、メッセージがキューまたはトピックから受信される順序を決定します。キューまたはトピックのキュー表の作成時に順序づけの方式が指定されます。現在は、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アプリケーションは、メッセージ・コンシューマを作成することによって、メッセージを受信できます。メッセージは、receive
コールを使用して同期的に受信するか、メッセージ・リスナーを使用して非同期的に受信できます。
受信モードには次の3つがあります。
メッセージがコンシューマに届くまでブロック
指定最大時間までブロック
非ブロック
コンシューマがナビゲーション・モードを指定しない場合、セッションの最初のreceive
はキューまたはトピックの最初のメッセージを取り出し、第2のreceive
は次のメッセージを取得します。優先順位が高いメッセージがコンシューマに届く場合、すでに届いているメッセージを削除するまで、コンシューマはこのメッセージを受信しません。
コンシューマが、メッセージに対してより効率的にキューのナビゲーションを制御できるように、Oracle Database Advanced QueuingにはJMS拡張機能として複数のナビゲーション・モードが用意されています。これらのモードは、TopicSubscriber
、QueueReceiver
またはTopicReceiver
で設定できます。
グループ化されていないメッセージには、次の2つのモードを使用できます。
FIRST_MESSAGE
このモードでは、位置がキューの先頭にリセットされます。コンシューマがキューの最上位にあるメッセージを削除できるため、優先順位に基づくキューで役立ちます。
NEXT_MESSAGE
このモードは、コンシューマの確立された位置の後のメッセージを取得します。たとえば、4番目のメッセージの位置で適用されたNEXT_MESSAGE
は、そのキューの5番目のメッセージを取得します。これはデフォルトのアクションです。
グループ化メッセージには、次の3つのモードを使用できます。
FIRST_MESSAGE
このモードでは、位置がキューの先頭にリセットされます。
NEXT_MESSAGE
このモードでは、位置が同一トランザクションの次のメッセージに設定されます。
NEXT_TRANSACTION
このモードでは、位置が次のトランザクションの最初のメッセージに設定されます。
注意: JMSシャード・キューは、前述の3つのモードをサポートしていません。 |
次の方法でメッセージが受信される場合、グループ化トランザクションのプロパティを無効にできます。
セレクタに相関識別子を指定して受信
セレクタにメッセージ識別子を指定して受信
トランザクション・グループのメッセージがすべて受信される前にコミット
NEXT
_MESSAGE
またはNEXT
_TRANSACTION
オプションの使用中にコンシューマがキューの最後に到達したとします。ブロッキングreceive()
を指定していた場合は、ナビゲート位置は自動的にそのキューの先頭に変更されます。
デフォルトでは、QueueReceiver
、TopicReceiver
または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シャード・キューは、再試行の遅延をサポートしていません。 |
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シャード・キューは、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 マークは付いていません。 |
あるフォーマットのメッセージを別のフォーマットのメッセージにマップするために変換を定義できます。変換は、同一の情報を異なるフォーマットで表現するアプリケーションを統合する必要がある場合に有効です。変換はSQL式およびPL/SQLファンクションです。メッセージ変換は、標準JMSインタフェースに対するOracle Database Advanced Queuingの拡張機能です。
変換は、DBMS_TRANSFORM.create_transformation
プロシージャを使用して作成できます。変換は、次の操作を行う場合に指定できます。
キューまたはトピックへのメッセージの送信
キューまたはトピックからのメッセージの受信。
TopicSubscriber
の作成
RemoteSubscriber
の作成。これによって、異なるフォーマットのトピック間でメッセージを伝播できます。
注意: 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のオーバーヘッドを削減します。
この項の内容は次のとおりです。
シャード・キューは、専用のメッセージ・キャッシュを導入しており、これを使用すると、SGAの使用量をトレードオフでき、スループットの向上、待ち時間の削減、同時処理の向上を図れます。パーティション化と組み合せると、メッセージ・キャッシュで、一部の問合せ、DML操作および索引に対する必要性が低くなります。メッセージ・キャッシュは、デキュー元の処理がエンキュー元に追いついている場合、およびメッセージ・キャッシュが、各シャード・キューのエンキュー元およびデキュー元に対して、メッセージ(ペイロードを含む)を十分に格納できる大きさである場合に最も効果的です。メッセージ・キャッシュでは、Streamsプールが使用されます。JMSシャード・キューが、Streamsのレプリケーション機能と同じインスタンスでStreamsプールを共有する場合、SET_MIN_STREAMS_POOL
およびSET_MAX_STREAMS_POOL
などのDBMS_AQADM
プロシージャを使用して、Streamsプールのメモリー割当てを微調整できます。
関連項目: 詳細は、『Oracle Database PL/SQLパッケージ・プロシージャおよびタイプ・リファレンス』を参照してください。 |
スループットを向上させ、オーバーヘッドおよび待ち時間を削減するために、エンキューおよびデキューは、メッセージ・キャッシュ、ルール・エンジン、および可能な場合はバックグラウンド処理を使用するように最適化されています。次に例を示します。
シャード・キューは、新しいルール・エンジンの改善点を利用します。
メッセージ・キャッシュ内にペイロードのあるメッセージは、デキュー中にディスクから再読取りする必要がありません。
相関IDによるデキューまたはその他のJMSプロパティは、ディスクにアクセスすることなく頻繁に評価できます。
シャード・キューにおけるパーティション操作により、効率的な一括処理が実装されます。
JMSシャード・キューは、次のネイティブ・サポートを有しています。
非永続サブスクライバ
JMSペイロード
優先順位
JMSシャード・キューでは、永続メッセージと非永続メッセージの両方がサポートされます。非永続メッセージはメッセージ・キャッシュ内のメモリーに格納され、ディスクには格納されません。そのため、非永続メッセージは、インスタンスのクラッシュ時や停止時に失われます。
JMSシャード・キューは、JMS要件を満たす2種類のサブスクライバをネイティブにサポートしています。
非永続サブスクライバ: これらのサブスクライバは、サブスクライバがアクティブ中にメッセージがパブリッシュされた場合のみ、選択されたトピックについてのメッセージを受信します。このサブスクリプションは、異なるセッション間で共有できません。
永続サブスクライバ: これらのサブスクライバは、サブスクライバが非アクティブ中にパブリッシュされたメッセージを含めて、トピックについてパブリッシュされたすべてのメッセージを受信します。複数のデータベース・セッションで、同じサブスクリプションを共有できます。
JMSシャード・キューは、ADTを使用してJMSペイロードを格納しません。JMSメッセージは、データベースのスカラー列に格納されます。TEXT
、BYTES
、MAP
、STREAM
、OBJECT
などのJMSメッセージ・タイプは、ペイロードのサイズとタイプに応じて、キュー表のTEXT
/RAW
またはCLOB/BLOB
のスカラー列にJMSペイロードを格納します。JMSメッセージ・プロパティは、ユーザー定義プロパティに属性アクセス機能が定義されているキュー表のCLOB
(SecureFile)列に格納されます。ペイロードおよびユーザー・プロパティは、ADTとして格納されずに、RAW
、VARCHAR2
または保護ファイル列に格納されます。JMSヘッダー・プロパティおよびJMSプロバイダ情報は、それ自体のスカラー列に格納されます。
JMSシャード・キューでは、0 (最も低い優先度)から9 (最も高い優先度)の範囲で整数の優先順位の値がサポートされており、JMS標準で定義されているように、デフォルトは4です。
JMSシャード・キューは、キュー表に使用される、基礎となるパーティション化された表を自動的に管理します。このようなパーティション管理は、フォアグラウンドまたはバックグラウンドで実行されます。各シャードは、エンキューされたメッセージのセッションレベルの順序付けを提供します。各エンキュー・セッションにはシャードが割り当てられます。各シャードは、一連のサブシャードで構成されます。各サブシャードは、1つのパーティションにマップされます。JMSメッセージは、エンキュー時に表パーティションに自動的に割り当てられます。
新しいパーティションは、デキュー元がエンキュー元の処理に追いついておらず、キュー表を大きくする必要がある場合など、必要に応じて自動的に作成されます。パーティション内のすべてのメッセージがデキューされて必要がなくなった場合、パーティションは切り捨てられ再利用されます。メッセージ・キャッシュは、デキュー元による要求に応じて、メッセージをパーティションからメモリーに自動的にロードします。グローバル索引は、JMSシャード・キューの基礎となる、パーティション化された表に作成できません。ローカル索引も、パーティション化された表では通常推奨されません。これらの索引が必要であるがパフォーマンスが低下する場合は、非シャード・キューの使用を検討してください。
JMSシャード・キューは、可能な場合にはインスタンス間通信を回避しながら、自動的にエンキュー・セッションの順序付けを行います。インスタンス間通信が必要な場合もあります。たとえば、JMSシャード・キューで、1つのOracleインスタンス上に単一のエンキュー・セッションがあり、別のインスタンスに単一のデキュー・セッションがある場合、JMSシャード・キューはOracle RACインスタンス間でメッセージを転送します。パフォーマンスを向上させるため、メッセージの転送は、エンキュー・トランザクションに対してアトミックではありません。シャードにメッセージがないインスタンスに接続している場合、デキュー元でORA-25228が発生する場合があります。
ほとんどの場合、スループットを改善し、インスタンス間のオーバーヘッドを削減するために、各サブスクライバに対し複数のデキュー元を持つか、各Oracle RACインスタンスに単一のコンシューマ・キューを持つことを検討します。単一メッセージを指定するデキュー・セレクタを使用している場合は例外です。Oracle RACデータベースのメッセージ識別子により、共有キューからメッセージをデキューする場合、メッセージを含む共有キューのデキュー所有権を割り当てられたインスタンスに接続する必要があります。そうしないと、メッセージはデキュー・セッションへのデキューで使用できません。すべてのデキューが単一インスタンスで実行される場合、メッセージはこのインスタンスに自動的に転送されます。そのため、メッセージIDで広くデキューする共有単一コンシューマ・キューの場合は、共有キューのすべてのデキュー・セッションが単一インスタンスに接続することを検討してください。同様に、メッセージIDで広くデキューする共有複数コンシューマ・キューの場合は、各サブスクライバのすべてのデキュー・セッションが単一インスタンスに接続することを検討してください。サービスを使用してデキュー・セッションの特定のインスタンスへの接続を簡略化することができます。
現在、JMSシャード・キューでは、次のOracle Database Advanced Queuingの機能はサポートされていません。
メッセージの保存
メッセージの遅延
グループ化トランザクション
配列のエンキュー
配列のデキュー
メッセージのエクスポートおよびインポート
サブスクライバの通知の転送
メッセージ・ゲートウェイ
例外キュー
JMS以外のエンキューまたはデキュー。たとえば、PL/SQLおよびOCIのエンキューとデキューは、JMSシャード・キューではサポートされていません
JMS伝播およびリモート・サブスクライバなど、JMSのOracle拡張機能
1つのキュー表に複数のキュー。シャード・キューは、CREATE_SHARDED_QUEUE
インタフェースを介して作成されます。
JMS標準で指定されているメッセージ優先順位、エンキュー時刻の順以外の順序付け。
JDBC thick (OCI)ドライバ。
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_SIZE
とSGA_TARGET
の初期化パラメータがどちらも0
に設定されている場合は、デフォルトにより、データベースで最初にStreamsプールを使用したときに、バッファ・キャッシュから共有プールの10%に相当する容量のメモリーがStreamsプールに割り当てられます。
関連項目:
|
SGA自動チューニングの有効化
Streamsプールの使用量およびSGAを使用するその他のコンポーネントの使用量に基づいて、SGAからStreamsプールに適切な量のメモリーが自動的に割り当てられます。その他のコンポーネントには、バッファ・キャッシュ、ライブラリ・キャッシュなどがあります。STREAMS_POOL_SIZE
を指定した場合は、下限として使用されます。
AQ JMSは、大量のメッセージ・データまたはペイロードを送受信するアプリケーション用に、AQjmsBytesMessage
およびAQjmsStreamMessage
を介した共有キューのエンキューおよびデキューでのストリーミングをサポートするようになりました。
JMSストリーミングは、大きい連続したバイトの配列を送受信するのではなく、メッセージ・ペイロードを小さいチャンクに分割することにより、大きいメッセージを扱うときのメモリー要件を緩和します。JMS標準にストリーミング・メカニズムは含まれないため、AQ JMSはAQストリーミング・エンキューおよびデキュー機能を示すための固有のインタフェースを提供します。これにより、ユーザーは既存のjava入出力ストリームを使用してメッセージ・データまたはペイロードを簡単に送受信できます。
データベースのRDBMS 12.1.0.2へのアップグレード時に既存のアプリケーションが変更なしで動作できるように、デフォルトではストリーミングAPIは無効化されます。
クライアント・アプリケーションはシステム・プロパティoracle.jms.useJmsStreaming
をtrue
に設定して使用することにより、JMSストリーミングを有効化できます。
注意: JMSストリーミングはThinドライバの場合のみサポートされます。 |
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);
注意:
|
ストリーミングを使用したデキュー操作は、2つの手順で実行されます。サーバーでは、メッセージ本文のサイズに基づき、メッセージ本文をストリーミングするかどうかが決定されます。デフォルトのしきい値制限は10MBです。そのため、メッセージ本文が10MBよりも大きく、システム・プロパティoracle.jms.useJmsStreamingを使用して、ストリーミングがクライアントで有効な場合、サーバーはデキューでストリーミングを使用します。
これはクライアントがreceive()
メソッドを呼び出す場合の通常のデキュー・プロセスです。
Destination destination = session.createQueue ("queueName"); AQjmsConsumer consumer = (AQjmsConsumer) session.createConsumer(destination); Message message = consumer.receive(10000);
クライアントがペイロードなしのメッセージを受信する場合、クライアントは受信メッセージでの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はAQjmsStreamMessage
とAQjmsBytesMessage
に対して正確にメッセージ本文の長さを移入します。そのため、クライアント・アプリケーションはメッセージで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
を使用してセッションで使用可能です。
Oracle Database 12cリリース1 (12.1)では、Oracle JMSはオラクル社のSun JMS 1.1標準に準拠しています。実行時に、Oracle Java Message Service (Oracle JMS)クライアントに対してJava EE準拠モードを定義できます。準拠モードにするには、コマンドライン・オプションとしてJavaプロパティ oracle.jms.j2eeCompliant
をTRUE
に設定します。非準拠モードにする場合は何もしません。FALSE
がデフォルト値です。
Java EE準拠をサポートし、非準拠モードでも使用できるOracle Database Advanced Queuingの機能は次のとおりです。
非トランザクション・セッション
永続サブスクライバ
一時キューおよびトピック
非永続配信モード
AQ$_JMS_MESSAGE
型のOracle Database Advanced Queuingキューを使用した単一のJMSキューまたはトピックに対する複数のJMSメッセージ・タイプ
永続サブスクライバに対するnoLocal
オプション
JMSシャード・キューはJMSでネイティブにサポートされており、Java EEコンプライアンスに準拠しています
関連項目
|