Oracle® Fusion Middleware Oracle WebLogic Server JMSアプリケーションの開発 12c (12.1.2) E48081-02 |
|
前 |
次 |
この章では、WebLogic Server JMSの設計オプション、設計の過程で考慮すべきアプリケーションの動作、および推奨の設計パターンについて説明します。
この節では、メッセージングのパフォーマンスを向上させるメッセージの設計方法について説明します。
Javaオブジェクトのシリアライズを行うと、CPUに非常に大きな負荷がかかるおそれがあります。最終的には、この負荷がJMSオブジェクト・メッセージに影響します。この負荷は、java.io.Externalizable
を実装するアプリケーション・オブジェクトを使用することである程度相殺できますが、クラス記述子のマーシャリングにおいては依然として大きなオーバーヘッドになります。Objectメッセージに組み込む追加オブジェクトのクラス記述子を記述する手間を省くには、これらのオブジェクトにExternalizable
を実装し、オブジェクト上で直接readExternal
およびwriteExternal
を呼び出します。たとえば、stream.writeObject(obj)
ではなくobj.writeExternal(stream)
を呼び出します。通常、Bytes
メッセージやStream
メッセージを使用すると、より望ましい結果が得られます。
Java文字列のシリアライズは、その他のJavaプリミティブ型のシリアライズよりも大きな負荷がかかります。文字列はメモリーも多用します。1文字につき2バイトのメモリーを消費し、バイナリ・データ(整数など)をコンパクトに表現することもできません。また、文字列ベースのメッセージを使用すると、多くの場合、文字列をアプリケーションで直接使用できる形式に処理するための解析が負荷になります。したがって、Bytesメッセージ、Streamメッセージ、Mapメッセージ、そしてObjectメッセージでさえも、TextメッセージやXMLメッセージよりも望ましい結果になることがあります。同様に、メッセージ・プロパティでは文字列を使用しないことをお薦めします(特にそのサイズが大きい場合)。
非永続メッセージのシリアライズの負荷は、WebLogic JMSサーバーにはかかりません。非永続メッセージ・タイプのシリアライズは、リモート・クライアントの負荷で実行されます。永続メッセージは、サーバーでシリアライズされます。
JMSアプリケーション内の大きなメッセージを圧縮するとパフォーマンスが向上します。圧縮することで、ネットワーク上でのメッセージの転送に必要な時間が短縮され、JMSサーバーが使用するメモリーの量も減ります。また、永続メッセージの場合は、永続書込みのサイズも小さくなります。多くの場合、TextおよびXMLメッセージはかなり圧縮できます。ただし、圧縮を行うと、当然のことながらクライアントのCPU使用量が増えることになります。
小さいメッセージの場合は、圧縮する利点がない場合もあります。メッセージのサイズが数KB以下の場合、圧縮することで実際のサイズが大きくなることもあります。JDKには、組込みの圧縮ライブラリが用意されています。詳細については、java.util.zip
パッケージを参照してください。
指定されたしきい値のサイズを超過したメッセージの自動圧縮をJMS接続ファクトリを使用して指定する方法については、『Oracle WebLogic Serverのパフォーマンスのチューニング』のメッセージの圧縮に関する項を参照してください。
ユーザー定義のメッセージ・プロパティのかわりに、標準のJMSメッセージ・ヘッダー・フィールドや、メッセージ・データのメッセージ本文を使用することも検討してください。メッセージ・プロパティは、シリアライズに余分な負荷がかかり、アクセスにおいても標準のJMSメッセージ・ヘッダー・フィールドより大きな負荷がかかります。
また、プロパティ・フィールドやヘッダー・フィールドに大量のデータを組み込むことも避けてください。ページングが有効になっている場合でも、ページングされるのはメッセージの本文のみです。したがって、アプリケーションにユーザー定義のメッセージ・プロパティが定義されている場合は、大きな文字列プロパティを使用しないようにしてください。
詳細については、「メッセージ・ヘッダー・フィールド」および「メッセージ・プロパティ・フィールド」を参照してください。
メッセージの処理を厳格に順序付けする場合は、再配信の順序付け機能ではなく、メッセージ順序単位機能を使用することをお薦めします。再配信の順序付けに比べ、メッセージ順序単位には以下の利点があります。
構成が容易であること。
非同期レシーバのカスタム接続ファクトリが必要ありません。たとえば、メッセージドリブンBean (MDB)を使用する場合は、MessagingMaximum
を1に設定します。
分散宛先を使用する場合の、単純な構成。
処理遅延の間もメッセージの順序が維持されます。
トランザクションのロールバックやセッションのリカバリの間もメッセージの順序が維持されます。
再配信の順序付けを使用しているアプリケーションは、メッセージ順序単位を使用するようにアップグレードすることをお薦めします。詳細については、第10章「メッセージ順序単位の使用」を参照してください。
アプリケーションの設計を始めるときには、トピックとキューのどちらを使用したほうがよいかを即座に判断できない場合もあります。一般的には、以下の条件のいずれかが満たされる場合にのみトピックを選択します。
同じメッセージを、複数のコンシューマにレプリケートする必要があります。
メッセージを選択するアクティブなコンシューマがない場合に、そのメッセージを破棄する必要があります。
たくさんのサブスクライバがあり、それぞれに一意のセレクタがあります。
恒久サブスクライバが1つのみのトピックは、セマンティクスの面ではキューに似ています。相違点は以下のとおりです。
恒久サブスクライバのトピック・セレクタを変更した場合、サブスクリプション内の以前のメッセージがすべて削除されますが、コンシューマのキュー・セレクタを削除してもキュー内のメッセージは削除されません。
キューの場合はメッセージを複数のコンシューマにラウンドロビン方式で配信できますが、トピック・サブスクライバのコンシューマは1つに制限されています。
JMSキューとトピックの構成の詳細は、『Oracle WebLogic Server JMSリソースの管理』のキューおよびトピック宛先のリソースに関する項を参照してください。
一般的に、非同期(onMessage
)コンシューマは、パフォーマンスとスケーラビリティの面で同期コンシューマより優れています。
非同期コンシューマの場合、作成されるネットワーク・トラフィックが少なくなります。メッセージは、メッセージ・リスナーへのパイプラインを使用して一方向に送信されます。パイプラインでは、複数のメッセージを単一のネットワーク呼出しに集約できます。
注意: WebLogic Serverでは、JMS接続ファクトリの「同期コンシューマのプリフェッチ・モード」オプションを有効にすることで、同期コンシューマでも非同期コンシューマと同じ効率的な動作を利用できるようになります。詳細は、「プリフェッチ・モードを使用した同期メッセージ・パイプラインの作成」を参照してください。 |
非同期コンシューマの場合、使用するスレッドが少なくなります。非同期コンシューマは、アクティブでない間はスレッドを使用しません。同期コンシューマは、受信呼出しの間スレッドを消費します。その結果、スレッドがアイドル状態になる期間が長くなり、呼出しにブロッキング・タイムアウトが指定されている場合は特に顕著になります。
サーバーで実行するアプリケーション・コードでは、ほとんどの場合、非同期コンシューマを(通常はMDBを介して)使用するのが最適。非同期コンシューマを使用することで、アプリケーション・コードがサーバー上でブロッキング処理を実行するのを回避できます。ブロッキング処理は、サーバー側スレッドをアイドルにし、デッドロックの原因になることもあります。デッドロックは、ブロッキング処理がすべてのスレッドを消費したときに発生します。ブロッキング処理自体の解除処理に使用するスレッドが残っていないと、ブロッキングを解除することができなくなってしまいます。
詳細については、「メッセージの非同期受信」および「メッセージの同期受信」を参照してください。
アプリケーションを設計する際は、永続QOSが必要な場合を除いて、メッセージが非永続モードで送信されるように指定してください。非永続モードをお薦めする理由は、同期書込みが無効になっていない限り、永続QOSが原因でパフォーマンスがかなり悪化する場合が多いためです。
注意: メッセージが誤って永続化されないよう十分に注意してください。設計者がメッセージを非永続モードで送信するつもりで設計しても、アプリケーションが永続メッセージを送信することがあります。 |
メッセージが本当に非永続であれば、通常のJMSストアには格納されません。誤って永続化されたメッセージがないことを確認するには、消費されていないメッセージがJMSサーバーに蓄積されているときに、JMSストアのサイズが大きくなっているかどうかをチェックします。以下に、メッセージの永続性を決定する条件を優先度の高い順に示します。
プロデューサの接続の接続ファクトリの構成:
PERSISTENT (デフォルト)
NON_PERSISTENT
QueueSenderおよびTopicPublisherでのJMSプロデューサAPIオーバーライド:
setDeliveryMode(DeliveryMode.PERSISTENT)
setDeliveryMode(DeliveryMode.NON_PERSISTENT)
setDeliveryMode(DeliveryMode.DEFAULT_DELIVERY_MODE) (デフォルト)
QueueSenderおよびTopicPublisherでのメッセージごとのJMSプロデューサAPIオーバーライド:
キューの場合は、send()の省略可能なdeliveryModeパラメータ
トピックの場合は、publish()の省略可能なdeliveryModeパラメータ
宛先の構成でのオーバーライド:
永続
非永続
配信しない(デフォルト、オーバーライドしないことを意味します)
JMSサーバーの構成でのオーバーライド:
ストアが構成されていない場合は、ターゲットの各WebLogic Serverインスタンス上で使用できるデフォルトの永続ストアを使用することを意味します。
ストアが構成されている場合はオーバーライドがないことを意味します。
恒久サブスクライバのみ:
サブスクライバがない場合や、トピックに非恒久サブスクライバしかない場合は、メッセージが非永続に格下げされます。(非恒久サブスクライバはJMSサーバーの稼動中しか存在しないため、メッセージを永続化する理由がありません。)
一時的な宛先:
一時的な宛先はそれらをホストするJMSサーバーの稼動中しか存在しないため、メッセージを永続化する理由がありません。WebLogic JMSでは、一時的な宛先のすべてのメッセージが自動的に非永続になります。
恒久サブスクライバが非永続メッセージしか受信しない場合でも、そのJMSサーバーには永続ストアを構成する必要があります。恒久サブスクリプションは、JMS仕様の要件に従って、サーバーの再起動後も継続するように永続化されます。
通常は送信よりも受信のほうに時間がかかるため、複数のメッセージを受信してまとめて確認応答できるようになるまで確認応答を延期して、受信に関わるオーバーヘッドを軽減することを検討してください。トランザクションを使用している場合は、「確認応答」を「コミット」と読み替えてください。
ただし、非恒久サブスクリプションの場合はすでに内部的に最適化されているため、確認応答を延期してもパフォーマンスはあまり向上しません。
非同期リスナーには、確認応答の延期を実装できない場合があります。メッセージ10個ごとに確認応答する非同期リスナーが5個のメッセージしか受信しなかった場合、最後のいくつかのメッセージが確認応答されない可能性があります。考えられる解決策としては、onMessage()
コールバック内からの同期非ブロッキング受信を非同期コンシューマにポストさせて、後続のメッセージを受信します。別の解決策としては、wake upリスナーがトリガーされたときに、リスナーの宛先にメッセージを送信するタイマーが開始されるようにします。このメッセージが正しいリスナーに確実に転送されれば、リスナーの宛先が起動してまだ確認応答されていない未処理の作業を完了します。
トランザクション非対応の非恒久トピック・サブスクライバがメッセージのローカル・コピーをクライアント側で格納するように最適化されており、これによって確認応答の発行に伴うネットワーク・オーバーヘッドを軽減しています。この最適化によってパフォーマンスが10 - 20%向上します。パフォーマンスの向上は、サブスクライバの負荷が大きいほどより顕著になります。
この最適化の副作用の1つは、特に数多くのトピック・サブスクライバが同時に存在する場合に、クライアント側でのガベージ・コレクションのオーバーヘッドが大きくなり、メッセージ・サブスクリプションのパフォーマンスが悪化するおそれがあることです。このような悪化を防ぐため、サブスクライバ・クライアントのヒープ・サイズを大きくすることをお薦めします。たとえば、10個のJVMで100個のサブスクライバを同時に存在させるテストでは、各JVMのヒープ・サイズの初期値と最大値を64 MBに設定すれば十分でした。
WebLogic JMSでは、パフォーマンスを改善できる代替のサービス品質(QOS)拡張が提供されています。
非恒久トピック・サブスクライバは、MULTICAST_NO_ACKNOWLEDGE
を使用してメッセージをサブスクライブできます。トピックにこのようなサブスクライバがある場合、JMSサーバーはマルチキャスト・モードを使用してこれらのサブスクライバにメッセージをブロードキャストします。マルチキャストでは、サブスクライバごとに1つずつメッセージを処理するのではなく、サブスクライバがいくつあってもネットワークで1つのメッセージを処理するだけでよいため、パフォーマンスが格段に向上し、直線的なスケーラビリティが提供されます。ネットワークが混み合っている場合や、クライアントによるメッセージ処理が遅れている場合は、マルチキャスト・メッセージが消失するおそれがあります。マルチキャスト・メッセージでrecover()
やacknowledge()
を呼び出しても効果はありません。
注意: クライアント側では、マルチキャスト・セッションごとに、マルチキャスト・ソケットからメッセージを取り出すための専用のスレッドが1つ必要になります。そのため、JMSクライアント側のスレッド・プール・サイズを増やして調整する必要があります。 |
このQOS拡張による保証は、非恒久トピック・サブスクリプション用にOracle WebLogic Server以外のベンダーから提供されている一部のJMS実装のデフォルトQOSによる保証と同じレベルです。JMS 1.1仕様では、サブスクライバの準備が整っていない場合に非恒久トピック・メッセージを破棄(削除)することが明確に許可されています。WebLogic JMSでは、非恒久トピック・サブスクリプション用に、JMS 1.1仕様で必須とされているレベルよりも高いレベルのQOSがデフォルトで提供されます。
NO_ACKNOWLEDGE配信モードでは、サーバーからコンシューマにメッセージが送信されますが、確認応答は呼び出されません。かわりに、サーバーはメッセージを事前に確認応答します。この確認応答モードでは、メッセージがすでに確認応答されているため、リカバリを呼び出しても機能しません。このモードを使用すると、確認応答のための追加のネットワーク呼出しによるオーバーヘッドは軽減されますが、サーバー、ネットワーク、またはクライアントで障害が発生した場合にメッセージが消失するおそれがあります。
注意: このような状況で非同期クライアントが |
NO_ACKNOWLEDGE QOSを使用する非同期コンシューマでは、クラッシュ時に消失するメッセージの数を抑えるために、メッセージ・パイプラインのサイズを小さくすることも検討してください。
JMS仕様(http://www.oracle.com/technetwork/java/jms/index.html
)では、close()
を呼び出したときを除き、セッション、プロデューサ、コンシューマ、またはメッセージ・メソッドをマルチスレッド化すると動作が不安定になるとされています。このリリースのWebLogic JMSでは、マルチスレッド化されたプロデューサを作成すると、サーバー・インスタンスからJMSException
がスローされます。アプリケーションのスレッドが制限されている場合は、プロデューサおよびセッションの数を増やすことを検討してください。
WebLogic Server 9.0以降では、メッセージ・センダーの認証されたユーザー名が自動的に伝播されるようにJMS接続ファクトリまたは宛先を構成できます。ユーザー名は、JMSXUserID
というjavax.jms.Message
プロパティに配置されます。
アプリケーションでJMSXUserID
プロパティを使用する場合は、次の点に注意してください。
JMSXUserID
はJMS仕様によって規定されますが、その動作の定義は厳格ではないため、JMSベンダーによって動作が異なる場合があります。
JMSXUserID
は、アプリケーションがJMSプロデューサの作成に使用するスレッドの資格証明に基づいています。JMS送信呼出し時にスレッド上にある資格証明からは派生しません。
JMSは、アプリケーションがJMSXUserID
を直接設定しようとする試行を無視またはオーバーライドします(たとえば、javax.jms.Message.setXXXProperty()
は機能しません)。
JMSメッセージは署名または暗号化されません(RMI/EJB呼出しと同様)。したがって、JMSXUserID
を完全に保護して転送するには、セキュア・プロトコル(t3s
やhttps
など)を使用してメッセージを送信する必要があります。
WebLogicストア・アンド・フォワード・エージェントは、JMSXUserID
を伝播しません(nullに設定します)。
WebLogicメッセージング・ブリッジは、メッセージング・ブリッジが9.0以降のJMSサーバーに転送し、メッセージのプロパティを保持するように構成されている場合、ソース宛先のメッセージのJMSXUserID
を伝播します。それ以外の場合は、転送されたメッセージはユーザー名を含まないか、ブリッジ・センダーによって使用されるユーザー名を含みます。後者の動作は、ブリッジ・センダーの接続ファクトリと宛先の構成によって決定されます。
WebLogic JMSのWLMessageProducer.forward()
拡張を使用すると、受信したメッセージのJMSXUserID
を転送可能です。
注意: 9.0より前のWebLogic JMSクライアントの |
接続ファクトリまたは宛先のJMSXUserID
プロパティの設定手順については、管理コンソール・オンライン・ヘルプの以下のトピックを参照してください。
アプリケーションを最大限に活用する方法については、『Oracle WebLogic Serverのパフォーマンスのチューニング』のWebLogic JMSのチューニングに関する項のWebLogic JMSで利用できるパフォーマンス・チューニング機能を実装します。