Oracle® Fusion Middleware Oracle WebLogic Server JMS プログラマーズ ガイド 11g リリース 1 (10.3.1) B55536-01 |
|
戻る |
次へ |
以下の節では、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 Fusion Middleware Oracle WebLogic Server パフォーマンス チューニング ガイド』の「メッセージの圧縮」を参照してください。
ユーザ定義のメッセージ プロパティの代わりに、標準の JMS メッセージ ヘッダ フィールドや、メッセージ データのメッセージ本文を使用することも検討してください。メッセージ プロパティは、シリアライズに余分な負荷がかかり、アクセスにおいても標準の JMS メッセージ ヘッダ フィールドより大きな負荷がかかります。
また、プロパティ フィールドやヘッダ フィールドに大量のデータを組み込むことも避けてください。ページングが有効になっている場合でも、ページングされるのはメッセージの本文のみです。したがって、アプリケーションにユーザ定義のメッセージ プロパティが定義されている場合は、大きな文字列プロパティを使用しないようにしてください。
詳細については、「メッセージ ヘッダ フィールド」および「メッセージ プロパティ フィールド」を参照してください。
メッセージの処理を厳格に順序付けする場合は、再配信の順序付け機能ではなく、メッセージ順序単位機能を使用することをお勧めします。再配信の順序付けに比べ、メッセージ順序単位には以下の利点があります。
コンフィグレーションが容易。
非同期レシーバのカスタム接続ファクトリが必要ない。たとえば、メッセージ駆動型 Bean (MDB) を使用する場合は、MessagingMaximum
を 1 に設定します。
分散送り先を使用する場合のコンフィグレーションが単純。
処理遅延の間もメッセージの順序が維持される。
トランザクションのロールバックやセッションの回復の間もメッセージの順序が維持される。
再配信の順序付けを使用しているアプリケーションは、メッセージ順序単位を使用するようにアップグレードすることをお勧めします。詳細については、「メッセージ順序単位の使用」を参照してください。
アプリケーションの設計を始めるときには、トピックとキューのどちらを使用したほうがよいかを即座に判断できない場合もあります。一般的には、以下の条件のいずれかが満たされる場合にのみトピックを選択します。
同じメッセージを、複数のコンシューマにレプリケートする必要がある。
メッセージを選択するアクティブなコンシューマがない場合に、そのメッセージを破棄する必要がある。
たくさんのサブスクライバがあり、それぞれにユニークなセレクタがある。
恒久サブスクライバが 1 つのみのトピックは、セマンティクスの面ではキューに似ています。相違点は以下のとおりです。
恒久サブスクライバのトピック セレクタを変更した場合、サブスクリプション内の以前のメッセージがすべて削除されるが、コンシューマのキュー セレクタを削除してもキュー内のメッセージは削除されない。
キューの場合はメッセージを複数のコンシューマにラウンドロビン方式で配信できるが、トピック サブスクライバのコンシューマは 1 つに制限されている。
JMS キューとトピックのコンフィグレーションの詳細については、『Oracle Fusion Middleware 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 インスタンス上で使用できるデフォルトの永続ストアを使用することを意味する。
ストアがコンフィグレーションされている場合はオーバーライドがないことを意味する。
恒久サブスクライバのみ :
WebLogic リリース 7.0 以降では、サブスクライバがない場合や、トピックに非恒久サブスクライバしかない場合は、メッセージが非永続に格下げされる (非恒久サブスクライバは JMS サーバの稼動中しか存在しないため、メッセージを永続化する理由がない)。
一時的な送り先 :
一時的な送り先はそれらをホストする JMS サーバの稼動中しか存在しないため、メッセージを永続化する理由がない。WebLogic JMS では、一時的な送り先のすべてのメッセージが自動的に非永続になります。
恒久サブスクライバが非永続メッセージしか受信しない場合でも、その JMS サーバには永続ストアをコンフィグレーションする必要があります。恒久サブスクリプションは、JMS 仕様の要件に従って、サーバの再起動後も継続するように永続化されます。
通常は送信よりも受信のほうに時間がかかるため、複数のメッセージを受信してまとめて確認応答できるようになるまで確認応答を延期して、受信に関わるオーバーヘッドを軽減することを検討してください。トランザクションを使用している場合は、「確認応答」を「コミット」と読み替えてください。
ただし、非恒久サブスクリプションの場合はすでに内部的に最適化されているため、確認応答を延期してもパフォーマンスはあまり向上しません。
非同期リスナには、確認応答の延期を実装できない場合があります。メッセージ 10 個ごとに確認応答する非同期リスナが 5 個のメッセージしか受信しなかった場合、最後のいくつかのメッセージが確認応答されない可能性があります。考えられる解決策としては、onMessage()
コールバック内からの同期非ブロッキング受信を非同期コンシューマにポストさせて、後続のメッセージを受信します。別の解決策としては、wake up リスナがトリガされたときに、リスナの送り先にメッセージを送信するタイマーが開始されるようにします。このメッセージが正しいリスナに確実に転送されれば、リスナの送り先が起動してまだ確認応答されていない未処理の作業を完了します。
WebLogic Server 7.0 以降では、トランザクション非対応の非恒久トピック サブスクライバがメッセージのローカル コピーをクライアントサイドで格納するように最適化されており、これによって確認応答の発行に伴うネットワーク オーバーヘッドを軽減しています。この最適化によってパフォーマンスが 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.0.2 仕様では、サブスクライバの準備が整っていない場合に非恒久トピック メッセージを破棄 (削除) することが明確に許可されています。WebLogic JMS では、非恒久トピック サブスクリプション用に、JMS 1.0.2 仕様で必須とされているレベルよりも高いレベルの QOS がデフォルトで提供されます。
NO_ACKNOWLEDGE 配信モードでは、サーバからコンシューマにメッセージが送信されますが、確認応答は呼び出されません。代わりに、サーバはメッセージを事前に確認応答します。この確認応答モードでは、メッセージがすでに確認応答されているため、回復を呼び出しても機能しません。このモードを使用すると、確認応答のための追加のネットワーク呼び出しによるオーバーヘッドは軽減されますが、サーバ、ネットワーク、またはクライアントで障害が発生した場合にメッセージが消失するおそれがあります。
注意 : このような状況で非同期クライアントがclose() を呼び出すと、非同期パイプライン内のすべてのメッセージが消失します。 |
NO_ACKNOWLEDGE QOS を使用する非同期コンシューマでは、クラッシュ時に消失するメッセージの数を抑えるために、メッセージ パイプラインのサイズを小さくすることも検討してください。
JMS 仕様 (http://java.sun.com/products/jms/docs.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 Interop の動作は未定義です。 |
接続ファクトリまたは送り先の JMSXUserID
プロパティの設定手順については、Administration Console オンライン ヘルプの以下のトピックを参照してください。