キューワーカー

メッセージキューからタスクを取り出して非同期に処理するバックグラウンドプロセス

非同期アーキテクチャ

キューワーカーとは

キューワーカーは、メッセージキュー (Amazon SQS など) からタスクを取り出して非同期に処理するバックグラウンドプロセスである。API のレスポンスを高速化し、重い処理をバックグラウンドに逃がす。

分離が効くのは、受け付ける側と処理する側で必要な規模の決まり方が違うからだ。受付は同時に来るリクエストの数に、処理は仕事量に比例する。キューを挟むと受付は投入だけで終わるので応答時間が処理時間から切り離され、処理側は溜まった件数を見て後から増やせる。流入が急に増えても、受付が倒れる代わりに待ち行列が伸びるだけで済む。

同期処理 vs キューワーカー

同じ画像リサイズでも、同期で行うか切り離すかで待たされる相手が変わる。

同期処理:
  API → 画像リサイズ (5秒) → レスポンス
  → ユーザーが 5 秒待つ

キューワーカー:
  API → SQS にメッセージ送信 → レスポンス (即座)
  SQS → Lambda (バックグラウンドで画像リサイズ)
  → ユーザーは待たない

ユースケース

キューワーカーは、リクエストの応答時間に含めたくない重い処理を非同期に実行する場面で使われる。API はメッセージをキューに投入して即座にレスポンスを返し、ワーカーがバックグラウンドで処理を進める。

ユースケース構成
画像・動画処理API → SQS → Lambda
メール送信API → SQS → Lambda → SES
データ変換S3 → SQS → Lambda → S3
注文処理API → SQS → Step Functions

取りこぼしと二重処理

ワーカーを組むときに最初に決めるのは、処理が途中で落ちたときの扱いである。SQS では受信したメッセージがすぐ消えるわけではなく、可視性タイムアウトの間だけ他のワーカーから見えなくなり、処理を終えたワーカーが明示的に削除するまでキューに残る。途中で落ちれば時間の経過とともに再び見えるようになり、別のワーカーが引き継ぐ。これが取りこぼしを防ぐ機序である。

可視性タイムアウトは既定で 30 秒、最大で 43,200 秒 (12 時間) まで指定できる。実際の処理時間より短いと、処理中のメッセージが再び配信されて同じ仕事が二重に走る。消費側を Lambda にする場合は、関数のタイムアウト設定の 6 倍以上を確保するのが公式に案内されている目安だ。

何度受け取っても失敗するメッセージは、受信回数の上限を超えた時点でデッドレターキュー (DLQ) へ移される。この上限を決めていないと、壊れた 1 件が再配信を繰り返して後続の処理を圧迫する。移した先は放置せず、件数の監視と原因を確かめる手順まで用意しておく。

標準キューの配信保証は at-least-once で、同じメッセージが 2 回届くことがある。したがってワーカーの処理は、同じ入力で 2 回走っても結果が変わらない形 (冪等) にしておく必要がある。メール送信なら 2 通届き、課金なら二重に請求される。処理済みの識別子を記録して 2 回目を弾く作りにするのが基本である。

SQS vs EventBridge

非同期にする手段として EventBridge も候補に挙がるが、宛先の数と順序の扱いが違う。

観点SQSEventBridge
宛先投入した 1 件を 1 つの処理系が消費1 つのイベントを複数の宛先へ配信
順序保証FIFO キューでメッセージグループ単位に保証なし
失敗時削除されなければ可視性タイムアウトの経過後に再び受信できる既定で 24 時間・最大 185 回まで再送
用途バックグラウンド処理イベント駆動

非同期にした後で困ること

切り離すと、失敗をその場でユーザーに伝えられなくなる。投入は成功したのに処理が失敗したという状態が生まれるため、結果を知らせる経路 (通知や、処理状況を問い合わせられる口) を用意しないと、利用者は完了したものと思い込む。投入時に識別子を返し、その識別子で状態を参照できるようにしておくと扱いやすい。

ワーカーの数は、キューに溜まっている件数と最も古いメッセージの待ち時間を見て決める。処理が追いつかない状態が続けば待ち時間は延び続けるので、この 2 つを監視対象にしておく。順序が要件なら FIFO キューを選ぶが、順序を守る単位をどう切るかで同時に処理できる本数が決まる点は設計の前に確かめておきたい。

この記事は役に立ちましたか?

関連用語

関連する記事