JMS Connector のトラブルシューティング - Mule 4

JMS 用 Anypoint Connector (Java Message Service Connector) のトラブルシューティングを行うには、冗長ログの有効化、肯定応答の問題のトラブルシューティング、JMS の停止したコンシュームメッセージのトラブルシューティング、バインディングモードの使用時の再デプロイメントエラーのトラブルシューティング、一般的なスローメッセージの解釈に関する情報を理解しておいてください。

冗長ログの有効化

場合によって、アプリケーションが失敗している理由がわからず、アプリケーションの JMS サーバーとのやりとりで何が行われているかについて理解を深める必要があることがあります。

詳細なログを収集する手順は、次のとおりです。

  • 設定ファイルを使用して、サーバー側のログレベルを引き上げます。

  • JMS Connector の冗長ログを有効にします。

    1. Anypoint Studio にアクセスし、​[Package Explorer]​ ビューに移動します。

    2. アプリケーションのプロジェクト名を開きます。

    3. src/main/resources​ パスフォルダーを開きます。

    4. フォルダー内の ​log4j2.xml​ ファイルを開きます。

    5. 次の行がすでに ​log4j2.xml​ ファイル内にある場合は、そのコメントを解除して有効にします。それ以外の場合、次の行を追加します。

          <AsyncLogger name=“org.mule.extensions.jms” level=“DEBUG”/>
          <AsyncLogger name=“org.mule.jms.commons” level=“DEBUG”/>

肯定応答の問題のトラブルシューティング

メッセージの肯定応答に関してアプリケーションの設定に矛盾が生じる理由はいくつか考えられます。 アプリケーションのセッション肯定応答は次のように設定できます。

  • IMMEDIATE

  • AUTO

  • MANUAL

  • DUPS_OK

セッション肯定応答を ​IMMEDIATE​ に設定すると、メッセージは受信されると直ちに肯定応答されます。​IMMEDIATE​ 肯定応答を ​Ack​ または ​Recovery session​ 操作と組み合わせないでください。

セッション肯定応答を ​AUTO​ に設定すると、イベントが完了したときに ​On New Message​ ソースで肯定応答が制御されるか、イベントの処理中にエラーが発生した場合はセッションが回復します。​AUTO​ 肯定応答のアプリケーションで手動肯定応答またはセッション回復を追加すると、チャネルで操作が重複します。

セッション肯定応答を ​MANUAL​ または ​DUPS_OK​ に設定する場合は、フロー実行のすべてのパスでメッセージ肯定応答またはセッション回復を取得することを確認してください。確認しなかった場合、メッセージがリークし、作業単位の最大深度に達したときにコンシューマーが無応答になる可能性があります。

この問題を解決する手順は、次のとおりです。

フローデザインを詳しく調べて、すべてのメッセージが肯定応答されるか、セッションが回復することを確認してください。

JMS の停止したコンシュームメッセージのトラブルシューティング

通常、JMS の停止したコンシュームメッセージは肯定応答されていない大量のメッセージに関連しています。Mule アプリケーションに ​On New Message​ ソースまたは ​Consume​ 操作とメッセージの手動肯定応答があり、メッセージのすべてのパスに適切な肯定応答またはセッション回復設定があるわけではない場合、Mule アプリケーションでコンシューマーが無応答になる場合があります。

このエラーを解決する手順は、次のとおりです。

ブローカー側で肯定応答されていないメッセージの深度をチェックし、アプリケーションロジックを確認します。

バインディングモード使用時の再デプロイメントエラーのトラブルシューティング

接続にバインディングモードを使用している場合、ドライバーは JNI リソースを読み込みます。JNI リソースは一度しか読み込めないため、アプリケーションを再デプロイすると、エラーがスローされます。

このエラーを解決する手順は、次のとおりです。

ドメインレベルでドライバー連動関係を追加します。これにより、アプリケーションの再デプロイメントが可能になります。

HA 環境と永続的なサブスクリプションのトラブルシューティング

HA (高可用性) システムの設定は、2 つのコンポーネントで構成されています。

  • プライマリノード
    継続的なサービスを提供するメインノード。

  • セカンダリノード
    同じサービスを提供する、プライマリノードの複製。

両方のノードは同一で、要求を受信可能であるため、エンドユーザーはシステムクラッシュを認識せずに透過的にシステムを使用し続けることができます。

ただし、永続的なサブスクリプションを使用する場合、一方のノードのみで接続が初期化され、もう一方のノードでは初期化されません。このシナリオでは、ノードは同一ですが、両方が同時に受信可能であることはあり得ません。なぜなら、接続しているのは一方のノードのみで、もう一方のノードは接続していないからです。HA クラスターで実行されている Mule の現在の設計は、プライマリノードの障害に対応できるようにすべてのノードで接続を初期化することを意図しています。

こうした理由から、JMS Connector では HA クラスター環境での永続的な ActiveMQ サブスクリプションはサポートされていません。

このシナリオの解決方法は、次のとおりです。

コンテナのライフサイクルを管理して、プライマリノードでの障害を検出し、新しいノードを開始するフォールバックソリューションを実装します。

プリフェッチの問題のトラブルシューティング

既知の問題として、JMS ドライバーまたはブローカーのプリフェッチ設定を MANUAL ACK および同時コンシューマーと組み合わせたり、フローごとに複数のメッセージをコンシュームしたりすると、予期しない順序でメッセージがコンシュームされることがあります。

JMS ブローカーではネットワークリソースを効率的に使用するためのプリフェッチポリシーが実装されており、プッシュモデルを使用してメッセージがコンシューマーにディスパッチされるため、コンシューマーには、処理可能なメッセージのローカルバッファが常に存在します。 JMS ドライバーまたはブローカーにプリフェッチサイズ設定がある場合、各コンシューマーで、コンシューム可能なメッセージのバッファが保持されます。バッファ内のメッセージ数は、ブローカー実装とカスタムパラメーター化に応じて決まります。

JMS Connector の ​Consume​ 操作では、操作ごとのコンシューマーを使用して一度に 1 つのメッセージがコンシュームされます。つまり、各操作でメッセージのバッファが保持されますが、仕様ではバッファ内の最初のメッセージのみがコンシュームされます。これにより、メッセージのコンシューム順序に関して予期しない動作が発生します。次のシナリオを考えてみます。

同時フロー

条件

  • 同じフローを 2 つの異なる実行スレッド (スレッド A とスレッド B) で同時に実行します。

  • JMS ドライバーまたはブローカーのプリフェッチサイズは 10 に設定されています。

  • キューには 100 件のメッセージがあります。

フローの反復 1:

  • スレッド A: コンシューマー A が作成され、そのローカルバッファにはブローカーによりプッシュされた処理可能な 10 件のメッセージがあります (メッセージ 1 ~ 10)。

  • スレッド B: コンシューマー B が作成され、そのローカルバッファにはブローカーによりプッシュされた処理可能な 10 件のメッセージがあります (メッセージ 11 ~ 20。最初の 10 件のメッセージはコンシューマー A にプッシュされたため)。

  • スレッド A: コンシューマー A でメッセージ 1 が肯定応答され、メッセージ 2 ~ 10 がブローカーに返されました。

  • スレッド B: コンシューマー B でメッセージ 11 が肯定応答され、メッセージ 12 ~ 20 がブローカーに返されました。

  • メッセージ 1 と 11 がコンシュームされました。

フローの反復 2:

  • スレッド A: コンシューマー A が作成され、そのローカルバッファにはブローカーによりプッシュされた処理可能な 10 件のメッセージがあります (メッセージ 2、3、4、5、6、7、8、9、10、12)。

  • スレッド B: コンシューマー B が作成され、そのローカルバッファにはブローカーによりプッシュされた処理可能な 10 件のメッセージがあります (メッセージ 13 ~ 22)。

  • スレッド A: コンシューマー A でメッセージ 2 が肯定応答され、メッセージ 3、4、5、6、7、8、9、10、12 がブローカーに返されました。

  • スレッド B: コンシューマー B でメッセージ 13 が肯定応答され、メッセージ 14 ~ 20 がブローカーに返されました。

  • メッセージ 2 と 13 がコンシュームされました。

フローの反復 3:

  • スレッド A: コンシューマー A が作成され、そのローカルバッファにはブローカーによりプッシュされた処理可能な 10 件のメッセージがあります (メッセージ 3、4、5、6、7、8、9、10、12、14)。

  • スレッド B: コンシューマー B が作成され、そのローカルバッファにはブローカーによりプッシュされた処理可能な 10 件のメッセージがあります (メッセージ 15 ~ 24)。

  • スレッド A: コンシューマー A でメッセージ 3 が肯定応答され、メッセージ 4、5、6、7、8、9、10、12、14 がブローカーに返されました。

  • スレッド B: コンシューマー B でメッセージ 15 が肯定応答され、メッセージ 16 ~ 24 がブローカーに返されました。

  • メッセージ 3 と 15 がコンシュームされました。

回避策:

  • フローの ​[Max Concurrency (最大同時実行)]​ 項目値を ​1​ に設定して実行を強制的にシリアル化すると、コンシュームされるメッセージの順序が期待どおりになります。

  • 他の方法として、ブローカーでのプリフェッチを無効にすることもできます。プリフェッチを無効にするには、サードパーティ JMS ベンダープロバイダーのドキュメントを参照してください。

同じフローでの複数のコンシューム

条件

  • foreach ブロック内でメッセージ 1 ~ 4 がコンシュームされます。

  • 最初のポイントでコンシュームされたメッセージがメッセージのコレクションに追加されます。これらのメッセージは後で処理および肯定応答されます。

  • JMS ドライバー/ブローカーのプリフェッチサイズは 2 に設定されています。

  • キューには 4 件のメッセージがあります。

  • JMS の ​Consume​ 操作の ​[Ack mode (肯定応答モード)]​ 項目は ​[MANUAL]​ に設定されており、メッセージは foreach ブロック内で、最初のポイントで作成されたコレクションを使用して肯定応答されます。

フローの反復 1:

  • Foreach の反復1 1:

    • コンシューマー 1 が作成され、そのローカルバッファにはブローカーによりプッシュされた処理可能な 2 件のメッセージがあります (メッセージ 1 と 2)。

    • メッセージ 1 がコレクションに追加されます。

  • Foreach の反復 2:

    • コンシューマー 2 が作成され、そのローカルバッファにはブローカーによりプッシュされた処理可能な 2 件のメッセージがあります (メッセージ 3 と 4)。

    • メッセージ 3 がコレクションに追加されます。

  • Foreach の反復 3:

    • キュー内に使用可能なメッセージはありません。

  • Foreach の反復 4:

    • キュー内に使用可能なメッセージはありません。

foreach によって作成されたコレクションのメッセージ (1、3) が肯定応答され、残りのメッセージ (2、4) はキューに返されます。

フローの反復 2:

  • Foreach の反復 1:

    • コンシューマー 1 が作成され、そのローカルバッファにはブローカーによりプッシュされた処理可能な 2 件のメッセージがあります (メッセージ 2 と 4)。

    • メッセージ 2 がコレクションに追加されます。

  • Foreach の反復 2:

    • キュー内に使用可能なメッセージはありません。

  • Foreach の反復 3:

    • キュー内に使用可能なメッセージはありません。

  • Foreach の反復 4:

    • キュー内に使用可能なメッセージはありません。

foreach によって作成されたコレクションのメッセージ (2) が肯定応答され、残りのメッセージ (4) はキューに返されます。

フローの反復 3:

  • Foreach の反復 1:

    • コンシューマー 1 が作成され、そのローカルバッファにはブローカーによりプッシュされた処理可能な 1 件のメッセージがあります (メッセージ 4)。

    • メッセージ 4 がコレクションに追加されます。

  • Foreach の反復 2:

    • キュー内に使用可能なメッセージはありません。

  • Foreach の反復 3:

    • キュー内に使用可能なメッセージはありません。

  • Foreach の反復 4:

    • キュー内に使用可能なメッセージはありません。

foreach によって作成されたコレクションのメッセージ (4) が肯定応答されます。

フローの反復をまとめると、フローの 3 回の反復によってキュー内の 4 件のメッセージがコンシュームされます。順序は守られていません。

  • 反復 1: [1、3]

  • 反復 2: [2]

  • 反復 3: [4]

回避策:

  • ブローカーでのプリフェッチを無効にします。プリフェッチを無効にするには、サードパーティ JMS ベンダープロバイダーのドキュメントを参照してください。

  • ブローカーでのプリフェッチを無効にできない場合は、JMS の ​Consume​ 操作で ​[Ack mode (肯定応答モード)]​ 項目を ​[IMMEDIATE]​ に設定し、メッセージが肯定応答されるまでローカルバッファでメッセージを保持しないようにします。

  • ユースケースに応じて、JMS の ​Consume​ 操作を使用してメッセージをポーリングする代わりに JMS の ​On New Message​ リスナーを使用してメッセージの到着時にメッセージを処理します。メッセージをチャンクで処理する必要がある場合は、Aggregators Module の ​[Size based aggregator (サイズベースのアグリゲーター)]​ スコープを使用して、後で処理するメッセージのコレクションを作成します。

一般的なスローを理解する

次に、一般的なスローメッセージとその解釈方法のリストを示します。

  • JMS:ACK

    処理中のメッセージの肯定応答のコンテキストでエラーが発生しました。
  • JMS:CONNECTIVITY

    接続が有効ではなくなりました。破棄されますが、アプリケーションの設定で定義されている場合、再接続ポリシーを適用できます。
  • JMS:CONSUMING

    WMQ からのメッセージのコンシューム中にエラーが発生しました。このエラーは保留中のメッセージが存在していないことに関連している場合もあります。
  • JMS:DESTINATION_NOT_FOUND

    JMS Connector が宛先を発見または作成できません。
  • JMS:RETRY_EXHAUSTED

    操作の最大再試行回数に達しました。
  • JMS:SECURITY

    セキュリティ関連のエラーが原因でスローされた例外。
  • JMS:TIMEOUT

    要求された操作のタイムアウトを超えました。
  • JMS:ILLEGAL_BODY

    メッセージ本文が無効であり、サポートされる種別に変換できません。
  • JMS:PUBLISHING

    対象キューまたはトピックへのパブリッシュ中にエラーが発生しました。