Amazon SQS とは?キューの種類やメッセージの送受信を学ぼう
アプリケーションのコンポーネント間でデータをやり取りする際、送信側と受信側が直接つながっていると、どちらかが停止したときにデータが失われるリスクがあります。Amazon SQS はメッセージを一時的に保管するキューを提供し、コンポーネント間を疎結合にするマネージドサービスです。本記事では SQS の基本概念からキューの作成・メッセージの送受信手順まで説明します。
Amazon SQS とは
SQS(Simple Queue Service)は AWS が提供するフルマネージドなメッセージキューイングサービスです。送信側(プロデューサー)がキューにメッセージを送り、受信側(コンシューマー)がキューからメッセージを取り出すことで、コンポーネント同士を直接接続しないで非同期に通信できます。
キューはメッセージのバッファとして機能するため、受信側が一時的に停止していてもメッセージは失われないです。また、受信側を複数用意することで処理を分散させ、スループットを向上させることもできます。
Amazon Simple Queue Serviceとは? - Amazon Simple Queue Service
アプリケーションコンポーネントのデカップリングの信頼性、スケーラビリティ、費用対効果など、Amazon SQS を使用する利点について説明します。
主な特徴
SQS にはマネージドサービスならではの特徴があります。それぞれ把握しておきましょう。
| 特徴 | 概要 |
|---|---|
| フルマネージド | インフラの管理や冗長化は AWS が担うため、運用の手間が少ない |
| 高可用性 | メッセージは複数のアベイラビリティーゾーンに自動で複製されるため、単一障害点がない |
| 無制限のスループット | 標準キューはほぼ無制限の 1 秒あたりのメッセージ数(TPS)をサポートする |
| 柔軟な保持期間 | メッセージの保持期間は最短 1 分から最長 14 日の範囲で設定できる(デフォルトは 4 日) |
| 従量課金 | 送受信したメッセージ数に応じた課金で、毎月 100 万件のリクエストまでは無料枠がある |
一度取得したメッセージは可視性タイムアウトと呼ばれる期間中、他のコンシューマーからは見えなくなります。コンシューマーが処理完了後にメッセージを削除しないと、タイムアウト後に再度取得可能になり、再処理が発生する点に注意しましょう。
Amazon SQS の可視性タイムアウト - Amazon Simple Queue Service
コンシューマーによるメッセージの 2 回目の処理を防ぐために Amazon SQS で使用する可視性タイムアウトについて説明します。
似たサービスに Amazon SNS がありますが、役割が異なります。SNS は複数の購読者にメッセージを配信する Pub/Sub 型のサービスで、SQS はメッセージを一時的に蓄えるキュー型のサービスです。SNS と SQS を組み合わせて、SNS トピックにファンアウトした先に複数の SQS キューを紐づける構成もよく使われます。
また、SQS は Lambda のイベントソースとしても利用でき、キューにメッセージが届くと自動的に Lambda 関数を呼び出せます。ポーリング処理を自前で実装する必要がなくなるため、サーバーレスな構成と相性が良いサービスです。
キューの種類
SQS には標準キューと FIFO キューの 2 種類があります。用途に合わせて使い分けましょう。
| 項目 | 標準キュー | FIFO キュー |
|---|---|---|
| スループット | ほぼ無制限 | 最大 3,000 TPS(バッチ処理時) |
| メッセージ順序 | ベストエフォート(保証されない) | 厳密に FIFO 順序を保証 |
| 重複配信 | まれに重複することがある | 重複なし |
| ユースケース | ログ収集・通知・大量処理など | 注文処理・決済・在庫更新など |
標準キューはスループットを最優先するためメッセージの順序が保証されず、まれに同じメッセージが複数回配信されることがあります。処理の冪等性(同じ操作を複数回行っても結果が変わらない性質)を担保する設計にしておくと安全です。
FIFO キューはメッセージの順序と重複排除を保証しますが、スループットには上限があります。キュー名の末尾を .fifo にする必要があります。
Amazon SQS キュータイプ - Amazon Simple Queue Service
Amazon SQS の FIFO キュー、標準キュー、デッドレターキュー、遅延キューなど、さまざまなキュータイプに関する包括的な情報を提供します。
デッドレターキュー
処理に繰り返し失敗したメッセージを別のキューに移動させる仕組みがデッドレターキュー(DLQ)です。
コンシューマーが処理を失敗してメッセージを削除しない場合、可視性タイムアウト後にメッセージが再度取得可能になります。これが設定した最大受信数(maxReceiveCount)を超えると、メッセージは DLQ へ自動的に移動されます。DLQ に移動したメッセージを確認・再処理することで、問題のあるメッセージを追跡しやすくなります。
SQS コンソールには DLQ に移動したメッセージを元のキューに戻す「DLQ の再処理」機能もあります。
Amazon SQS でのデッドレターキューの使用 - Amazon Simple Queue Service
デッドレターキューについて説明します。デッドレターキューは、処理に失敗したメッセージの送信先となり、未消費のメッセージを分離するため、アプリケーションのデバッグに役立ちます。メッセージフローを効果的に...
メッセージの属性とサイズ制限
SQS のメッセージには本文以外に、送信元の情報や処理に必要な付加情報を含めるためのメッセージ属性を設定できます。属性はキーと値のペアで構成され、1 つのメッセージにつき最大 10 個まで指定できます。受信側は本文を解析しなくても属性だけを見て処理を振り分けられるため、メッセージの種類ごとに処理を分岐させたい場合に便利です。
メッセージ本文のサイズには上限があり、最大 1,048,576 バイト(1 MiB)までしか送信できないです。それを超えるデータを扱いたい場合は、本文には S3 オブジェクトへの参照だけを含め、実データは S3 に保存する構成にするのが一般的です。この仕組みは Amazon SQS Extended Client Library として SDK 側に用意されており、1 MiB を超えるメッセージを扱う際に活用できます。
Amazon Simple Queue Service
AWS CLI で SQS を使ってみる
AWS CLI を使ってキューの作成からメッセージの送受信・削除までの基本的な流れを体験してみましょう。
キューを作成する
まず標準キューを作成します。キューの作成には --queue-name でキュー名を指定します。
❯ aws sqs create-queue --queue-name exrecord-queue
{
"QueueUrl": "https://sqs.ap-northeast-1.amazonaws.com/123456789012/exrecord-queue"
}
以降のコマンドでこの URL を使うため、変数に保存します。
❯ QUEUE_URL="https://sqs.ap-northeast-1.amazonaws.com/123456789012/exrecord-queue"
なお、アカウント内に作成済みのキューは、以下のコマンドで一覧を取得できます。
❯ aws sqs list-queues
{
"QueueUrls": [
"https://sqs.ap-northeast-1.amazonaws.com/123456789012/exrecord-queue"
]
}
メッセージを送信する
キューにメッセージを送信します。--message-body に送信したい内容を文字列で指定します。
❯ aws sqs send-message \
--queue-url "$QUEUE_URL" \
--message-body "SQS からのテストメッセージです。"
{
"MD5OfMessageBody": "4b999f2b9ac63a0e8c4a2bea7ae2e12b",
"MessageId": "ca0330b3-c5e5-44d3-85a4-4062ef5dd0f5"
}
メッセージを受信する
キューからメッセージを取得します。取得したメッセージは可視性タイムアウト中は他のコンシューマーから見えなくなります。
❯ aws sqs receive-message --queue-url "$QUEUE_URL"
{
"Messages": [
{
"MessageId": "ca0330b3-c5e5-44d3-85a4-4062ef5dd0f5",
"ReceiptHandle": "AQEBwJnKyrHigUMZj...",
"MD5OfBody": "4b999f2b9ac63a0e8c4a2bea7ae2e12b",
"Body": "SQS からのテストメッセージです。"
}
]
}
メッセージが届いていないタイミングで receive-message を呼ぶと、即座に空の応答が返ります。これを避けたい場合は --wait-time-seconds でロングポーリングを有効にすると、指定した秒数だけメッセージの到着を待ってから応答するため、無駄なリクエストの回数を減らせます。
❯ aws sqs receive-message --queue-url "$QUEUE_URL" --wait-time-seconds 10
メッセージを削除する
処理が完了したらメッセージをキューから削除します。削除しないと可視性タイムアウト後に再度配信されます。
❯ aws sqs delete-message \
--queue-url "$QUEUE_URL" \
--receipt-handle "AQEBwJnKyrHigUMZj..."
キューの属性を確認する
キューの現在の設定や状態を確認したい場合は、get-queue-attributes を使います。--attribute-names All を指定すると、可視性タイムアウトやメッセージの保持期間、キュー内にあるメッセージ数などをまとめて確認できます。
❯ aws sqs get-queue-attributes --queue-url "$QUEUE_URL" --attribute-names All
{
"Attributes": {
"ApproximateNumberOfMessages": "0",
"VisibilityTimeout": "30",
"MaximumMessageSize": "1048576",
"MessageRetentionPeriod": "345600"
}
}
処理待ちのメッセージが溜まっていないか確認したいときは ApproximateNumberOfMessages の値をチェックするとよいです。
キューを削除する
不要になったキューを削除します。削除するとキュー内のメッセージもすべて消えるため、事前に処理が完了しているか確認しましょう。
❯ aws sqs delete-queue --queue-url "$QUEUE_URL"
まとめ
Amazon SQS の基本概念やキューの種類、AWS CLI での基本操作について説明しました。コンポーネント同士のつなぎ目を柔軟にし、システム全体の可用性を高めてくれるサービスなので、以下のポイントを押さえて非同期処理が必要な箇所に取り入れてみましょう。
- Amazon SQS はコンポーネント間を疎結合にするフルマネージドなメッセージキューイングサービス
- 標準キューはほぼ無制限のスループット、FIFO キューは順序保証と重複排除を提供する
- 可視性タイムアウト中は他のコンシューマーからメッセージが見えなくなる
- 処理に失敗し続けたメッセージはデッドレターキューに移動させることで追跡・再処理しやすくなる
- メッセージ本文には 1 MiB のサイズ上限があり、超える場合は S3 と組み合わせる構成を検討する
- ロングポーリングを使うと無駄なリクエストを減らせるため、コンシューマー側の実装で有効化しておくとよい