27
21

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

AWSでよく使うSQS+Lambdaの組み合わせで気をつけるべきこと

Posted at

今回はSQS+Lambdaを組み合わせて使う場合に気をつけるべきことについて書きました
サーバレスなアーキテクチャを考えた時に、何かと候補に上がる組み合わせだと思います
一部、自分が体験した失敗から学んだこともあるので、反省の復習をしつつ同じ失敗をする人が減ってくれれば良いなと思います

なんでSQS+Lambdaなのか?

そもそもこの組み合わせを選ぶのはなぜか?ということですが

  • サーバレスなアーキテクチャを組みたい
  • Lambdaを使用するにはトリガーとして全段にサービスが必要(SQS、APIGateway・・・など)
  • Lambdaの処理が失敗した場合、再実行したい

このような理由からSQS+Lambdaの組み合わせを選択します

【ケース①】SQSの標準キューはメッセージの配信を1回”以上”保証する

SQSの標準キューとはこれです

スクリーンショット 2020-12-24 20.58.11.png

「少なくとも1回の配信」とあります
複数回同じメッセージが配信されることもあります
そのため、Lambdaで2回以上同じメッセージが来ることを考慮する必要があります
/tmpにファイル保存したり、DB処理するときに「重複してるからダメよ」と言われないように、「2回目以降は処理しない」など回避方法を考える必要があります

【ケース②】SQSの標準キューは順序性を保持しない

ケース①と同じく標準キューの話になります
FIFOキューであれば順序が保持されるのですが、標準キューは順序が保持されません
[1, 2, 3, 4]という順序でメッセージが入っても[1, 2, 4, 3]と処理されることがあります
順序性が必要な処理を行う際は「データをファイルやDBに全部まとめる前処理を置く」などデータを繋げたり、順序性が不要なデータにするなど対処が必要です
※「FIFOキューにすればいいじゃないか」という話はあるのですが、S3バケットのファイルを処理したい時に標準キューしか選べなかったりします

スクリーンショット 2020-12-24 21.12.01.png

【ケース③】LambdaはSQSの複数メッセージを拾うことがある

LambdaはSQSのキューをポーリングして「処理するメッセージないかなー」と待っています
キューにメッセージが入ってくるとLambdaが処理を開始します
Lambdaが確認したタイミングでメッセージが複数存在すると複数のメッセージをLambdaの1起動分(プロセスと表現した方が良いのか?)で処理しようとすることがあります

lambda_function.py
import json

# "event"にメッセージが配列となって格納される
def lambda_handler(event, context):

Lambdaのタイムアウト、SQSキューの可視性タイムアウトの時間は「最大何メッセージを処理し、全体の処理時間は何秒か?」を考慮して設定する必要があります
また、途中のメッセージ(例えば10個中5個目)で例外などが発生した時に「次のメッセージを処理するのか?」など、ハンドリングを考慮する必要があります

1起動あたり何メッセージを取得するかはLambda側に設定します
Lambdaでトリガーを設定するところに「バッチサイズ」というのがあり、これが1バッチあたり何メッセージ取得するか?を決めています
Lambdaは1度に5バッチまで取得することが可能で、取得しきれないメッセージが存在するとLambdaの同時実行数が増えていきます
バッチはメッセージを入れる箱で、1度に箱に何メッセージ入れられて、箱を何個持てるか?持てない分は実行数を増やして箱を持つというイメージになります
AWS公式のドキュメントはこちらです

スクリーンショット 2020-12-24 21.20.12.png

【ケース④】SQSのデッドレターキューを使用する際はLambdaは例外をスローする

SQSのキューの機能でデッドレターキューというものがあります
キューのメッセージを処理していると当然異常が発生すると思います
異常が発生したメッセージをキューに戻すと異常が繰り返し発生することになります
異常が発生したメッセージを保存しておく場所としてデッドレターキューを作ります

[キュー] → [Lambda(異常)] → [デッドレターキューにメッセージ入れる]

デッドレターキューにメッセージを入れるにはLambdaで例外をスローして処理を終了する必要があります
pythonを例にするとraise Exceptionでfunctionの処理を終了すると自動的にメッセージがデッドレターキューに入ります

さいごに

最近、AWSがLambdaに力を入れていると思いますので、もっとサーバレスなアーキテクチャを選択することが増えてくることになると思っています
気軽に使えるのは間違いないのですが、Lambdaの仕様(クセ?)がもちろんあるので、理解しながら開発を進めて行くのが大事だと感じています
今後もLambdaに触れる機会はどんどん増えるので、そこで経験した知見やしくじりを書いていこうと思います

27
21
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
27
21

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?