アプリケーション設計の決定は、メッセージングのパフォーマンス全体に大きく影響することがあります。
パフォーマンスに影響するもっとも重要な要因は、メッセージ配信の信頼性に影響を及ぼす要因です。これには、次のものがあります。
そのほかに、パフォーマンスに影響するアプリケーション設計の要因には、次のものがあります。
以降の節では、これらの各要因がメッセージングパフォーマンスに及ぼす影響について説明します。原則として、パフォーマンスと信頼性は相反しています。つまり、信頼性が高くなるとパフォーマンスは低下します。
表 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 などのより複雑なタイプほどパフォーマンスは低下します。データのシリアライズとデシリアライズがパフォーマンスを低下させます。パフォーマンスは、データがどの程度単純か、またはどの程度複雑かによって異なります。