SNS + SQS — メッセージング

概要

SNS (Simple Notification Service)SQS (Simple Queue Service) は AWS の 2 大メッセージング基盤。 システム間を疎結合にする、非同期処理を導入する、再試行や負荷平準化を行う、といった目的で使い分けます。

両者を組み合わせる「Fanout パターン」(SNS → 複数 SQS)が定番。

SNS の主な機能

SQS の主な機能

SNS vs SQS の使い分け

シナリオ選択理由
1 メッセージ → 複数の処理SNS (+ SQS)Fanout が前提
負荷平準化したいSQSConsumer が自分のペースで pull
順序保証が必要FIFO Topic + FIFO QueueStandard では順序保証無し
失敗リトライ + DLQSQSDLQ 機能で再処理を制御
Email / Mobile 通知SNSSNS が Subscriber 種別豊富
CloudWatch Alarm の通知先SNSAlarm から SNS Topic へが標準

使うべきパターン

使わない方が良いパターン

Terraform 最小サンプル(SNS Fanout + SQS + DLQ)

# SNS Topic
resource "aws_sns_topic" "events" {
  name = "events"
}

# DLQ
resource "aws_sqs_queue" "worker_dlq" {
  name = "worker-dlq"
}

# Worker Queue
resource "aws_sqs_queue" "worker" {
  name                       = "worker"
  visibility_timeout_seconds = 60
  message_retention_seconds  = 1209600   # 14 日
  redrive_policy = jsonencode({
    deadLetterTargetArn = aws_sqs_queue.worker_dlq.arn
    maxReceiveCount     = 3
  })
}

# SQS が SNS を購読
resource "aws_sns_topic_subscription" "worker" {
  topic_arn = aws_sns_topic.events.arn
  protocol  = "sqs"
  endpoint  = aws_sqs_queue.worker.arn
}

# SNS から SQS への送信を許可する Queue Policy
resource "aws_sqs_queue_policy" "worker" {
  queue_url = aws_sqs_queue.worker.id
  policy = jsonencode({
    Version = "2012-10-17"
    Statement = [{
      Effect    = "Allow"
      Principal = { Service = "sns.amazonaws.com" }
      Action    = "sqs:SendMessage"
      Resource  = aws_sqs_queue.worker.arn
      Condition = {
        ArnEquals = { "aws:SourceArn" = aws_sns_topic.events.arn }
      }
    }]
  })
}

# Lambda トリガ
resource "aws_lambda_event_source_mapping" "worker" {
  event_source_arn = aws_sqs_queue.worker.arn
  function_name    = aws_lambda_function.worker.arn
  batch_size       = 10
}

用語集

Topic / Subscription
SNS の 2 主要要素。Topic = 送信先カテゴリ、Subscription = 受信先設定。
Pub/Sub
Publish/Subscribe パターン。1 メッセージを複数の Subscriber に同時配信する設計。
Fanout
SNS → 複数 SQS への配信パターン。Producer は SNS に送るだけで複数の処理パイプを起動可能。
Standard / FIFO
Standard = 高スループット・順序保証なし。FIFO = 順序保証 + Exactly-Once、ただしスループット制限あり。
Visibility Timeout
Consumer が message を取った後、他 Consumer に見えなくする期間。Lambda timeout より長くする。
Dead Letter Queue (DLQ)
maxReceiveCount を超えたメッセージを退避する別キュー。失敗メッセージの可視化と手動再処理に。
Long Polling
SQS の受信を最大 20 秒待つことで API 呼び出し回数を削減する仕組み。
Filter Policy
SNS Subscriber 側でメッセージ属性を見て受信可否を判定する仕組み。
Lambda Event Source Mapping
SQS / Kinesis / DynamoDB Stream を Lambda のトリガに紐付ける仕組み。