このトピックでは、メッセージ消費時における適応型メッセージ処理期間の概念、シナリオ、およびソリューションについて説明します。
基本概念
可視: 可視メッセージは、多数のコンシューマーが読み取りおよび受信できます。コンシューマーとは、メッセージを受信して処理するサービスまたはアプリケーションです。
非可視:メッセージが 1 つのコンシューマーに受信されると非可視状態になり、他のコンシューマーは受信できません。これにより、他のコンシューマーが同じメッセージを処理するのを防ぎます。
可視性タイムアウト期間:メッセージがコンシューマーに受信されて (他のコンシューマーには非可視になり) から、他のコンシューマーが再び受信できる (他のコンシューマーに可視になる) までの期間です。
メッセージが 1 つのコンシューマーに受信されると非可視状態になり、他のコンシューマーは受信できません。この非可視の状態は可視性タイムアウト期間によって決まり、他のコンシューマーが同じメッセージを処理するのを防ぎます。
可視性タイムアウト期間の詳細については、「Visibility Timeout」をご参照ください。
ユースケース
Simple Message Queue (旧称:MNS) は、各メッセージに対してデフォルトの可視性タイムアウト期間を指定します。カウントダウンは、コンシューマーがメッセージを受信した時点で開始されます。コンシューマーが可視性タイムアウト期間内にメッセージを処理できない場合、別のコンシューマーがメッセージを受信して処理する可能性があります。このタイムアウトは、処理後にメッセージを明示的に削除する必要があるため役立ちます。コンシューマーのプロセスがクラッシュするなどの異常が発生した場合でも、別のコンシューマーがメッセージを処理できます。
一部のユーザーは、コンシューマーがメッセージの処理を完了する前にメッセージが解放されないようにするため、キューのデフォルトの可視性タイムアウト期間を長く設定します。たとえば、キューの可visible性タイムアウト期間を 6 時間に設定します。コンシューマーがメッセージ M1 を受信して処理します。その後、プロセスがクラッシュするかマシンが再起動すると、メッセージ M1 は少なくとも 6 時間、別のコンシューマーが受信して処理できません。これらの障害に対処するカスタムコードを作成すると、プログラムの複雑さが増します。
高いリアルタイム性能と各メッセージに対する迅速な応答が求められるシナリオでは、メッセージの消費は次の目標を満たす必要があります:
キューの可視性タイムアウト期間を短くする必要があります。プロセスがクラッシュした場合、短い可視性タイムアウト期間の期限切れ後に、別のコンシューマーが未処理のメッセージを受信して処理できます。
処理中にメッセージがタイムアウトしないようにする必要があります。たとえば、コンシューマーがメッセージの処理に 5 分以上かかる場合でも、この処理中にメッセージがタイムアウトしてはなりません。
ソリューション
Simple Message Queue (formerly MNS) が提供する C# SDK は、このシナリオに対応できます。解決策は、コンシューマーがメッセージを処理している間に、メッセージに ChangeVisibility 操作が必要かどうかを定期的にチェックすることです。処理が完了した後、コンシューマーは依然としてメッセージを明示的に削除する必要があります。
C# SDK のダウンロードリンクについては、「C# SDK」をご参照ください。デモで問題が発生した場合は、チケットを送信できます。
プログラムには次の点が適用されます:
プログラムを実行する前に、
accessId、accessKey、およびEndPointを指定する必要があります。変数の説明:
変数
説明
MessageMinimalLife
メッセージを登録する際に必要となる、メッセージの最小生存期間です。たとえば、登録時点でメッセージのタイムアウト期間の残りが 0.1 秒しかない場合、
ChangeVisibilityを使用して生存期間を延長する時間が不足します。したがって、MessageMinimalLifeは、ChangeVisibilityを呼び出せるだけの十分な生存期間を確保します。業務負荷に基づき、必要に応じてこの値を設定してください。TimerInterval
Manager 内部タイマーの間隔です。タイマーは、メッセージの残り生存期間が
MessageMinimalLifeに達する前に開始されるようにしてください。短い間隔を設定することもできますが、その場合はチェック頻度が高くなります。QueueMessageVisibilityTimeout
メッセージのデフォルトの可視性タイムアウト期間です。これはキューのプロパティです。
ChangeVisibilityを呼び出すたびに、メッセージの可視性タイムアウト期間はQueueMessageVisibilityTimeoutにリセットされます。そのため、メッセージがタイムアウトしないように、値はTimerInterval+MessageMinimalLifeよりも大きくする必要があります。MessageTimeout
Manager 内でのメッセージのタイムアウト期間です。たとえば、コンシューマーがスタックし、5 時間経ってもメッセージが処理されない場合 (5 時間が通常の処理時間より十分に長いと仮定)、Manager はそのメッセージに対して
ChangeVisibilityの呼び出しを停止します。そして、メッセージの可視性タイムアウトが期限切れになるようにします。フローの説明:
コンシューマーはメッセージを受信した後、まずメッセージを登録し、次にそれを処理し、最後に Manager の
deleteMessageメソッドを呼び出します。メッセージが最初に登録されると、Manager はスレッドプールを使用して
ChangeVisibilityTaskをスケジュールし、ChangeVisibilityAPI が必要かどうかを確認します。また、Manager はメッセージを内部メッセージリストに追加します。Manager の内部タイマーは、定期的に
Parallelを使用してChangeVisibilityTaskを開始し、メッセージリスト内のすべてのメッセージを確認します。Manager.ChangeMessageVisibility (ChangeVisibilityTask) の具体的な操作は、フローチャートに示されています。
フローチャートは次のとおりです: