メッセージの消費に失敗した場合、ApsaraMQ for RocketMQは消費再試行ポリシーに基づいてメッセージを再配信します。 このトピックでは、消費再試行機能の一般的なシナリオ、作業メカニズム、バージョン互換性、および使用状況に関する注意事項について説明します。
一般的なシナリオ
ApsaraMQ for RocketMQの消費再試行機能は、消費ロジックが失敗したときに消費の整合性を保証します。 この機能は、消費ロジックの障害に対する保護手段であり、ビジネスプロセスの制御には使用できません。
推奨シナリオ
メッセージの内容が原因でビジネスが失敗します。 たとえば、メッセージに対応するトランザクションステータスが返されないため、一定期間後に消費が実行されることが予想されます。
1つのメッセージの消費失敗は、必ずしも他のメッセージの消費失敗を引き起こすわけではない。 1つのメッセージが消費されなかった場合、後続のメッセージの消費成功の確率は高い。 この場合、失敗したメッセージに対して再試行を実行して、プロセスがブロックされないようにすることができます。
推奨されないシナリオ
消費失敗は、実行される必要がある消費ロジックを決定するための条件として使用される。 消費ロジックは、大量のメッセージが消費されない可能性があると想定しているため、問題が発生する可能性があります。
消費失敗は、メッセージ処理の速度を制限するために使用される。 スロットルは、再試行のためにメッセージを配信する代わりに、後の処理のためにキューに過剰なメッセージを一時的にスタックするために使用されます。
目的
メッセージ指向のミドルウェアを非同期デカップリングに使用する場合、解決すべき課題は、ダウンストリームサービスがメッセージの処理に失敗した場合に呼び出しチェーンの整合性を確保する方法です。 金融グレードのメッセージ指向のミドルウェアとして、ApsaraMQ for RocketMQは信頼性の高い送信をサポートし、適切に設計されたメッセージ確認メカニズムと再試行ポリシーを使用して、すべてのメッセージが期待どおりに処理されるようにします。
ApsaraMQ for RocketMQのメッセージ確認メカニズムと再試行ポリシーを理解することで、次の問題を解決できます。
メッセージ消費の整合性を確保する方法。 メッセージ確認メカニズムと再試行ポリシーを使用して、すべてのメッセージが完全に処理されるようにすることができます。 これにより、例外発生時にメッセージが無視されず、ステータスの一貫性が確保されます。
例外が発生したときに機内メッセージのステータスを復元する方法。 メッセージ確認メカニズムと再試行ポリシーを使用して、機内メッセージのステータスを復元し、サービス障害などの例外が発生した場合にステータスの一貫性を確認できます。
消費再試行ポリシー
消費再試行ポリシーは、再試行の最大数と、メッセージの消費が失敗した後の2回の連続した再試行の間隔を定義します。
トリガー条件
メッセージの消費に失敗しました。 この場合、コンシューマが障害ステータスを返すか、システムが例外をスローします。
メッセージの処理中にタイムアウトエラーが発生します。これには、プッシュコンシューマキューのタイムアウトエラーも含まれます。
行動
再試行ステータス: メッセージの再試行中のステータスとステータス変更のロジックを制御します。
再試行間隔: メッセージの消費失敗またはタイムアウトが発生した時点から、メッセージの次の消費が開始される時点までの間隔。
最大再試行: メッセージを再試行して使用できる最大回数。
ポリシーの違い
消費再試行ポリシーは、消費者タイプに基づいて異なる再試行メカニズムと構成方法を使用します。 次の表に、ポリシーの違いを示します。
コンシューマタイプ | 再試行ステータス | 再試行間隔 | 最大再試行 |
消費者をプッシュ |
| コンシューマグループの作成時にメタデータで指定されます。
| ApsaraMQ for RocketMQコンソールで、またはAPI操作を呼び出すことによって指定されます。 詳細については、「最大再試行の変更」をご参照ください。 |
シンプルなコンシューマー |
| 対応するAPI操作のInvisibleDurationパラメーターで指定されます。 | ApsaraMQ for RocketMQコンソールで、またはAPI操作を呼び出すことによって指定されます。 詳細については、「最大再試行の変更」をご参照ください。 |
詳細については、「プッシュモードで消費されるメッセージの再試行ポリシー」および「シンプルモードで消費されるメッセージの再試行ポリシー」をご参照ください。
プッシュモードで消費されたメッセージの再試行ポリシー
再試行ステータス
メッセージがプッシュモードで消費された場合、メッセージは次のいずれかの状態になります。
準備完了
メッセージは、ApsaraMQ for RocketMQブローカーで使用できるようになりました。
機内
メッセージはコンシューマによって取得されて消費されますが、消費結果は返されません。
WaitingRetry
この状態は、プッシュモードで消費されるメッセージ専用です。 メッセージの消費に失敗した場合、またはメッセージの消費がタイムアウトした場合、消費の再試行ロジックがトリガーされます。 再試行の最大数に達するまで、メッセージはWaitingRetry状態になります。 リトライ間隔が経過すると, メッセージの状態はReadyに変わります。 Ready状態にあるメッセージは、再び消費することができる。 2回の連続したリトライの間隔を増やして、頻繁なリトライを防ぐことができます。
コミット
メッセージが消費されます。 消費者が成功応答を返した後、消費は完了する。
DLQ
消費ロジックの実装を保証するために使用されるメカニズム。 無効文字メッセージ機能が有効になっている場合、再試行の最大数に達した後に消費されないメッセージが無効文字トピックに送信されます。 デッドレターメッセージを使用してビジネスを復元できます。 詳細については、「デッドレターメッセージ」をご参照ください。
廃棄
無効メッセージ機能が有効になっていない場合、再試行の最大数に達した後に消費されないメッセージは破棄されます。
上の図は、再試行プロセスのサンプルを示しています。 図では、メッセージは5秒間レディ状態のままであり、消費されるのに6秒を要する。
メッセージが再試行されるたびに、メッセージのステータスはReadyからInflightに変わり、次にWaitingRetryに変わります。 リトライ間隔とは、メッセージの消費失敗またはタイムアウトが発生した時点から、メッセージの次の消費が開始する時点までの間隔を指す。 2つの連続した消費の間の間隔は、再試行間隔、消費持続時間、およびメッセージがレディ状態のままである期間を含む。 例:
メッセージが消費のために初めて配信されると、メッセージは0秒目にレディ状態に入る。
メッセージは5秒目にプルされます。 6秒目に、消費エラーが発生し、消費失敗を示すメッセージがクライアントによって返されます。
10秒のリトライ間隔が指定されているため, すぐにはリトライできません。
21秒で、メッセージは再びレディ状態に入る。
5秒後、クライアントは再びメッセージの消費を開始します。
消費間隔は、以下の式を使用することによって21秒として計算される。消費間隔=消費持続時間 + 再試行間隔 + レディ状態における持続時間=6 + 10 + 5 = 21。
再試行間隔
順序付けられていないメッセージの再試行間隔は増分です。 次の表に、詳細を示します。
リトライ番号
インターバル
リトライ番号
インターバル
1
10 秒
9
7分
2
30 秒
10
8分
3
1 分
11
9分
4
2分
12
10 分
5
3分
13
20分
6
4分
14
30分
7
5 分
15
1 時間
8
6分
16
2時間
説明再試行回数が16回を超える場合、その後のすべての再試行の間隔は2時間です。
順序付けられたメッセージの再試行間隔は固定です。 詳細については、「パラメーターの制限」をご参照ください。
最大再試行
デフォルト値: 16。
最大値は 1000 です。
プッシュモードで消費されるメッセージの再試行の最大数は、コンシューマグループの作成時にメタデータで指定されます。 詳細については、「最大再試行の変更」をご参照ください。
例えば、リトライの最大回数が3回に指定されている場合、メッセージは、1回の最初の試行と3回のリトライを含めて、4回配信することができる。
例:
メッセージがプッシュモードで消費された場合、メッセージの消費が失敗した場合に返されるステータスコードを使用して、消費の再試行をトリガーできます。 予期しない例外が発生した場合、SDKは例外をキャプチャできます。
SimpleConsumer simpleConsumer = null;
// Consumption example: When a normal message is consumed in Push mode, consumption retry can be triggered if the message fails to be consumed.
MessageListener messageListener = new MessageListener() {
@Override
public ConsumeResult consume(MessageView messageView) {
System.out.println(messageView);
// The system retries the message until the message is consumed or the maximum number of retries is reached.
return ConsumeResult.FAILURE;
}
};
消費再試行ログの表示
順序付けされたメッセージがプッシュモードで消費された場合、メッセージはコンシューマークライアントで再試行され、ブローカーは再試行ログの詳細を取得できません。 順序付けられたメッセージのトレースに表示された配信結果が、メッセージの配信に失敗したことを示す場合は、再試行の最大回数とコンシューマークライアントに関する情報をコンシューマークライアントログで確認する必要があります。
コンシューマークライアントのログパスについては、「ログ設定」をご参照ください。
次のキーワードを検索して、クライアントログの消費失敗に関する情報を照会できます。
Message listener raised an exception while consuming messages
Failed to consume fifo message finally, run out of attempt times
が不足しました
シンプルモードで消費されたメッセージの再試行ポリシー
再試行ステータス
メッセージがシンプルモードで消費されると、メッセージは次のいずれかの状態になります。
準備完了
メッセージは、ApsaraMQ for RocketMQブローカーで使用できるようになりました。
機内
メッセージはコンシューマによって取得されて消費されますが、消費結果は返されません。
コミット
メッセージが消費されます。 消費者が成功応答を返した後、消費は完了する。
DLQ
消費ロジックの実装を保証するために使用されるメカニズム。 無効文字メッセージ機能が有効になっている場合、再試行の最大数に達した後に消費されないメッセージが無効文字トピックに送信されます。 デッドレターメッセージを使用してビジネスを復元できます。 詳細については、「デッドレターメッセージ」をご参照ください。
廃棄
無効メッセージ機能が有効になっていない場合、再試行の最大数に達した後に消費されないメッセージは破棄されます。
シンプルモードで消費されるメッセージのリトライ間隔は, あらかじめ設定されています。 対応するAPIを呼び出してメッセージを取得する前に、メッセージを処理する最大期間を指定するために使用されるInvisibleDurationパラメーターを設定する必要があります。 メッセージの使用に失敗し、再試行がトリガーされた場合は、再試行の間隔を指定する代わりに、InvisibDurationパラメーターの値を使用できます。
プリセットの非表示期間がビジネス要件を満たしていない場合は、対応するAPI操作を呼び出して期間を変更できます。
たとえば、InvisibleDurationパラメーターを20ミリ秒に設定したが、その期間内にメッセージを処理できない場合、値をより大きい値に変更して、再試行間隔を長くすることができます。
InvisibleDurationパラメーターの値を変更する前に、次の条件が満たされていることを確認する必要があります。
メッセージにタイムアウトエラーは発生しませんでした。
消費ステータスはコミットされていません。
次の図は、InvisibleDurationパラメーターの値を変更すると、対応するAPI操作を呼び出すとすぐに非表示期間が再計算されることを示しています。
再試行間隔
リトライ間隔=InvisibleDurationの値-実際のメッセージ処理時間
シンプルモードで消費されるメッセージの再試行間隔は、InvisibleDurationパラメーターによって決まります。 たとえば、InvisibleDurationパラメーターの値を30ミリ秒に設定します。 実際のビジネスシナリオでは、消費の失敗は消費開始から10ミリ秒後に返され、システムは次の再試行を開始するまで20ミリ秒待機します。 この場合、リトライ間隔は20ミリ秒です。 30ミリ秒までに消費結果が返されない場合、タイムアウトエラーが発生し、再試行がトリガーされます。 そして、リトライ間隔は0 msとなる。
最大再試行
デフォルト値: 16。
最大値は 1000 です。
シンプルモードで消費されるメッセージの再試行の最大数は、コンシューマグループの作成時にメタデータで指定されます。 詳細については、「最大再試行の変更」をご参照ください。
例えば、リトライの最大回数が3回に指定されている場合、メッセージは、1回の最初の試行と3回のリトライを含めて、4回配信することができる。
例:
シンプルモードで消費されるメッセージの再試行には操作は必要ありません。
// Consumption example: When a normal message is consumed in Simple mode, the consumer needs to only wait until the consumption times out. After a consumption timeout occurs, the broker automatically retries the message.
List<MessageView> messageViewList = null;
try {
messageViewList = simpleConsumer.receive(10, Duration.ofSeconds(30));
messageViewList.forEach(messageView -> {
System.out.println(messageView);
// If you want a message to be retried after the message fails to be consumed, ignore the failure and wait until the message is visible again.
});
} catch (ClientException e) {
// If the message fails to be pulled due to throttling or other reasons, you must re-initiate the request to obtain the message.
e.printStackTrace();
}
最大再試行の変更
次のいずれかの方法を使用して、プッシュモードとシンプルモードで使用されるメッセージの最大リトライ回数を変更できます。
UpdateConsumerGroup APIの呼び出し
操作:
インスタンス数 ページで、管理するインスタンスの名前をクリックします。
左側のナビゲーションウィンドウで、グループ をクリックします。 グループ ページで、グループの作成 をクリックします。
使用上の注意
消費量の調整に対処するために消費の再試行機能を使用しないでください
一般的なシナリオで述べたように、消費の再試行は、メッセージ消費失敗の確率が小さいシナリオに適しています。 消費の再試行は、消費の抑制など、1つのメッセージの失敗が後続のメッセージの失敗を引き起こすシナリオには適していません。
間違った例
現在の消費率が指定された制限よりも高い場合は、消費失敗を返して再試行をトリガーします。
正しい例
現在の消費率が指定された制限より高い場合は、後でメッセージを取得して消費します。
FAQ
メッセージ消費のタイムアウト期間を設定するにはどうすればよいですか?
コンシューマークライアントでのメッセージ消費のタイムアウト期間を設定できます。
シンプルモードでメッセージを消費する場合、10秒から12時間の範囲のタイムアウト期間を設定できます。
サンプルコード:
private long minInvisiableTimeMillsForRecv = Duration.ofSeconds(10).toMillis(); private long maxInvisiableTimeMills = Duration.ofHours(12).toMillis();
プッシュモードでメッセージを消費する場合、メッセージ消費のタイムアウト時間は1分です。 値は変更できません。