メッセージの遅延とメッセージのスループットは、2 つの主要なパフォーマンスの評価基準です。これらは一般に、標準的なメッセージがメッセージ配信プロセスの各手順を完了するまでに要する時間に依存します。メッセージを持続的で信頼できる方法で配信する場合の各手順は次のとおりです。各手順を以下で図示します。
メッセージはプロデューシングクライアントからブローカへ配信されます。
ブローカはメッセージの内容を読み取ります。
メッセージは、信頼性を維持するために持続ストレージに配置されます。
ブローカは、信頼性を維持するためにメッセージの受信確認を発行します。
ブローカは、メッセージのルーティングを決定します。
ブローカはメッセージを書き込みます。
メッセージはブローカからコンシューミングクライアントへ配信されます。
コンシューミングクライアントは、信頼性を維持するためにメッセージの受信確認を発行します。
ブローカは、信頼性を維持するために、クライアントの通知を処理します。
ブローカは、クライアントの通知が処理されたことを通知します。
これらの手順は順次実行されるため、プロデューシングクライアントからコンシューミングクライアントへメッセージを配信する際には、どの手順もボトルネックとなる恐れがあります。これらの手順の大半は、メッセージングシステムの物理的な特性に依存しています。物理的な特性には、ネットワーク帯域幅、コンピュータの処理速度、メッセージサービスのアーキテクチャーなどが含まれます。ただし、一部の手順は、メッセージングアプリケーションの特性と必要とされる信頼性のレベルにも依存しています。
次の節では、アプリケーション設計の要因とメッセージングシステムの要因の両方がパフォーマンスに及ぼす影響について説明します。アプリケーション設計の要因とメッセージングシステムの要因はメッセージの配信に密接に関係しますが、各カテゴリは個別に考慮します。
アプリケーション設計の決定は、メッセージングのパフォーマンス全体に大きく影響することがあります。
パフォーマンスに影響するもっとも重要な要因は、メッセージ配信の信頼性に影響を及ぼす要因です。これには、次のものがあります。
そのほかに、パフォーマンスに影響するアプリケーション設計の要因には、次のものがあります。
以降の節では、これらの各要因がメッセージングパフォーマンスに及ぼす影響について説明します。原則として、パフォーマンスと信頼性は相反しています。つまり、信頼性が高くなるとパフォーマンスは低下します。
表 11–1 は、さまざまなアプリケーション設計の要因が一般にどのようにメッセージングパフォーマンスに影響するかを示しています。表には、信頼性が高くパフォーマンスが低いシナリオと、パフォーマンスが高く信頼性の低いシナリオの 2 つのシナリオと、それぞれを特徴付ける主要なアプリケーション設計の要因を示します。これらの極端なシナリオの間には、信頼性とパフォーマンスの両方に影響する、多数の選択肢と兼ね合いがあります。
表 11–1 高信頼性シナリオと高パフォーマンスシナリオの比較
アプリケーション設計の要因 |
高信頼性、低パフォーマンスシナリオ |
高パフォーマンス、低信頼性シナリオ |
---|---|---|
配信モード |
持続メッセージ |
持続性のないメッセージ |
トランザクションの使用 |
処理済みセッション |
トランザクションなし |
通知モード |
AUTO_ACKNOWLEDGE または CLIENT_ACKNOWLEDGE |
DUPS_OK_ACKNOWLEDGE |
永続的/永続的でないサブスクリプション |
永続サブスクリプション |
永続的でないサブスクリプション |
セレクタの使用 |
メッセージのフィルタリング |
メッセージのフィルタリングなし |
メッセージのサイズ |
多数の小さいメッセージ |
少数の大きいメッセージ |
メッセージ本文のタイプ |
複合本文タイプ |
単純本文タイプ |
持続メッセージはブローカの障害時にもメッセージの配信を保証します。すべての対象のコンシューマが、メッセージを消費したことを通知するまで、ブローカはメッセージを持続ストアに格納します。
持続メッセージのブローカの処理速度は、次の理由から、持続性のないメッセージの場合より低速です。
ブローカに障害が生じても持続メッセージが失われないように、ブローカは信頼できる方法で持続メッセージを格納する必要があります。
ブローカは受信した持続メッセージごとに、受信確認をする必要があります。メッセージを生成するメソッドが例外を返さなければ、ブローカへの配信は保証されます。
クライアントの通知モードによっては、クライアントからの持続メッセージの受信通知が消費されたことを、ブローカが確認しなければならない場合があります。
キューへ配信した場合と、永続サブスクライバを使用しているトピックへ配信した場合の両方で、パフォーマンスは、持続性のないメッセージが 40% 上回りました。これらは、10K バイトのメッセージと AUTO_ACKNOWLEDGE モードを使用した場合の結果です。
トランザクションとは、処理済みセッションで生成されたすべてのメッセージと処理済みセッションで消費されたすべてのメッセージが、一体として処理されるか、または一体として処理されない、つまりロールバックされることを保証するものです。
Message Queue では、ローカルと分散の両方のトランザクションがサポートされます。
処理済みセッションでのメッセージの生成または通知の処理速度は、次の理由から、処理済みでないセッションの場合より低速です。
生成されたメッセージごとに追加情報を格納する必要があります。
状況によっては、通常は格納されないトランザクション内のメッセージを格納する場合があります。たとえば、サブスクリプションを使用しないトピック送信先へ配信された持続メッセージは、通常削除されますが、トランザクションの開始時にサブスクリプションに関する情報が使用できなくなります。
トランザクションでのメッセージの消費と通知に関する情報は、トランザクションがコミットされた時点で格納し処理する必要があります。
JMS メッセージの配信の信頼性を保証する手段の 1 つは、Message Queue ブローカによってクライアントへ配信されたメッセージの消費をクライアントに通知するという方法です。
クライアントがメッセージを通知することなくセッションが閉じられた場合や、通知が処理される前にブローカに障害が生じた場合には、ブローカはメッセージを再配信して JMSRedelivered フラグをセットします。
処理済みでないセッションの場合、クライアントは、それぞれ固有のパフォーマンス特性をもつ 3 つの通知モードの中から 1 つを選択できます。
AUTO_ACKNOWLEDGE。コンシューマがメッセージを処理したあと、システムは自動的にメッセージを通知します。このモードでは、プロバイダで障害が生じたあとは、多くても 1 つのメッセージの再配信を保証するだけです。
CLIENT_ACKNOWLEDGE。アプリケーションは、メッセージが通知されるポイントを制御します。直前の通知以降にそのセッションで処理されたすべてのメッセージが通知されます。一連の通知の処理中にブローカに障害が生じた場合は、そのグループ内の複数のメッセージが再配信されることがあります。
DUPS_OK_ACKNOWLEDGE。このモードは、時間をかけてメッセージを通知するようにシステムに指示します。プロバイダに障害が生じたあとでも、複数のメッセージを再配信できます。
CLIENT_ACKNOWLEDGE モードの使い方はトランザクションの使い方に似ています。ただし、処理中にプロバイダに障害が生じた場合に、すべての通知が一括して処理されることを保証していない点を除きます。
次の理由により、通知モードはパフォーマンスに影響します。
AUTO_ACKNOWLEDGE モードと CLIENT_ACKNOWLEDGE モードでは、ブローカとクライアント間で特別な制御メッセージが必要です。追加の制御メッセージは、処理オーバーヘッドを高め、JMS ペイロードメッセージに干渉して処理遅延を引き起こすことがあります。
AUTO_ACKNOWLEDGE モードと CLIENT_ACKNOWLEDGE モードでは、ブローカがクライアントの通知を処理したことを確認するまで、クライアントは待機する必要があります。その後、クライアントは追加メッセージを消費できるようになります。このブローカの確認によって、何らかの理由でブローカがこれらのメッセージを再配信しないように保証します。
Message Queue 持続ストアは、コンシューマが受信したすべての持続メッセージに関する通知情報を使って更新する必要があります。そのため、パフォーマンスは低下します。
トピック送信先へのサブスクライバは、永続サブスクリプションをもつものと、永続的でないサブスクリプションをもつものの 2 つのカテゴリに分かれます。
永続サブスクリプションでは、次の理由により、信頼性が高まりますが、スループットが遅くなります。
Message Queue メッセージサービスは、ブローカに障害が生じた場合でも回復後にリストを使用できるように、各永続サブスクリプションに割り当てられたメッセージのリストを持続的に格納する必要があります。
ブローカに障害が生じた場合でも、回復後に、対応するコンシューマがアクティブになったときに、メッセージを引き続き配信できるように、永続サブスクリプションの持続メッセージは持続ストアに格納されます。対照的に、永続的でないサブスクリプションの持続メッセージは持続ストアには格納されません。したがって、ブローカに障害が生じると、対応するコンシューマ接続は失われ、メッセージは配信されません。
10K バイトの持続メッセージと持続性のないメッセージの 2 とおりのケースで、永続サブスクライバと永続的でないサブスクライバのパフォーマンスを比較しました。どちらの場合も AUTO_ACKNOWLEDGE 通知モードを使用しています。その結果、持続メッセージの場合にのみパフォーマンスに影響が見られ、永続サブスクライバの方が約 30% 低速でした。
アプリケーション開発者は、通常、特定のコンシューマへの一連のメッセージを対象にしています。それは、一意の物理的送信先への一連のメッセージごとを対象とするか、単一の物理的送信先を使用しコンシューマごとに複数のセレクタを登録することで実現できます。
セレクタは文字列であり、この文字列に一致するプロパティー値を持ったメッセージだけを特定のコンシューマに配信します。たとえば、セレクタ NumberOfOrders >1 は、NumberOfOrders プロパティー値が 2 以上のメッセージだけを配信します。
セレクタを使用してコンシューマを作成すると、各メッセージを取り扱うために追加処理が必要となり、複数の物理的送信先を使用する場合に比べ、パフォーマンスは低下します。以降のメッセージを比較する際にも構文解析できるセレクタを使用する必要があります。さらに、各メッセージがルーティングされるたびに、各メッセージのメッセージプロパティーを読み取り、比較する必要があります。ただし、セレクタを使用すると、メッセージングアプリケーションの柔軟性が向上します。
メッセージのサイズはパフォーマンスに影響します。プロデューシングクライアントからブローカへ、さらにブローカからコンシューミングクライアントへは、より多くのデータを渡す必要があり、持続メッセージの場合はサイズの大きいメッセージを格納する必要があるからです。
ただし、複数のサイズの小さいメッセージを 1 つのメッセージにまとめることで、個々のメッセージの転送と処理を最小限に抑え、パフォーマンス全体を向上させることができます。この場合、個々のメッセージの状態に関する情報は失われてしまいます。
AUTO_ACKNOWLEDGE 通知モードを使用して、キュー送信先へ 1K、10K、および 100K バイトのメッセージを送信した場合のスループットを、1 秒あたりの K バイト数で比較したテストにより、持続性のないメッセージングの方が、1K バイトのメッセージで約 50%、10K バイトのメッセージで約 20%、および 100K バイトのメッセージで約 5% 高速であることが分かりました。メッセージのサイズは、持続メッセージと持続性のないメッセージの両方のパフォーマンスに大きく影響します。100K バイトのメッセージは 10K バイトのメッセージよりも 10 倍高速であり、10K バイトのメッセージは 1K バイトのメッセージよりも 5 倍高速です。
JMS がサポートするメッセージ本文のタイプ 5 種類の概要を複雑な順に次に示します。
BytesMessage は、一連のバイトデータを含み、形式はアプリケーションによって決まります。
TextMessage は、単純な Java 文字列です。
StreamMessage は、Java プリミティブ値によるストリームを含みます。
MapMessage には、一連の名前と値のペアが含まれます。
ObjectMessage には、Java のシリアライズされたオブジェクトが含まれます。
一般に、メッセージのタイプはアプリケーションのニーズによって決定され、MapMessage や ObjectMessage などのより複雑なタイプほどパフォーマンスは低下します。データのシリアライズとデシリアライズがパフォーマンスを低下させます。パフォーマンスは、データがどの程度単純か、またはどの程度複雑かによって異なります。
メッセージングアプリケーションのパフォーマンスは、アプリケーション設計だけでなく、メッセージのルーティングと配信を実行するメッセージサービスによっても影響を受けます。
次の節では、パフォーマンスに影響することのあるさまざまなメッセージサービスの要因について説明します。これらの要因の影響を理解しておくことは、メッセージサービスの内容を変更したり、配置済みのアプリケーションで発生することのあるパフォーマンスボトルネックを診断し解決したりする上で重要となります。
Message Queue サービスのパフォーマンスに影響するもっとも重要な要因は、次のとおりです。
以降の節では、これらの各要因がメッセージングパフォーマンスに及ぼす影響について説明します。
Message Queue ブローカとクライアントアプリケーションのどちらの場合も、CPU の処理速度と使用可能なメモリーはメッセージサービスのパフォーマンスを決定する主要な要因となります。処理性能を強化して、多数のソフトウェア制限をなくす一方で、メモリーを追加して処理速度と能力を増加させることができます。ただし、一般に、単にハードウェアをアップグレードするだけでボトルネックを解消すると多額の費用がかかります。
同じハードウェアプラットフォームを前提とした場合でも、異なるオペレーティングシステムの効率によって、パフォーマンスも変わってきます。たとえば、オペレーティングシステムが採用しているスレッドモデルが、ブローカがサポート可能な同時接続数に大きく影響することがあります。一般に、すべてのハードウェアが同じであれば、Solaris は通常 Linux より高速で、Linux は Windows より高速です。
ブローカは、ホスト JVM 内で実行され、ホスト JVM によってサポートされる Java プロセスです。そのため、JVM 処理は、ブローカがメッセージをいかに早く効率良くルーティングし配信できるかを決定する重要な要因となります。
特に、JVM のメモリーリソースの管理が不可欠となる場合があります。増加し続けるメモリーの負荷に対応するには、JVM に十分なメモリーを割り当てる必要があります。さらに、JVM は定期的に未使用のメモリーを再利用します。このメモリー再利用がメッセージの処理を遅らせることがあります。JVM のメモリーヒープが大きくなるほど、メモリー再利用時に経験することのある、潜在する遅延も長くなります。
クライアントとブローカ間の接続の数と速度は、メッセージサービスが処理可能なメッセージ数とメッセージ配信速度に影響することがあります。
ブローカへのアクセスはすべて、接続経由で行われます。同時接続数の制限によって、ブローカを同時に使用できるプロデューシングクライアントまたはコンシューミングクライアントの数が左右されることがあります。
ブローカへの接続の数は、一般に、使用可能なスレッド数によって制限されます。Message Queue は、専用スレッドモデルまたは共有スレッドモデルのどちらかをサポートするように設定できます (「スレッドプール管理」を参照)。
専用スレッドモデルは、各接続が専用のスレッドを持つため非常に高速ですが、接続の数は使用可能なスレッド数によって制限されます。この場合、接続ごとに、入力スレッドと出力スレッドが 1 つずつ必要です。共有スレッドモデルには、接続数の制限はありませんが、多数の接続でスレッドを共有するため、オーバーヘッドが増え、スループットが悪化します。これは、多くの接続が使用中のとき特に顕著になります。
Message Queue ソフトウェアを使うと、クライアントは各種の低レベルのトランスポートプロトコルを使用してブローカと通信できます。Message Queue は、「接続サービス」で説明されている接続サービスとそれに対応するプロトコルをサポートします。
暗号化、ファイアウォールを介したアクセスなどのプロトコルは、アプリケーション要件に基づいて選択されますが、選択結果はパフォーマンス全体に影響を及ぼします。
テストでは、2 つのケースでの TCP と SSL のスループットを比較しました。2 つのケースとは、1K バイトの持続メッセージを、永続サブスクリプションとAUTO_ACKNOWLEDGE 通知モードを使用しているトピック送信先へ送信する高信頼性シナリオと、1K バイトの持続性のないメッセージを、永続サブスクリプションと DUPS_OK_ACKNOWLEDGE 通知モードを使用しているトピック送信先へ送信するハイパフォーマンスシナリオです。
通常、高信頼性ケースの方がプロトコルによる影響は少ないことが分かりました。これは、高信頼性のケースで必要な持続メッセージのためのオーバーヘッドの方が、プロトコルの速度より、スループットを制限する重要な要因となるからです。そのほかの特性は次のとおりです。
TCP は、ブローカと通信する最速の方法を提供します。
SSL は、メッセージの送信と受信に関しては、TCP より 50 〜 70% 低速です。持続メッセージの場合は 50%、持続性のないメッセージの場合は約 70% です。さらに、初期接続の確立は、SSL を使用した場合の方が低速で数秒かかります。これは、クライアントとブローカ、または HTTPS の場合は Web Server で、送信するデータの暗号化に使う非公開鍵の作成が必要なためです。低レベルの各 TCP パケットの暗号化と復号化に必要な追加処理によって、パフォーマンスの低下が引き起こされます。
HTTP は、TCP または SSL より低速です。HTTP ではクライアントとブローカ間のプロキシとして、Web サーバー上で実行しているサーブレットを使用します。パケットを HTTP 要求へカプセル化する必要がある点と、メッセージがブローカへ到達するには、クライアントからサーブレットへ、サーブレットからブローカへという 2 つの段階が必要である点から、パフォーマンスへのオーバーヘッドが発生します。
HTTPS は HTTP より低速です。これは、クライアントとサーブレット間、およびサーブレットとブローカ間でパケットを暗号化するためにオーバーヘッドが必須となるからです。
Message Queue メッセージサービスは、シングルブローカ、または複数の連結されたブローカインスタンスで構成されたクラスタとして実装できます。
ブローカに接続するクライアントの数や配信されるメッセージの数が増えると、ブローカは最終的に、ファイル記述子、スレッド、メモリーの制限などのリソースの限界を超えてしまいます。増え続ける負荷に対処するための 1 つの方法は、Message Queue メッセージサービスにブローカインスタンスを追加して、クライアントの接続とメッセージのルーティングおよび配信を複数のブローカに分散することです。
一般に、ブローカインスタンスの追加は、クライアント、特にメッセージプロデューシングクライアントがクラスタ間で均等に分散されている場合に最適に動作します。クラスタ内のブローカ間でのメッセージ配信にはオーバーヘッドが伴うため、接続数とメッセージ配信レートが制限されているクラスタでは、シングルブローカよりパフォーマンスが低くなります。
また、ブローカクラスタを使用してネットワークの帯域幅を最適化することもできます。たとえば、クラスタ内の一連のリモートブローカ間で、速度の遅い、長距離のネットワークリンクを使用する一方で、個々のブローカインスタンスへのクライアントの接続に、高速なリンクを使用することができます。
クラスタの詳細については、第 9 章「ブローカクラスタを使用した作業」を参照してください。
メッセージを処理するためにブローカに要求されるメッセージスループットは、ブローカがサポートするメッセージングアプリケーションの使用パターンによって異なります。ただし、ブローカでは、メモリーや CPU サイクルなどのリソースに制限があります。リソースの制限により、ブローカは、過負荷となり、無応答または不安定となるポイントに達してしまうことがあります。
Message Queue メッセージブローカには、メモリーリソースを管理し、ブローカのメモリー不足を防ぐためのメカニズムが組み込まれています。これらのメカニズムに含まれるのは、ブローカまたは個々の物理的送信先が保持できるメッセージ数またはメッセージのバイト数についての設定可能な制限と、物理的送信先の制限に達したときに起動できる一連の動作です。
これらの設定可能なメカニズムを使用して、システムが過負荷にならないように、メッセージの受信と送信のバランスを取ることができますが、これには注意深い監視と調整が必要です。これらのメカニズムは、オーバーヘッドを増加させ、メッセージのスループットを制限することがありますが、それでも動作の完全性を維持します。
Message Queue は、ファイルベースの持続モジュールと JDBC ベースの持続モジュールの両方をサポートしています。ファイルベースの持続モジュールでは、持続データを格納するために個別のファイルを使用します。JDBC ベースの持続では、JDBC™ (Java Database Connectivity) インタフェースを使用し、JDBC 互換のデータストアを必要とします。一般的に、ファイルベースの持続は、JDBC ベースの持続よりも高速です。ただし、JDBC 互換のストアによって提供される冗長性や管理機能を好むユーザーもいます。
ファイルベースの持続の場合は、持続的な操作によりメモリー内の状態とデータストアとを同期化するように指定することで、信頼性を高められます。この同期化は、システム破壊によるデータの損失をなくす上で役立ちますが、パフォーマンスが犠牲になります。
Message Queue クライアントランタイムは、クライアントアプリケーションに Message Queue メッセージサービスへのインタフェースを提供します。クライアントランタイムでは、物理的送信先にメッセージを送信し、物理的送信先からメッセージを受信する場合に、クライアントに必要なすべての処理をサポートします。クライアントランタイムは、接続ファクトリ属性値を使って設定可能で、パフォーマンスとメッセージスループットを向上させるように、接続フロー測定、コンシューマフローの制限、接続フロー制御などのプロパティーと動作を設定できます。これらの機能とそれを設定するために使用される属性の詳細は、「クライアントランタイムのメッセージフローの調整」を参照してください。