Sun Java System Message Queue 3.7 UR1 管理ガイド

パフォーマンスを改善するための設定の調整

次の節では、設定の調整がどのようにパフォーマンスに影響するかを説明します。

システムの調整

次の節では、オペレーティングシステム、JVM、および通信プロトコルで実行できる調整について説明します。

Solaris での調整: CPU 使用率、ページング/スワッピング/ディスク I/O

オペレーティングシステムの調整については、システムのマニュアルを参照してください。

Java 仮想マシン (JVM) の調整

デフォルトでは、ブローカは 192M バイトの JVM ヒープサイズを使用します。通常、大量のメッセージ負荷がある場合はこのサイズでは小さ過ぎるため、大きくする必要があります。

Java オブジェクトが使用する JVM のヒープ容量を使い果たしそうになると、ブローカは、フロー制御やメッセージスワップなどのさまざまな技術を使用して、メモリーを解放します。極端な状況のもとでは、メモリーを解放し、メッセージの流入を減少させるために、クライアント接続を閉じることもあります。このような状況を避けるため、最大 JVM ヒープ容量を十分に高く設定するようお勧めします。

ただし、Java の最大ヒープ容量がシステムの物理メモリーに対して高くしすぎた場合、ブローカは Java ヒープ容量を増加し続け、システム全体のメモリーを使い果たしてしまうことがあります。これは、パフォーマンスの低下、予期しないブローカのクラッシュにつながり、そのシステムで実行されているほかのアプリケーションやサービスの動作にも影響を与える場合があります。一般に、オペレーティングシステムとそのほかのアプリケーションをマシン上で実行させるために十分な物理メモリーを使用させる必要があります。

一般に、通常時とピーク時のシステムメモリーフットプリントを評価して、十分なパフォーマンスを得られて、しかもシステムメモリーに問題を生じさせるほどではない大きさに Java ヒープサイズを設定するのが良い方法です。

ブローカの最小ヒープサイズと最大ヒープサイズを変更するには、ブローカの起動時に -vmargs コマンド行オプションを使用します。たとえば、次のように指定します。

/usr/bin/imqbrokerd -vmargs "-Xms256m -Xmx1024m"

このコマンドは、起動時の Java ヒープサイズを 256M バイトに、最大 Java ヒープサイズを 1G バイトに設定します。

どのような場合でも、ブローカのログファイルを確認するか、imqcmd metrics bkr -m cxn コマンドを使用して設定を検証します。

トランスポートプロトコルの調整

アプリケーションのニーズを満たすプロトコルが選択されたら、選択されたプロトコルに基づいて調整を加えることでパフォーマンスを改善できます。

プロトコルのパフォーマンスは、次の 3 つのブローカプロパティーを使用して修正できます。

TCP と SSL プロトコルの場合、これらのプロパティーがクライアントとブローカ間のメッセージ配信の速度に影響します。HTTP プロトコルと HTTPS プロトコルの場合は、これらのプロパティーが、Web サーバー上で実行している Message Queue トンネルサーブレットとブローカ間のメッセージ配信の速度に影響します。HTTP/HTTPS プロトコルの場合、そのほかにもパフォーマンスに影響することのあるプロパティーがあります (「HTTP/HTTPS の調整」を参照)。

プロトコルを調整するためのプロパティーについては、次の節で説明します。

nodelay

nodelay プロパティーは、特定のプロトコルの Nagle のアルゴリズム、つまり TCP/IP 上の TCP_NODELAY ソケットレベルのオプションの値に影響します。Nagle のアルゴリズムは、広域ネットワーク (WAN) などの低速接続を使用しているシステム上で TCP パフォーマンスを改善するために使用されます。

このアルゴリズムが使用されている場合、TCP は、データをサイズの大きいパケットにバンドルすることで、複数の小さいデータの塊がリモートシステムへ送信されるのを防ぎます。ソケットに書き込まれたデータが必要なバッファーサイズを満たしていない場合、プロトコルは、バッファーが満たされるか、一定の遅延時間が経過するまで、パケットの送信を遅らせます。バッファーがいっぱいになるか、タイムアウトが発生すると、パケットが送信されます。

大半のメッセージングアプリケーションでは、パケットの送信に遅延がない、つまり Nagle のアルゴリズムが無効な場合にパフォーマンスは最適となります。これは、クライアントとブローカ間の大半の対話が、要求/ 応答型の対話だからです。つまり、クライアントはデータのパケットをブローカへ送信し、その応答を待ちます。たとえば、典型的な対話には次のものがあります。

これらの対話では、大半のパケットがバッファーサイズより小さいサイズです。つまり、Nagle のアルゴリズムが使用されている場合は、ブローカは数ミリ秒遅れて、コンシューマに応答を送信します。

ただし、Nagle のアルゴリズムは、接続が低速でブローカの応答が必要ない状況で、パフォーマンスを改善することができます。これは、クライアントが持続性のないメッセージを送信する場合や、クライアント通知がブローカによって確認されない場合 (DUPS_OK_ACKNOWLEDGE セッション) です。

inbufsz/outbufsz

inbufsz プロパティーは、ソケットからのデータを読み取る入力ストリームのバッファーサイズを設定します。同様に、outbufsz は、ブローカがデータをソケットに書き込むために使用する出力ストリームのバッファーサイズを設定します。

一般に、どちらのパラメータも受信パケットまたは送信パケットの平均サイズより多少大きい値に設定する必要があります。経験上、これらのプロパティーはパケットの平均サイズに 1K バイトを足した値 (K バイト単位で四捨五入) に設定すると良いでしょう。たとえば、本文が 1K バイトのパケットをブローカで受信している場合、パケット全体のサイズ (メッセージ本文 + ヘッダー + プロパティー) は約 1200 バイトです。inbufsz を 2K バイト (2048 バイト) にすると、妥当なパフォーマンスが得られます。inbufsz または outbufsz をそのサイズより大きくすると多少パフォーマンスは改善しますが、接続ごとに必要なメモリーも増えます。

HTTP/HTTPS の調整

前の 2 つの節で説明した一般的なプロパティーに加え、HTTP/HTTPS のパフォーマンスは、Message Queue トンネルサーブレットをホスティングする Web サーバーへの HTTP 要求をクライアントが作成する速度によっても制限されます。

Web サーバーは、シングルソケットで複数の要求を処理するように最適化する必要があります。JDK バージョン 1.4 以降では、Web サーバーが複数の HTTP 要求を処理する際に使用するリソースを最小限にするために、Web サーバーへの HTTP 接続 (Web サーバーへのソケット) は開かれたままになっています。JDK 1.4 を使用しているクライアントアプリケーションのパフォーマンスが JDK の旧リリースで稼働している同じアプリケーションより低速な場合は、パフォーマンスを改善するために Web サーバーのキープアライブ設定パラメータの調整が必要となることがあります。

このような Web サーバーの調整に加え、クライアントが Web サーバーをポーリングする頻度を調整することもできます。HTTP は要求ベースのプロトコルです。つまり、HTTP ベースのプロトコルを使用しているクライアントは、メッセージが待機中かどうかを判断するたに Web サーバーを定期的に確認する必要があります。imq.httpjms.http.pullPeriod ブローカプロパティーとそれに対応する imq.httpsjms.https.pullPeriod プロパティーは、Message Queue クライアントランタイムが Web サーバーをポーリングする頻度を指定します。

pullPeriod 値が -1 (デフォルト値) の場合、クライアントランタイムは直前の要求が戻るとすぐにサーバーをポーリングし、個々のクライアントのパフォーマンスを最大化します。その結果、各クライアント接続が Web サーバー内の要求スレッドを 1 つずつ占有するため、Web サーバーのリソースにかなりの負荷がかかる場合があります。

pullPeriod 値が正の数字である場合、クライアントランタイムは要求を定期的に Web サーバーへ送信し、データが保留されているかどうかを確認します。この場合、クライアントは Web サーバーの要求スレッドを占有しません。したがって、多数のクライアントが Web サーバーを使用している場合は、pullPeriod を正の値に設定することで Web サーバーのリソースを節約できます。

ファイルベースの持続ストアの調整

ファイルベースの持続ストアの調整については、「持続サービス」を参照してください。

ブローカの調整

次の節では、パフォーマンスを改善するためにブローカのプロパティーに対して実行できる調整について説明します。

メモリー管理: 負荷のある状態でブローカの安定性を高める

メモリー管理は、送信先単位で、またはシステム全体に対してすべての送信先を一括で、設定できます。

物理的送信先の制限の使い方

物理的送信先の制限については、第 6 章「物理的送信先の管理」を参照してください。

システム全体の制限の使い方

メッセージプロデューサの処理速度がメッセージコンシューマの処理速度を上回る傾向がある場合には、メッセージをブローカに蓄積できます。ブローカにはメモリーが不足した場合に、プロデューサの処理速度を低下させ、アクティブメモリーからメッセージをスワップさせるメカニズムが組み込まれていますが、ブローカが保持可能なメッセージの合計数とメッセージのバイトの合計数に厳密な制限を設定した方が賢明です。

imq.system.max_count ブローカプロパティーと imq.system.max_size ブローカプロパティーを設定して、これらの制限を制御します。

たとえば、次のように指定します。

imq.system.max_count=5000

上記で定義された値は、ブローカが未配信/未通知のメッセージを最大 5000 までしか保持しないことを示しています。それ以上のメッセージが送信されると、メッセージはブローカによって拒否されます。メッセージが持続的な場合は、プロデューサがメッセージを送信しようとすると例外を受け取ります。メッセージが持続的でない場合は、ブローカは暗黙のうちにメッセージを廃棄します。

メッセージの送信時に例外が戻った場合、クライアントは一時停止してから、送信を再試行します。この例外は、メッセージ受信に関するブローカの障害が原因ではありません。発生した例外は、送信側のクライアントだけが検出します。

複数のコンシューマキューのパフォーマンス

複数のキューコンシューマがキュー送信先でメッセージを処理する能率は、次の設定可能キュー送信先属性によって決まります。

最適なメッセージスループットを実現するには、十分な数のアクティブコンシューマがキューでのメッセージの生成に遅れずに対応し、消費する割合を最大にするような方法で、キュー内のメッセージをルーティングし、アクティブコンシューマへ配信しなければなりません。メッセージ配信を複数のコンシューマに分散させる一般的なメカニズムについては、『 Sun Java SystemTM Message Queue 技術の概要』で説明されています。

メッセージがキューに蓄積している場合、メッセージ負荷を処理するアクティブコンシューマの数が不十分であることが考えられます。また、複数のメッセージがバッチサイズでコンシューマに配信されるため、メッセージがコンシューマ上でバックアップされていることも考えられます。たとえば、バッチサイズ (consumerFlowLimit) が大き過ぎる場合は、あるコンシューマがキュー内のすべてのメッセージを受信し、そのほかのコンシューマは何も受信していないことがあります。コンシューマが非常に高速であれば、これは問題にはなりません。

ただし、コンシューマが比較的低速で、メッセージをコンシューマに均等に分散させたい場合は、バッチサイズを小さくする必要があります。バッチサイズが小さいほど、メッセージをコンシューマへ配信するのに必要なオーバーヘッドは増加します。それでも、低速なコンシューマの場合は、一般に、小さいバッチサイズを使用した方がパフォーマンスは向上します。

クライアントランタイムのメッセージフローの調整

この節では、パフォーマンスに影響するフロー制御の動作について説明します (「クライアントランタイムの設定」を参照)。これらの動作は、接続ファクトリの管理対象オブジェクトの属性として設定されます。接続ファクトリ属性の設定方法については、第 8 章「管理対象オブジェクトの管理」を参照してください。

メッセージフロー測定

クライアントによって送受信されるメッセージ (ペイロードメッセージ) と Message Queue 制御メッセージは、同じクライアントとブローカ間の接続を使って伝送されます。ブローカ通知などの制御メッセージの配信における遅延は、ペイロードメッセージの配信によって制御メッセージが保留された場合の結果として生じます。このようなネットワークの輻輳を防止するため、Message Queue は接続全体のペイロードメッセージのフローを測定します。

ペイロードメッセージは、接続ファクトリ属性 imqConnectionFlowCount の指定に従い、設定した数のみが配信されるようにバッチされます。バッチが配信されたあと、ペイロードメッセージの配信は中断され、保留中の制御メッセージのみが配信されます。ペイロードメッセージの追加のバッチが配信されるときも、このサイクルが繰り返され、保留中の制御メッセージが続きます。

クライアントが、ブローカからの多数の応答を必要とする操作を実行している場合、たとえば、クライアントが CLIENT_ACKNOWLEDGE または AUTO_ACKNOWLEDGE モード、持続メッセージ、トランザクション、キューブラウザを使用している場合や、クライアントがコンシューマを追加または削除している場合などには、imqConnectionFlowCount の値を小さいままにしておく必要があります。一方、クライアントが DUPS_OK_ACKNOWLEDGE モードを使用しており、接続上に単純なコンシューマしかいない場合は、パフォーマンスを犠牲にすることなく imqConnectionFlowCount の値を増やすことができます。

メッセージフロー制限

Message Queue クライアントランタイムがメモリーなどのローカルリソースの上限に達する前に処理可能なペイロードメッセージの数には制限があります。この数に達すると、パフォーマンスに悪影響が出ます。したがって、Message Queue では、コンシューマあたりのメッセージ数または接続あたりのメッセージ数を制限できます。この制限は、接続を介して配信し、クライアントランタイムにバッファリングし、消費を待機できるメッセージの数を示しています。

コンシューマフローの制限

クライアントランタイムへ配信されたペイロードメッセージの数が、いずれかのコンシューマの imqConsumerFlowLimit 値を超えた場合、そのコンシューマへのメッセージ配信は停止します。そのコンシューマの消費されないメッセージの数が、 imqConsumerFlowThreshold で設定された値を下回った場合にだけ、配信処理が再開されます。

次の例は、これらの制限の使い方を示しています。トピックコンシューマのデフォルト設定値を前提としています。

imqConsumerFlowLimit=1000
imqConsumerFlowThreshold=50

コンシューマが作成され、1000 のメッセージがあれば、ブローカはこれらのメッセージを最初のバッチとしてコンシューマに配信します。このとき一時停止はありません。1000 メッセージの送信後、ブローカはクライアントランタイムが追加のメッセージを要求するまで、配信を停止します。アプリケーションがこれらのメッセージを処理するまで、クライアントランタイムはそれらを保持します。その後、クライアントランタイムは、アプリケーションがメッセージバッファー容量の 50% (imqConsumerFlowThreshold) つまり 500 メッセージ以上を消費するのを待ってから、ブローカに次のバッチを送信するように要求します。

同じ状況で、しきい値が 10% の場合、クライアントランタイムは、アプリケーションが少なくとも 900 メッセージを消費してから、次のバッチを要求します。

次のバッチサイズの計算方法:

imqConsumerFlowLimit - (現在、バッファーに保留中のメッセージ数
)

そのため、imqConsumerFlowThreshold が 50% の場合、次のバッチサイズは、アプリケーションがメッセージを処理する速度に応じて 500 〜 1000 の間になります。

imqConsumerFlowThreshold がかなり高く (100% 近くに) 設定された場合、ブローカは比較的小さいサイズのバッチを送信するため、メッセージのスループットは低下することがあります。値が低過ぎる (0% に近い) 場合は、クライアントは次のセットを配信する前に残りのバッファリングされたメッセージの処理を完了してしまい、やはりメッセージスループットを低下させることがあります。一般に、パフォーマンスや信頼性に特定の問題がないかぎり、imqConsumerFlowThreshold 属性のデフォルト値を変更する必要はありません。

コンシューマベースのフロー制御、特に、imqConsumerFlowLimit は、クライアントランタイム内のメモリーを管理する最適な手段です。一般に、クライアントアプリケーションに応じて、接続でサポートする必要のあるコンシューマの数、メッセージのサイズ、クライアントランタイムで使用可能なメモリー総量がわかります。

接続フローの制限

一部のクライアントアプリケーションでは、エンドユーザーの選択によって、コンシューマの数が不確定な場合があります。そのような場合は、引き続き、接続レベルのフロー制限を使用してメモリーを管理できます。

接続レベルのフロー制御は、接続上のすべてのコンシューマについてバッファリングされたメッセージの合計数を制限します。この数が imqConnectionFlowLimit の値を超えると、合計数が接続の制限を下回るまで、接続経由のメッセージの配信は停止します。imqConnectionFlowLimit 属性は、imqConnectionFlowLimitEnabledtrue に設定した場合にだけ使用できます。

1 つのセッションでキューに入るメッセージの数は、そのセッションを使用するメッセージコンシューマの数と、各コンシューマのメッセージ負荷によって決まります。クライアント側のメッセージの生成またはメッセージの消費に遅延が発生する場合は、通常は、アプリケーションを再設計し、より多くのセッションにメッセージプロデューサとメッセージコンシューマを分散し、またはより多くの接続にセッションを分散してパフォーマンスを改善できます。