すべてのプロダクト
Search
ドキュメントセンター

:メッセージの可視性のタイムアウト

最終更新日:Mar 22, 2020

メッセージ処理時間を柔軟に変更する方法

状況

Alibaba Cloud Message Service の仕様では、各メッセージのデフォルトの可視性のタイムアウトがあります。ワーカーがメッセージを受信すると、タイムアウトのカウントが開始されます。ワーカーがタイムアウト時間内にメッセージ処理を完了しない場合、メッセージは他のワーカーによって受信され処理されることがあります。

タイムアウトの利点:メッセージ処理の完了後に明示的に DeleteMessage を実行する必要があります。ワーカープロセスがクラッシュした場合でも、メッセージは別のワーカーによって処理されることが可能です。

キューのデフォルトの VisibilityTimeout を長時間に設定し、ワーカーがメッセージ処理を完了する前に、タイムアウトによりメッセージが解放されないようにするユーザーもいます。

問題

あるアプリケーションシナリオで、キューの VisibilityTimeout が 6 時間に設定されているとします。

ワーカーはメッセージ M1 を受け取ります。しかし、ワーカーがメッセージ処理を完了した後に、ワーカープロセスがクラッシュしたり、システムが再起動されたりしたとします。

メッセージ M1 は、少なくとも 6 時間が経過しない限り、別のワーカーに受信され処理されることができません。この状況は、フェールオーバーを処理するプログラムを作成するには複雑すぎます。

目的

リアルタイム要件が高く、各メッセージに迅速に対応する必要があるシナリオでは、次のことが期待されます。

  1. キューの VisibilityTimeout を短く (例えば 5 分) すれば、現在のワーカーがクラッシュしてから最大 5 分後には、別のワーカーが処理未完了のメッセージを受信して処理できること。

  2. ワーカーのメッセージ処理に 5 分以上かかった場合、処理中にタイムアウトしないこと。

解決策

このようなシナリオに対して、ベストプラクティスとして C# のデモを提供します (添付ファイル参照)。ワーカーがメッセージを処理している最中に、メッセージに対して ChangeVisibility が必要かどうかを定期的にチェックします。ワーカーは処理を完了した後、DeleteMessage でメッセージを削除します。

注意:

1. プログラムを実行する前に、accessId、accessKey、および endPoint を設定します。

2. 変数の説明:

  • MessageMinimalLife は、メッセージが登録されたときに必要な最小生存時間を示します。メッセージが登録された時点で残っているタイムアウト時間がわずか 0.1 秒である場合、ChangeVisibility を実行してメッセージの生存時間を延ばすことはできません。したがって、MessageMinimalLife は、ChangeVisibility が実行されるまでメッセージが持続することを保証する必要があります。この変数は、サービスに応じて設定できます。
  • TimerInterval は、マネージャーのタイマーの間隔を示します。メッセージが MessageMinimalLife に到達する前に、タイマーが有効になっていることを確認する必要があります。この変数を短い時間に設定できます (チェックが頻繁になります)。
  • QueueMessageVisibilityTimeout は、サンプル内のメッセージのデフォルトのタイムアウト時間を示します (これはキュー内の属性です)。サンプルが ChangeVisibility を実行するたびに、VisibilityTimeout の値を QueueMessageVisibilityTimeout の値に設定します。したがって、メッセージがタイムアウトしないように、QueueMessageVisibilityTimeout の値は TimerInterval + MessageMinimalLife の値より大きくしなければなりません。
  • MessageTimeout は、マネージャーのメッセージのタイムアウト時間を示します。ワーカーが立ち往生している場合、メッセージ処理は 5 時間で完了しません (この時間は通常のメッセージ処理時間をはるかに超えていると見なされます)。マネージャーはメッセージの ChangeVisibility を実行しませんが、メッセージの可視性のタイムアウトを有効にします。

3. 処理の説明

  • メッセージを受信した後、ワーカーはメッセージを登録し、メッセージを処理し、マネージャーの DeleteMessage を呼び出します。

  • 最初にメッセージがマネージャーに登録されると、マネージャーは ThreadPool を呼び出して ChangeVisibilityTask をスケジュールして ChangeVisibility が必要かどうかを確認し、そのメッセージを内部メッセージリストに追加します。

  • マネージャーのタイマーは定期的に Parallel を呼び出して ChangeVisibilityTask を開始し、メッセージリスト内のすべてのメッセージをチェックします。

  • 次のフローチャートに Manager.ChangeMessageVisibility (ChangeVisibilityTask) に関する処理を示します。

ChangeMessageVisibility

サンプルコードのダウンロード:ChangeMessageVisibilitySample