SQS, SNS, EventBridge: 언제 어떤 AWS 서비스를 사용해야 할까요?
세 가지 AWS 서비스, 세 가지 서로 다른 철학. SQS 대기열입니다. 모든 메시지가 단 한 명의 소비자가 처리합니다. SNS 팬아웃 펍/구독입니다: 전달하세요 모든 구독자에게 동일한 메시지를 동시에 보냅니다. 이벤트브리지 스마트 라우터입니다: 콘텐츠를 기반으로 이벤트를 라우팅합니다. 잘못된 서비스 선택은 취약한 아키텍처를 의미합니다. 높은 비용과 예상치 못한 메시지 손실 또는 중복.
Amazon SQS: 메시지 대기열
Amazon Simple Queue Service(SQS) 관리되는 메시지 대기열입니다. 생산자는 대기열에 메시지를 보내고 소비자는 폴링을 통해 메시지를 검색합니다. 기본 의미론은 다음과 같습니다. 지점 간: 대기열에 있는 메시지 한 번에 한 명의 소비자가 읽습니다(먼저 가져가는 사람이 다른 소비자에게 "숨깁니다"). 를 통해 공개 시간 초과).
표준 대기열과 FIFO 대기열
SQS는 두 가지 모드를 제공합니다.
- 표준 대기열: 무제한 처리량, 최소 1회 배송 (중복 가능), 최선을 다해 주문합니다(보장되지 않음). 대용량 사용 사례의 경우 소비자 측에서 중복을 관리할 수 있습니다.
-
FIFO 대기열: 딱 한 번만 전달(자동 중복 제거를 통해)
MessageDeduplicationId), 정렬 보장 메시지 그룹, 처리량은 요청당 3,000msg/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: 팬아웃 게시/구독
아마존 단순 알림 서비스(SNS) 패턴을 구현합니다 게시/구독: 생산자가 메시지를 게시합니다. SNS 주제, SNS는 모든 사람에게 동시에 전달합니다. 회원들 (구독자). SNS 주제에는 수천 명의 구독자가 있을 수 있습니다. Lambda, SQS, HTTP 엔드포인트, 이메일, SMS, 모바일 푸시.
SNS + SQS 패턴(SNS 팬아웃)은 가장 일반적인 패턴 중 하나입니다. 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만 개의 이벤트 |
| 숨어 있음 | 밀리초(폴링) | < 1초(푸시) | < 500ms |
| 스키마 레지스트리 | No | No | 예(통합) |
| 이벤트 보관/재생 | No | No | Si |
| 파트너 통합 SaaS | No | No | 예(35개 이상의 파트너) |
| 백만 메시지당 비용 | ~$0.40 | ~$0.50 | ~$1.00 |
결정 가이드: 언제 어느 것을 사용할 것인가?
다음과 같은 경우 SQS를 사용하세요.
- 당신은 로드 밸런싱 동일한 유형의 여러 소비자 간(예: 동일한 대기열을 처리하는 5개의 Lambda)
- 메시지는 정교해야 한다 정확히 한 번 (FIFO 대기열)
- 당신은 배압: 소비자가 느려지면 대기열에 메시지가 쌓입니다.
- 당신은 배송 지연 (단일 메시지당 최대 15분)
- 기존 대기열 모델을 사용하는 레거시 시스템을 통합하고 있습니다.
다음과 같은 경우 SNS를 사용하세요.
- 동일한 이벤트가 도달해야 합니다. 여러 시스템을 병렬로 (팬아웃 패턴)
- 당신은 보내야합니다 알림 (이메일, SMS, 모바일 푸시, HTTP 웹훅)
- SNS + SQS를 결합하여 각 소비자에 대한 팬아웃 및 버퍼링 기능 제공
다음과 같은 경우 EventBridge를 사용하십시오.
- 당신은 지능형 라우팅 페이로드의 내용을 기반으로
- 와 통합하다 AWS 서비스 (EC2, S3, RDS) 또는 SaaS 파트너 (Zendesk, Shopify, 스트라이프)
- 당신은 그것을 원한다 스키마 레지스트리 및 계획 거버넌스
- 당신은 이벤트 보관 및 재생
- 빌드 기업 이벤트 버스 중앙 집중식 라우팅
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 구성 세부 정보.
- 아파치 카프카(시리즈 38): 온프레미스 또는 매우 높은 처리량 사용 사례 (>1천만 msg/s), Kafka는 SQS/SNS보다 우수합니다. 선택은 클라우드 제공업체에 따라 다릅니다. 처리량 및 이벤트 재생의 필요성에 따라 결정됩니다.







