SQS 対 SNS 対 EventBridge: いつどの AWS サービスを使用するか
3 つの AWS サービス、3 つの異なる哲学。 SQS はキューです。すべてのメッセージがキューであることを保証します。 唯一の消費者によって処理されます。 SNS それはファンアウトパブ/サブです: それを届けてください すべての加入者に同じメッセージを並行して送信します。 イベントブリッジ それはスマートルーターです: コンテンツに基づいてイベントをルーティングします。間違ったサービスを選択すると、アーキテクチャが脆弱になることを意味します。 コストが高く、メッセージが予期せず失われたり重複したりする可能性があります。
Amazon SQS: メッセージキュー
Amazon シンプル キュー サービス (SQS) は管理されたメッセージ キューです。 プロデューサはキューにメッセージを送信し、コンシューマはポーリングを通じてメッセージを取得します。 基本的なセマンティクスは次のとおりです ポイントツーポイント: キュー内のメッセージ 一度に 1 人の消費者によって読み取られます (最初に受け取った消費者が他の消費者からそれを「隠します」 を介して 可視性タイムアウト).
標準キューと FIFO キューの比較
SQS は 2 つのモードを提供します。
- 標準キュー: 無制限のスループット、少なくとも 1 回の配信 (重複可能)、ベストエフォート型の注文 (保証されません)。大規模なユースケース向け 重複は消費者側で管理可能です。
-
FIFOキュー: 1 回限りの配信 (自動重複排除による)
MessageDeduplicationId)、 保証されたソート メッセージグループ、スループットはリクエストごとに 3,000 msg/s に制限されます (バッチ処理あり)。順序付けと重複が重要なユースケース (金融取引など)。
// SQS Producer Java con AWS SDK v2
import software.amazon.awssdk.services.sqs.*;
import software.amazon.awssdk.services.sqs.model.*;
public class SqsProducer {
private final SqsClient sqsClient = SqsClient.builder()
.region(Region.EU_WEST_1)
.build();
// Standard Queue: invio semplice
public void sendToStandardQueue(String queueUrl, String messageBody) {
SendMessageResponse response = sqsClient.sendMessage(
SendMessageRequest.builder()
.queueUrl(queueUrl)
.messageBody(messageBody)
// Delay di consegna (0-900 secondi)
.delaySeconds(0)
// Attributi del messaggio per filtraggio (SNS subscription filter)
.messageAttributes(Map.of(
"eventType", MessageAttributeValue.builder()
.stringValue("OrdineCreato")
.dataType("String")
.build()
))
.build()
);
System.out.println("Messaggio inviato: " + response.messageId());
}
// FIFO Queue: richiede MessageGroupId e MessageDeduplicationId
public void sendToFifoQueue(String queueUrl, String ordineId, String payload) {
sqsClient.sendMessage(
SendMessageRequest.builder()
.queueUrl(queueUrl) // url deve terminare in .fifo
.messageBody(payload)
// Group: tutti i messaggi dello stesso ordine vengono elaborati in ordine
.messageGroupId("ordine-" + ordineId)
// Deduplication: prevenzione duplicati (valido 5 minuti)
.messageDeduplicationId(ordineId + "-" + System.currentTimeMillis())
.build()
);
}
}
SQS コンシューマ: ポーリングと可視性のタイムアウト
// SQS Consumer con Long Polling e gestione DLQ
public class SqsConsumer {
private final SqsClient sqsClient = SqsClient.builder()
.region(Region.EU_WEST_1).build();
public void poll(String queueUrl) {
while (true) {
// Long polling: aspetta fino a 20 secondi per nuovi messaggi
// Riduce le chiamate vuote (e i costi) rispetto al short polling
ReceiveMessageResponse response = sqsClient.receiveMessage(
ReceiveMessageRequest.builder()
.queueUrl(queueUrl)
.maxNumberOfMessages(10) // max 10 per chiamata
.waitTimeSeconds(20) // long polling
.visibilityTimeout(30) // 30s per elaborare
.messageAttributeNames("All")
.build()
);
for (Message message : response.messages()) {
try {
processMessage(message.body());
// Successo: elimina dalla coda
sqsClient.deleteMessage(
DeleteMessageRequest.builder()
.queueUrl(queueUrl)
.receiptHandle(message.receiptHandle())
.build()
);
} catch (Exception e) {
// Non eliminare: SQS rirenderà visibile il messaggio
// dopo il visibility timeout. Dopo maxReceiveCount tentativi
// finisce nella DLQ configurata
System.err.println("Errore, il messaggio tornera visibile: " + e.getMessage());
}
}
}
}
}
Amazon SNS: ファンアウト Pub/Sub
Amazon シンプル通知サービス (SNS) パターンを実装します パブリッシュ/サブスクライブ: プロデューサーがメッセージを投稿する SNSの話題をSNSで並行して皆様にお届けします メンバー(加入者)。 SNS トピックには数千の購読者が含まれる場合があります。 Lambda、SQS、HTTP エンドポイント、電子メール、SMS、モバイル プッシュ。
SNS + SQS パターン (SNSファンアウト) は最も一般的なパターンの 1 つです AWS アーキテクチャ: SNS は同じイベントを複数の SQS キューに並行して配信します。 そして、各キューは異なるコンシューマー (異なるマイクロサービス) にサービスを提供します。
# SNS + SQS Fan-Out: un evento raggiunge 3 servizi in parallelo
# Struttura:
# SNS Topic "ordini-topic"
# |--- SQS "inventario-queue" --- Lambda inventario
# |--- SQS "pagamenti-queue" --- Lambda pagamenti
# |--- SQS "notifiche-queue" --- Lambda notifiche email
# Terraform
resource "aws_sns_topic" "ordini" {
name = "ordini-topic"
}
resource "aws_sqs_queue" "inventario" {
name = "inventario-queue"
visibility_timeout_seconds = 60
redrive_policy = jsonencode({
deadLetterTargetArn = aws_sqs_queue.inventario_dlq.arn
maxReceiveCount = 3
})
}
resource "aws_sns_topic_subscription" "ordini_inventario" {
topic_arn = aws_sns_topic.ordini.arn
protocol = "sqs"
endpoint = aws_sqs_queue.inventario.arn
# Filter policy: questa subscription riceve SOLO OrdineCreato
filter_policy = jsonencode({
eventType = ["OrdineCreato"]
})
}
// SNS Publisher Java
import software.amazon.awssdk.services.sns.*;
import software.amazon.awssdk.services.sns.model.*;
public class SnsPublisher {
private final SnsClient snsClient = SnsClient.builder()
.region(Region.EU_WEST_1).build();
public void publishOrdineCreato(String topicArn, OrdineCreato event) throws Exception {
String messageJson = new ObjectMapper().writeValueAsString(event);
PublishResponse response = snsClient.publish(
PublishRequest.builder()
.topicArn(topicArn)
.message(messageJson)
// Message attributes per subscription filter
.messageAttributes(Map.of(
"eventType", MessageAttributeValue.builder()
.stringValue("OrdineCreato")
.dataType("String")
.build()
))
// Subject visibile solo nelle email
.subject("Nuovo ordine: " + event.getOrdineId())
.build()
);
System.out.println("SNS Message ID: " + response.messageId());
}
}
完全な比較
| 特性 | SQS | SNS | イベントブリッジ |
|---|---|---|---|
| モデル | ポイントツーポイント (キュー) | ファンアウト (パブ/サブ) | コンテンツベースのルーティング |
| 受信者 | 一度に 1 人の消費者 | すべて並行して登録されています | ルールによるターゲット (1-5) |
| フィルター | 誰も(すべてを奪う) | メッセージ属性 (限定的) | 任意の JSON フィールドのイベント パターン |
| 仕分け | 保証されたFIFO(FIFOキュー) | No | No |
| 重複排除 | はい (FIFO キュー) | No | No |
| 最大。スループット | 無制限(標準) | 無制限 | リージョンあたり 1,000 万イベント/秒 |
| レイテンシ | ミリ秒 (ポーリング) | < 1s (プッシュ) | < 500ms |
| スキーマレジストリ | No | No | はい (統合) |
| イベントアーカイブ/リプレイ | No | No | Si |
| パートナー統合SaaS | No | No | はい (パートナー 35 名以上) |
| 100 万メッセージあたりのコスト | ~0.40ドル | ~0.50ドル | ~$1.00 |
意思決定ガイド: いつどれを使用するか
次の場合に SQS を使用します。
- 必要がある 負荷分散 同じタイプの複数のコンシューマー間 (例: 同じキューを処理する 5 つの Lambda)
- メッセージを詳しく説明する必要がある ちょうど一度だけ (FIFOキュー)
- 必要がある 背圧: コンシューマが遅いとメッセージがキューに溜まる
- 欲しいですか? 配達遅延 (1メッセージあたり最大15分)
- 従来のキュー モデルを使用するレガシー システムを統合している場合
SNS は次のような場合に使用します。
- 同じイベントが到達する必要があります 複数のシステムを並行して実行する (ファンアウトパターン)
- 送信する必要があります 通知 (電子メール、SMS、モバイルプッシュ、HTTP Webhook)
- SNS と SQS を組み合わせて、各コンシューマのファンアウトとバッファリングの両方を実現
次の場合に EventBridge を使用します。
- 必要がある インテリジェントルーティング ペイロードの内容に基づいて
- と統合する AWSのサービス (EC2、S3、RDS) または SaaSパートナー (Zendesk、Shopify、Stripe)
- あなたはそれが欲しいです スキーマレジストリ およびスキームガバナンス
- 必要がある イベントのアーカイブとリプレイ
- を構築する 企業イベントバス 集中ルーティングを使用する
SNS + SQS + ラムダ パターン: 完全なスタック
# Architettura tipica per un microservizio event-driven su AWS
#
# Client HTTP
# |
# v
# API Gateway / Lambda "ordini-api"
# | pubblica su
# v
# SNS Topic "ordini-events"
# |-- filtra "OrdineCreato" --> SQS "inventario-queue" --> Lambda "inventario-handler"
# |-- filtra "OrdineCreato" --> SQS "notifiche-queue" --> Lambda "email-notifier"
# |-- tutti i tipi --> SQS "audit-queue" --> Lambda "audit-logger"
#
# Ogni SQS ha la sua DLQ per messaggi non elaborabili
# Le Lambda usano le SQS come event source (SQS trigger)
# Configurazione Lambda con SQS trigger
resource "aws_lambda_event_source_mapping" "inventario" {
event_source_arn = aws_sqs_queue.inventario.arn
function_name = aws_lambda_function.inventario_handler.arn
batch_size = 10 # processa 10 messaggi alla volta
enabled = true
# Bisection on error: in caso di errore batch, divide il batch a meta
# per identificare il messaggio problematico (evita il poison pill)
bisect_batch_on_function_error = true
# Finestra di aggregazione (utile per batch processing)
maximum_batching_window_in_seconds = 5
}
EventBridge + SQS: 両方の長所
多くのアーキテクチャでは、EventBridge と SQS は補完的です。 EventBridge はインテリジェントなルーティングを行い、SQS はバッファリングと負荷分散を行います。 イベントは EventBridge に到着し、適切な SQS キューにルーティングされます。 そしてコンシューマー Lambda は、再試行と DLQ を使用してキューからそれを処理します。
# EventBridge --> SQS (con transform di input opzionale)
resource "aws_cloudwatch_event_target" "ordini_to_sqs" {
rule = aws_cloudwatch_event_rule.ordini_vip.name
event_bus_name = aws_cloudwatch_event_bus.mioapp.name
arn = aws_sqs_queue.vip_orders.arn
# Input transformer: ristruttura il payload prima di inviarlo a SQS
# Utile per estrarre solo i campi necessari
input_transformer {
input_paths = {
ordineId = "$.detail.ordineId"
clienteId = "$.detail.clienteId"
totale = "$.detail.totale"
}
input_template = <<-EOF
{
"ordineId": "<ordineId>",
"clienteId": "<clienteId>",
"totale": "<totale>",
"processato_da": "eventbridge-vip-rule"
}
EOF
}
}
シリーズの次のステップ
- 第 8 条 – デッドレターキューと回復力: 正しい構成 SQS、SNS、および EventBridge の DLQ は、メッセージ損失を回避するために重要です。 可視性タイムアウト、maxReceiveCount、および再処理パターン。
他シリーズとの連携
- AWS EventBridge (第 6 条): イベントパターンの詳細な分析、 スキーマ レジストリとイベント アーカイブ、すべての EventBridge 構成の詳細。
- Apache Kafka (シリーズ 38): オンプレミスまたは非常に高スループットのユースケース向け (>1,000 万 msg/s)、Kafka は SQS/SNS よりも優れています。選択はクラウドプロバイダーによって異なりますが、 スループットとイベント再生の必要性によって異なります。







