floci#Part02_SQSを試しましょう!

こちらは新しい記事シリーズでflociを利用しAWSの勉強を進めたいと思います。第2話はSQSの仕組み、そして動作を一緒に見てみましょう。

Reference Link

floci#Part01_Dockerから簡単に環境構築しよう!

My環境

こちらは自分の環境です。

threespc01@threespc01-MINI-S:~$ lscpu
Architecture: x86_64
CPU op-mode(s): 32-bit, 64-bit
Address sizes: 39 bits physical, 48 bits virtual
Byte Order: Little Endian

threespc01@threespc01-MINI-S:~$ cat /etc/os-release
PRETTY_NAME=”Ubuntu 24.04.1 LTS”
NAME=”Ubuntu”
VERSION_ID=”24.04″
VERSION=”24.04.1 LTS (Noble Numbat)”
VERSION_CODENAME=noble
ID=ubuntu
ID_LIKE=debian
HOME_URL=”https://www.ubuntu.com/”
SUPPORT_URL=”https://help.ubuntu.com/”
BUG_REPORT_URL=”https://bugs.launchpad.net/ubuntu/”
PRIVACY_POLICY_URL=”https://www.ubuntu.com/legal/terms-and-policies/privacy-policy”
UBUNTU_CODENAME=noble
LOGO=ubuntu-logo

SQS?

SQS(Simple Queue Service)はAWSが提供するメッセージキューサービスです。

システム間でメッセージを非同期にやり取りするための仕組みです。

基本的な仕組み

Producer(送信側)→ キュー → Consumer(受信側)

  • Producer → メッセージを送信する側(アプリ、サーバーなど)
  • キュー → メッセージを一時的に保管する場所
  • Consumer → メッセージを受信して処理する側(ワーカーなど)

重要な概念

Visibility Timeout

  • メッセージを受信すると、一定時間(デフォルト30秒)他のConsumerから見えなくなる
  • 二重処理を防ぐための仕組み
  • 処理成功 → delete-message で削除
  • 処理失敗 → そのまま終わる → タイムアウト後に再び受信可能

At least once delivery

  • メッセージは少なくとも1回は必ず届く
  • ただし稀に重複して届くこともあるので、受信側で冪等性(同じ処理を何度やっても結果が同じ)を考慮する必要がある

Dead Letter Queue(DLQ)

  • 何度も処理に失敗したメッセージを別のキューに移す仕組み
  • 問題のあるメッセージを隔離して後で調査できる

主なコマンド

操作

コマンド

キュー作成

aws sqs create-queue

メッセージ送信

aws sqs send-message

メッセージ受信

aws sqs receive-message

メッセージ削除

aws sqs delete-message

全件削除

aws sqs purge-queue

キュー削除

aws sqs delete-queue

処理の基本フロー

① キュー作成

② Producerがメッセージ送信

③ Consumerがメッセージ受信(Visibility Timeout開始)

④-a 処理成功 → delete-messageで削除

④-b 処理失敗 → そのまま終わる → タイムアウト後に再処理

SQSが向いているユースケース

  • 非同期処理(注文処理、メール送信など)
  • 複数のWorkerで並列処理したい場合
  • システム間の疎結合化(直接通信をなくしたい)
  • 負荷の平準化(急激なリクエスト増加をキューで吸収)

注意点

  • メッセージの順番は保証されない(FIFOキューを使えば保証される)
  • 範囲指定での削除はできない
  • 同じメッセージが複数回届く可能性がある(冪等性の考慮が必要)

キュー作成

こちらのコマンドでキューを作成します。

aws sqs create-queue \
–queue-name soup-quece

Done!

{
“QueueUrl”: “http://localhost:4566/000000000000/soup-quece”
}

キューにメッセージ送信

こちらのコマンドでsoup-queceキューにメッセージを送信します。

aws sqs send-message \
–queue-url http://localhost:4566/000000000000/soup-quece \
–message-body “Text11234”

Done!

{
“MD5OfMessageBody”: “e76a8be577944d2d8bb32d7643b9fdf2”,
“MessageId”: “045b33eb-6042-4c0b-b9b5-cafa1f2e11d9”
}

キューにメッセージ受信

こちらのコマンドでsoup-queceキューにメッセージを受信します。

threespc01@threespc01-MINI-S:~$ aws sqs receive-message –queue-url http://localhost:4566/000000000000/soup-quece

Done!メッセージが受信されました。

{
“Messages”: [
{
“MessageId”: “045b33eb-6042-4c0b-b9b5-cafa1f2e11d9”,
“ReceiptHandle”: “217f6501-7de1-42c1-a87a-61a43dd307be”,
“MD5OfBody”: “e76a8be577944d2d8bb32d7643b9fdf2”,
“Body”: “Text11234”,
“Attributes”: {
“ApproximateReceiveCount”: “4”,
“SentTimestamp”: “1778647299741”
}
}
]
}

もしすぐ同じコマンドでsoup-queceキューを受信したら…

threespc01@threespc01-MINI-S:~$ aws sqs receive-message –queue-url http://localhost:4566/000000000000/soup-quece

下記の通り、空メッセージが帰ってきました。

{
“Messages”: []
}

しばらく待つと…

threespc01@threespc01-MINI-S:~$ aws sqs receive-message –queue-url http://localhost:4566/000000000000/soup-quece

また同じメッセージが受信されました。

{
“Messages”: [
{
“MessageId”: “045b33eb-6042-4c0b-b9b5-cafa1f2e11d9”,
“ReceiptHandle”: “217f6501-7de1-42c1-a87a-61a43dd307be”,
“MD5OfBody”: “e76a8be577944d2d8bb32d7643b9fdf2”,
“Body”: “Text11234”,
“Attributes”: {
“ApproximateReceiveCount”: “4”,
“SentTimestamp”: “1778647299741”
}
}
]
}

複数のメッセージをキューに

今度は複数のメッセージを一気にキューに送信します。

threespc01@threespc01-MINI-S:~$ aws sqs send-message –queue-url http://localhost:4566/000000000000/soup-quece –message-body “Text_002”

threespc01@threespc01-MINI-S:~$ aws sqs send-message –queue-url http://localhost:4566/000000000000/soup-quece –message-body “Text_003”

threespc01@threespc01-MINI-S:~$ aws sqs send-message –queue-url http://localhost:4566/000000000000/soup-quece –message-body “Text_004”

複数のTerminal検証

次は複数のターミナルを起動し、メッセージの受信動作を確認します。

TerminalA

最初に1つ目のターミナルをキューからデータを取ります。

threespc01@threespc01-MINI-S:~$ aws sqs receive-message –queue-url http://localhost:4566/000000000000/soup-quece

ここで”Text_002”を受け取りました。

{
“Messages”: [
{
“MessageId”: “1b90a7ff-9c71-4ae8-abe3-257b9da27fae”,
“ReceiptHandle”: “5c9a7dc3-c1c7-4715-8a78-666b3179e67a”,
“MD5OfBody”: “3da03fdffac39298d3d4b538e5f49911”,
“Body”: “Text_002”,
“Attributes”: {
“ApproximateReceiveCount”: “1”,
“SentTimestamp”: “1778648757771”
}
}
]
}

TerminalB

次は別のターミナルからもう一度キューからメッセージを取ります。

threespc01@threespc01-MINI-S:~$ aws sqs receive-message –queue-url http://localhost:4566/000000000000/soup-quece

先程TerminalAが受け取った”Text_002”も受けることできず、次のメッセージ”Text_003”に取りました。

{
“Messages”: [
{
“MessageId”: “3884187c-3187-42ab-9d32-e0922af8c08e”,
“ReceiptHandle”: “29512a85-8785-4a05-81ce-3783d4b0af4c”,
“MD5OfBody”: “0be965851ec95baa03970fedf792cb37”,
“Body”: “Text_003”,
“Attributes”: {
“ApproximateReceiveCount”: “1”,
“SentTimestamp”: “1778648760072”
}
}
]
}

Visibility Timeout設定

では、先程受信したメッセージはいつからまた取得できるでしょうか?それはVisibility Timeout設定の設定に左右されます。短すぎると処理中に再び見えてしまい二重処理のリスクがあり、長すぎると失敗時のリカバリが遅くなります。

① キュー: [メッセージA] ← 見える状態

② Consumer A が receive-message

→ メッセージAが30秒間「非表示」になる

③ Consumer B が receive-message

→ 何も返ってこない(非表示中)

④-a Consumer Aが処理成功

→ delete-message → 完全に削除

④-b Consumer Aが処理失敗・クラッシュ

→ 30秒後に自動的に「見える」状態に戻る

→ Consumer Bが再処理できる

キュー作成時に設定

aws sqs create-queue \
–queue-name my-queue \
–attributes VisibilityTimeout=60

既存キューに設定

aws sqs set-queue-attributes
–queue-url http://localhost:4566/000000000000/my-queue \
–attributes VisibilityTimeout=60

メッセージを取り

次はメッセージを取り出します。

threespc01@threespc01-MINI-S:~$ aws sqs receive-message –queue-url http://localhost:4566/000000000000/soup-quece

{
“Messages”: [
{
“MessageId”: “045b33eb-6042-4c0b-b9b5-cafa1f2e11d9”,
“ReceiptHandle”: “5e23a047-2cee-4da1-a0c5-3b6df5cec70e”,
“MD5OfBody”: “e76a8be577944d2d8bb32d7643b9fdf2”,
“Body”: “Text11234”,
“Attributes”: {
“ApproximateReceiveCount”: “7”,
“SentTimestamp”: “1778647299741”
}
}
]
}

もちろん、すぐ同じメッセージ取り出すことはできません。

threespc01@threespc01-MINI-S:~$ aws sqs receive-message –queue-url http://localhost:4566/000000000000/soup-quece

{
“Messages”: [
{
“MessageId”: “1b90a7ff-9c71-4ae8-abe3-257b9da27fae”,
“ReceiptHandle”: “2aacf4bf-2c20-4357-bd51-afa4f4c1a993”,
“MD5OfBody”: “3da03fdffac39298d3d4b538e5f49911”,
“Body”: “Text_002”,
“Attributes”: {
“ApproximateReceiveCount”: “3”,
“SentTimestamp”: “1778648757771”
}
}
]
}

ですが、30sのTimeoutすぎると、また同じメッセージを取り出せます。

threespc01@threespc01-MINI-S:~$ aws sqs receive-message –queue-url http://localhost:4566/000000000000/soup-quece

{
“Messages”: [
{
“MessageId”: “045b33eb-6042-4c0b-b9b5-cafa1f2e11d9”,
“ReceiptHandle”: “8c9c11d0-66bc-4730-9202-aa9996c296c7”,
“MD5OfBody”: “e76a8be577944d2d8bb32d7643b9fdf2”,
“Body”: “Text11234”,
“Attributes”: {
“ApproximateReceiveCount”: “8”,
“SentTimestamp”: “1778647299741”
}
}
]
}

Dead Letter Queue(DLQ)

そもそもなぜDead Letter Queueが必要なのか?

通常のキューだと、壊れたメッセージや処理できないメッセージがキューを占領し続けてしまいます。

メッセージA → 処理失敗 → 30秒後に再処理
→ また失敗 → 30秒後に再処理
→ また失敗 → 30秒後に再処理
→ 永遠に繰り返す..

DLQがあると、正常なメッセージだけ処理継続できます。

通常キュー: メッセージA → 失敗
→ 失敗
→ 失敗(3回失敗)

DLQ: メッセージA を隔離
→ 後から調査・修正できる
通常キュー: 正常なメッセージだけ処理継続できます。

いつDLQを使いますか?

ユースケース

説明

データ不正

壊れたメッセージを隔離

バグ調査

失敗したメッセージを保存して後から分析

本番障害対応

問題のあるメッセージだけ別処理

失敗はどう判定?

SQSは「削除されたかどうか」だけを見ています。

受信 → Visibility Timeout以内にdelete-message → 成功(削除される)

受信 → Visibility Timeout以内にdelete-message無し → 失敗とみなす

つまり明示的に「失敗」と伝える必要はなく、削除しなければ自動的に失敗扱いになります。

ApproximateReceiveCountで失敗回数を追跡

1回目受信 → ApproximateReceiveCount: 1 → 失敗

2回目受信 → ApproximateReceiveCount: 2 → 失敗

3回目受信 → ApproximateReceiveCount: 3 → 失敗

maxReceiveCount=3ならDLQへ移動

DLQ用のキューを作成

aws sqs create-queue \
–queue-name my-queue-dlq

DLQのARNを取得

threespc01@threespc01-MINI-S:~$ aws sqs get-queue-attributes \
–queue-url http://localhost:4566/000000000000/my-queue-dlq \
–attribute-names QueueArn

DLQのキューのARNが取得できました。

{
“Attributes”: {
“QueueArn”: “arn:aws:sqs:us-east-1:000000000000:my-queue-dlq”
}
}

DLQのメッセージ確認

現在DLQキューのメッセージを確認します。

threespc01@threespc01-MINI-S:~$
aws sqs receive-message \
–queue-url http://localhost:4566/000000000000/my-queue-dlq \
–max-number-of-messages 10

{
“Messages”: []
}

通常キューにDLQを設定

現在使用するキューとDLQキューと接続し、最大Counterを3に設定します。

threespc01@threespc01-MINI-S:~$ aws sqs set-queue-attributes \
–queue-url http://localhost:4566/000000000000/soup-quece \
–attributes ‘{
“RedrivePolicy”: “{\”deadLetterTargetArn\”:\”arn:aws:sqs:us-east-1:000000000000:my-queue-dlq\”,\”m
axReceiveCount\”:\”3\”}”
}’

DLQのメッセージ確認

最後はMessageを複数回送信し、DLP キューには3回以上処理に失敗したメッセージが格納されます。

threespc01@threespc01-MINI-S:~$ aws sqs receive-message –queue-url http://localhost:4566/000000000000/my-queue-dlq –max-number-of-messages 10

{
“Messages”: [
{
“MessageId”: “045b33eb-6042-4c0b-b9b5-cafa1f2e11d9”,
“ReceiptHandle”: “7cc3fbd8-6fa5-4773-b442-8d337bbc8449”,
“MD5OfBody”: “e76a8be577944d2d8bb32d7643b9fdf2”,
“Body”: “Text11234”,
“Attributes”: {
“ApproximateReceiveCount”: “10”,
“SentTimestamp”: “1778647299741”
}
},
{
“MessageId”: “1b90a7ff-9c71-4ae8-abe3-257b9da27fae”,
“ReceiptHandle”: “a7ce2b1e-b8a9-451f-bbb4-3198189fe918”,
“MD5OfBody”: “3da03fdffac39298d3d4b538e5f49911”,
“Body”: “Text_002”,
“Attributes”: {
“ApproximateReceiveCount”: “5”,
“SentTimestamp”: “1778648757771”
}
}
]
}

基本コマンド list-queues

こちらのコマンドで現在存在しているキューをリストアップできます。

threespc01@threespc01-MINI-S:~$ aws sqs list-queues

{
“QueueUrls”: [
“http://localhost:4566/000000000000/my-queue”,
“http://localhost:4566/000000000000/soup-quece”,
“http://localhost:4566/000000000000/my-queue-dlq”
]
}

基本コマンド get-queue-attributes

こちらはあるキューの設定を読み出すことができます。

threespc01@threespc01-MINI-S:~$ aws sqs get-queue-attributes \
–queue-url http://localhost:4566/000000000000/soup-quece \
–attribute-names ApproximateNumberOfMessages

ApproximateNumberOfMessagesNotVisible
{
“Attributes”: {
“ApproximateNumberOfMessages”: “0”,
“ApproximateNumberOfMessagesNotVisible”: “0”
}
}

キューのメッセージ削除‐Purge

キュー内の全メッセージを一括削除するコマンドです。

threespc01@threespc01-MINI-S:~$ aws sqs purge-queue \
–queue-url http://localhost:4566/000000000000/soup-quece

最後は下記のコマンドでキューを確認すると、メッセージ残数が0になります。

threespc01@threespc01-MINI-S:~$ aws sqs get-queue-attributes –queue-url http://localhost:4566/000000000000/soup-quece –attribute-names

ApproximateNumberOfMessages
{
“Attributes”: {
“ApproximateNumberOfMessages”: “0”
}
}

キューごと削除‐delete-queue

最後は下記のコマンドでキューを削除します。

threespc01@threespc01-MINI-S:~$ aws sqs delete-queue \
–queue-url http://localhost:4566/000000000000/soup-quece

項目

purge-queue

delete-queue

メッセージ

削除

削除

キュー自体

残る

削除される

復元

不要

再作成が必要

下記のように、キューsoup-queceが削除されたことがわかりました。

threespc01@threespc01-MINI-S:~$ aws sqs list-queues
{
“QueueUrls”: [
“http://localhost:4566/000000000000/my-queue”,
“http://localhost:4566/000000000000/my-queue-dlq”
]
}

シェアする

  • このエントリーをはてなブックマークに追加

フォローする