2
0

More than 3 years have passed since last update.

ElasticBeanstalk worker環境 の 3つのタイムアウトの違いについて

Last updated at Posted at 2020-11-03

概要

ElasticBeanstalk の worker environment には VisibilityTimeout, ErrorVisibilityTimeout, InactivityTimeout というよく似た名前の設定値があり,それぞれ何を意味するのかについて整理しました.

公式ドキュメントの説明

公式ドキュメントには以下のように記載されています:

パラメータ 説明
VisibilityTimeout 「Amazon SQS キューからの着信メッセージが処理のためにロックされる時間」
ErrorVisibilityTimeout 「明示的なエラーで処理が失敗した後、Elastic Beanstalk が Amazon SQS キューにメッセージを返すまでの経過時間」
InactivityTimeout 「アプリケーションへの既存の接続が応答するまでの待機時間」

VisibilityTimeout

VisibilityTimeout とは SQS API のパラメータで, sqsd が GetMessage APIを呼び出すときに引数として設定します.設定値の意味は,メッセージが可視(visible) である時間の上限です.

message の可視性(visibility) というのは SQS の概念で,メッセージの排他処理を実現するための機構です.message が visible なときはすべての worker がメッセージを見ることができますが,ある worker が GetMessage すると,メッセージは一定の期間不可視(invisible) となり,他の worker からは取得できなくなります.このメッセージが不可視となる期間が VisibilityTimeout です.

メッセージが取得されてから VisibilityTimeout を経過したメッセージは,SQS マネージドサービスによって再び可視(visible) 状態となり,ほかの worker によって再処理されます.後述する ErrorVisibilityTimeout が設定されていない場合,VisibilityTimeout がメッセージの再処理間隔と同義になります.(詳しい説明は公式ドキュメントを参照)

ErrorVisibilityTimeout

次に,ErrorVisibilityTimeout というのは VisibilityTimeout と似ていますが,こちらはエラー処理のときに使われる設定値です.デフォルトでは未設定です.

ErrorVisibilityTimeout が設定されている場合,アプリケーションが明示的にエラーを返した場合に, sqsd は SQS の API ChangeMessageVisibility を呼び出し,メッセージの可視期間を ErrorVisibilityTimeout に設定された値に変更します.

すなわち,明示的なエラーとなった場合に,あらかじめ設定された VisibilityTimeout の値とは独立して再処理間隔を設定することができます.VisibilityTimeout は worker の処理時間よりも十分長い値が設定されているので(デフォルト値は 300 sec),一度エラーを返したメッセージが次に再処理されるまでに長く待つ必要があります.一方で, ErrorVisibilityTimeout が設定されていれば,最初に設定した VisibilityTimeout の経過を待たずに,エラーが起きた時刻を起点として再処理間隔を設定することができます.

また,注意しなければならないのは,アプリケーション側のミドルウェアがタイムアウトした場合です.通常,sqsd とアプリケーションの間には nginx や WSGI のようなミドルウェアが存在する構成にすると思いますが,例えば nginx でタイムアウトした場合,sqsd は nginx のステータスコードをもとにエラーとして処理しますが,アプリケーションは処理を継続しています.したがって,ErrorVisibilityTimeout が短いと,アプリケーションが処理中にも関わらず,アプリケーションを2重に起動してしまう可能性が高くなります.(通常はアプリケーションを冪等に設計するはずなので,実際には2重起動は問題にならないかもしれません.)

InactivityTimeout

最後に, InactivityTimeout ですが,他の2つが SQS API を呼び出すときのパラメータなのに対し,こちらは SQS の worker daemon (sqsd) に閉じたパラメータです.

sqsd が既に確立されたアプリ側とのコネクションに対して POST メッセージを送ってから,アプリケーションが応答を返すまでの待ち時間です.(同様に,アプリ側とのコネクションを確立するときの待ち時間として ConnectionTimeout があります)

シーケンス図による説明

以上が言葉による説明ですが,具体的なケースで実際に sqsd がどのように振る舞うかを理解すると,
よりいっそう理解が深まると思うので,以下では 4つのケースについてシーケンス図で説明します.

  1. アプリケーションが正常に応答する場合
  2. アプリケーションがエラーレスポンスを返す場合(ErrorVisibilityTimeout が設定されていない場合)
  3. アプリケーションがエラーレスポンスを返す場合(ErrorVisibilityTimeout が設定されている場合)
  4. アプリケーションが InactivityTimeout を超えても応答しなかった場合

1. アプリケーションが正常に応答する場合

sqsd001.png

まず,アプリケーションが正常な応答を直ちに(タイムアウトよりも十分短い時間で)返す場合です.

sqsd は SQS のキューをポーリングし,メッセージがキューに入ると,GetMessage API を呼び出してメッセージを取得します.取得されたメッセージはSQS上では不可視(invisible)状態,すなわち,他の daemon プロセスからは処理できない状態となります.

次に,sqsd はこのメッセージをパースして HTTP リクエストに変換し,アプリ側に POST リクエストとして送信します.アプリ側が正常なレスポンス(ステータス200)を返した場合は,sqsd は処理が成功したとみなし,DeleteMessage API を呼び出して SQS 上からメッセージを削除します.

以上が最も基本的なシーケンスです.

2. アプリケーションがエラーレスポンスを返す場合(ErrorVisibilityTimeout が設定されていない場合)

sqsd002.png

次に,アプリケーションが明示的にエラー応答を返す場合で,かつ,ErrorVisibilityTimeout が設定されていない場合について説明します.

sqsd がアプリケーションに POST リクエストを投げるまでは,1つめのシーケンスと同じです.アプリケーションが明示的なエラー(5xx など)を返した場合,sqsd は処理に失敗したとみなしますが,ErrorVisibilityTimeout が設定されていないため,可視性の変更はせず,VisibilityTimeout が経過するのを待ちます.VisibilityTimeout が経過すると,メッセージはSQS上から再び可視(visible)状態になるため,worker プロセスによって再処理されます.

3. アプリケーションがエラーレスポンスを返す場合(ErrorVisibilityTimeout が設定されている場合)

sqsd003.png

以下は,アプリケーションが明示的なエラー応答と返す場合で,かつ,ErrorVisibilityTimeout が設定されている場合のシーケンスです.

アプリケーションが明示的なエラーレスポンスを返すまでは2つめのシーケンスと同じです.sqsd は処理に失敗したとみなし,ChangeMessageVisibility API を呼び出して,ErrorVisibilityTimeout で設定した値でメッセージの可視性タイムアウト(VisibilityTimeout) を再設定します.ChangeMessageVisibility API が呼び出されてから ErrorVisibilityTimeout だけ経過したら,メッセージは再び可視(visible) 状態となり,worker プロセスによって再処理されます.

4. アプリケーションが InactivityTimeout を超えても応答しなかった場合

sqsd004.png

最後に,アプリケーションが InactivityTimeout を超えて応答を返さなかった場合のシーケンスを説明します.

sqsd がアプリケーションに POST リクエストを送るまでは1-3つめのシーケンスと同じですが,アプリケーションが応答を返すまでに, InactivityTimeout 以上経過した場合,sqsd はメッセージの処理に失敗したとみなします.その後の処理は,ErrorVisibilityTimeout が設定されているかどうかによって決まり,設定されていない場合は2つめ,設定されている場合は3つめのシーケンスにしたがって処理されます.

終わりに

説明は以上ですが,最後に,sqsd のソースコードの場所を共有しておきます.ubuntu 16.04 の場合,EC2インスタンスの以下のディレクトリにあります.

  • /opt/elasticbeanstalk/lib/ruby/lib/ruby/gems/2.2.0/gems/aws-sqsd-2.3

ruby の gem で提供されているようですが, public なリポジトリではないようです.

AWSのドキュメントを読みながらだと,細かい仕様が理解しずらかったのですが,ソースコードを見ながらだとすんなり理解することができました.

参考

2
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
0