AWS上級 #5 EventBridge / SQS / SNS

読了 9分

#3 Lambda#4 API Gateway が同期呼び出しの領域だったなら、今回は 非同期 / イベント駆動 方式です。呼び出し元が結果を待たず、コンポーネント間がメッセージで緩く繋がるパターン。

AWS にこの領域のツールが 3 つ — SNS / SQS / EventBridge。3 つは似て見えますが強調点が違います。この記事でその違いを正確に分け、fan-out パターン、DLQ、冪等性のような運用ポイントまで一気に。

3 つの違い — 一行比較 #

SNSSQSEventBridge
モデルPub/Sub (push)Queue (pull)Event Bus (push、ルーティングルール)
受け手0〜N 購読者同時1 人だけ (1 メッセージに)0〜N (rule マッチに応じて)
保存即時 push、受け取らないと消える最大 14 日キューに保管rule マッチ即時 push
適した場合1 イベント → 複数の受け手作業キュー、バックプレッシャーイベントベースのルーティング (多重ソース)
統合Lambda、SQS、HTTP、Email、SMSLambda、ECS、EC2 (ポーリング)Lambda、SQS、SNS、ECS、Step Functions、… 25+

最もよく見るパターンを一行で:

3 つの構成の流れ
                    ┌──────────────┐
                    │              │
   生産者 ─→ SNS ─→ ├─→ SQS  ─→ Lambda
                    └─→ Lambda    Worker (長い処理)
   (1 イベント)        (即時 push)

   生産者 ─→ EventBridge ──┬─→ Lambda (ルール A マッチ)
   (多様なソース)           ├─→ Step Functions (ルール B)
                            └─→ SQS (ルール C)

SNS — Pub/Sub #

Topic に publish すると すべての購読者 に即時配信。

モデル #

SNS Topic
publish → Topic ──┬─→ 購読者 1 (Lambda)
                  ├─→ 購読者 2 (SQS)
                  ├─→ 購読者 3 (Email)
                  ├─→ 購読者 4 (HTTP endpoint)
                  └─→ 購読者 5 (SMS)

1 つのイベントが発生したときに 複数のコンポーネントが同時に知る必要がある 場合。

作る + Publish #

SNS
TOPIC_ARN=$(aws sns create-topic --name user-events \
  --query TopicArn --output text)

# Lambda 購読
aws sns subscribe \
  --topic-arn $TOPIC_ARN \
  --protocol lambda \
  --notification-endpoint arn:aws:lambda:ap-northeast-2:123456789012:function:on-user-event

# Email 購読 (確認メール後に有効化)
aws sns subscribe \
  --topic-arn $TOPIC_ARN \
  --protocol email \
  --notification-endpoint admin@example.com

# Publish
aws sns publish \
  --topic-arn $TOPIC_ARN \
  --message '{"userId":42,"action":"signup"}'

Standard vs FIFO #

  • Standard: ほぼ無限の処理量、順序保証なし重複可能
  • FIFO: グループ内順序保証、正確に 1 度配信。処理量制限 (3,000 msg/s with batching)

名前に .fifo 接尾辞必須、MessageGroupId 必須。

メッセージフィルタリング #

同じ Topic に publish されても購読者が一部だけ受け取るように:

フィルタポリシー
aws sns set-subscription-attributes \
  --subscription-arn $SUB_ARN \
  --attribute-name FilterPolicy \
  --attribute-value '{"event": ["signup", "purchase"]}'

publish 時の MessageAttributesevent が一致する場合のみ配信。

適した場合 #

  • 1 イベント → 複数処理 (メール、通知、分析、監査ログ)
  • Email / SMS / Mobile Push 通知
  • SQS fan-out の入口

SQS — Queue #

Queue にメッセージを入れると 1 人の 消費者 が polling で持っていって処理。

モデル #

SQS Queue
生産者 ─→ Queue ─→ 消費者 (Lambda / ECS Task)
                    pull (polling)

消費者が受け取るモデル — バックプレッシャー が自然に効きます。消費者が遅ければ Queue にメッセージが溜まり、その間生産者は影響なし。

作る + Send / Receive #

SQS
QUEUE_URL=$(aws sqs create-queue --queue-name jobs \
  --query QueueUrl --output text)

# Send
aws sqs send-message \
  --queue-url $QUEUE_URL \
  --message-body '{"job":"resize","key":"photo.jpg"}'

# Receive
aws sqs receive-message \
  --queue-url $QUEUE_URL \
  --max-number-of-messages 10 \
  --wait-time-seconds 20  # long polling

# Delete (処理完了後)
aws sqs delete-message \
  --queue-url $QUEUE_URL \
  --receipt-handle <handle>

Lambda と自動接続 #

Lambda に SQS をトリガーとして付ければ polling / 削除は Lambda インフラが自動。

SQS → Lambda
aws lambda create-event-source-mapping \
  --function-name process-jobs \
  --event-source-arn arn:aws:sqs:ap-northeast-2:123456789012:jobs \
  --batch-size 10 \
  --maximum-batching-window-in-seconds 5
Lambda ハンドラ
def handler(event, context):
    for record in event["Records"]:
        body = json.loads(record["body"])
        process_job(body)
    # 正常終了 → Lambda が自動でメッセージ削除
    # 例外 → メッセージはキューに残り visibility timeout 後に再試行

Visibility Timeout — 最も重要な設定 #

消費者がメッセージを受け取ると N 秒間他の消費者から見えないように なります。この時間内に処理 + 削除が終わらなければなりません。さもないと再びキューに浮かんで他の消費者が受け取る → 重複処理リスク

設定推奨
平均処理時間 1 秒Visibility Timeout 30 秒 (余裕)
平均処理時間 30 秒60〜90 秒
非常に長くなりうる処理change-message-visibility で処理中に延長

Standard vs FIFO #

SNS と同じ。

  • Standard: ほぼ無限の処理量、順序保証なし、at-least-once (まれに重複)
  • FIFO: グループ内順序、正確に 1 度 (MessageDeduplicationId)

Dead Letter Queue (DLQ) #

処理失敗したメッセージを別キューに送付。運用必須

DLQ セットアップ
# DLQ を作る
DLQ_URL=$(aws sqs create-queue --queue-name jobs-dlq \
  --query QueueUrl --output text)
DLQ_ARN=$(aws sqs get-queue-attributes \
  --queue-url $DLQ_URL --attribute-names QueueArn \
  --query 'Attributes.QueueArn' --output text)

# Main queue に redrive policy
aws sqs set-queue-attributes \
  --queue-url $QUEUE_URL \
  --attributes '{
    "RedrivePolicy": "{\"deadLetterTargetArn\":\"'"$DLQ_ARN"'\",\"maxReceiveCount\":\"3\"}"
  }'

3 回 retry 後に失敗 → DLQ に送付。DLQ のメッセージは人が分析 / 修正 / 再びキューに送る。

適した場合 #

  • 作業キュー (画像処理、メール送信、外部 API 呼び出し)
  • トラフィックスパイクの吸収
  • コンポーネント分離 (生産者が消費者の速度の影響を受けない)

EventBridge — Event Bus #

EventBridge は 複数のソースから入ってくるイベント複数のターゲット にルールベースでルーティング。

モデル #

EventBridge
イベントソース (S3、EC2 状態変更、外部 SaaS、自分のコード ...)
Event Bus (default またはユーザー定義)
    ├─ Rule A (パターン: source=aws.s3、eventName=ObjectCreated:Put)
    │     → Lambda
    ├─ Rule B (パターン: source=myapp、detail-type=user.signup)
    │     → SQS + Step Functions (両方ターゲット)
    └─ Rule C (cron: 毎日 03:00)
          → Lambda (バッチ作業)

2 種類のイベント #

1) AWS サービスイベント — AWS が自動 publish。

  • EC2 状態変更 (running → stopped)
  • S3 ObjectCreated
  • CodePipeline 段階完了

2) Custom イベント — 自分のコードが publish。

Custom イベント publish
aws events put-events --entries '[{
  "Source": "myapp.users",
  "DetailType": "user.signup",
  "Detail": "{\"userId\":42,\"plan\":\"pro\"}",
  "EventBusName": "default"
}]'

Rule を作る #

Rule (イベントパターンベース)
aws events put-rule \
  --name on-user-signup \
  --event-pattern '{
    "source": ["myapp.users"],
    "detail-type": ["user.signup"],
    "detail": {"plan": ["pro"]}
  }'

# ターゲット追加
aws events put-targets \
  --rule on-user-signup \
  --targets 'Id=1,Arn=arn:aws:lambda:ap-northeast-2:123456789012:function:welcome-pro'
Rule (cron / rate ベース — スケジューラ)
aws events put-rule \
  --name nightly-cleanup \
  --schedule-expression 'cron(0 18 * * ? *)'   # UTC 18:00 = JST 03:00

aws events put-targets \
  --rule nightly-cleanup \
  --targets 'Id=1,Arn=arn:aws:lambda:ap-northeast-2:123456789012:function:cleanup'

スケジューリングはより綺麗なツールとして EventBridge Scheduler が別にあります (200,000 個まで / cron または rate / 1 回または繰り返し)。新規プロジェクトでは Scheduler 優先。

Schema Registry / Pipes #

大規模なイベントエコシステムで:

  • Schema Registry: イベントのスキーマを登録 / 自動発見。コードジェネレータで型安全なクライアント
  • EventBridge Pipes: SQS / Kinesis / DynamoDB Streams → (オプションの enrichment / filter) → ターゲット

適した場合 #

  • AWS サービスイベントへの反応 (S3 アップロード → 処理)
  • ドメインイベントのルーティング (user.signup → 5 つの処理)
  • スケジューリング (cron) — Lambda + EventBridge Scheduler が標準
  • SaaS 統合 (Datadog、PagerDuty、Stripe 等のマネージド統合)

Fan-out パターン #

最もよくある運用パターンの 1 つ。1 イベント → 複数の非同期処理

SNS + SQS Fan-out
生産者 ─→ SNS Topic ──┬─→ SQS Queue A ─→ Lambda A
                      ├─→ SQS Queue B ─→ Lambda B
                      └─→ SQS Queue C ─→ Lambda C

なぜ SNS + SQS なのか? — Lambda を SNS に直接付けても良いですが SQS を 1 段挟むと:

  • 各処理のバックプレッシャーが独立 (B が遅くても A は影響なし)
  • 各処理の retry / DLQ が独立
  • Lambda が一時的に死んでもメッセージが SQS に 14 日まで保管

EventBridge も同じパターン — 1 イベントが複数ルールにマッチすれば複数ターゲットに同時配信。

冪等性 (Idempotency) の重要性 #

非同期システムの核心。同じメッセージを 2 度受け取っても結果が同じでなければならない

なぜ 2 度受け取るか:

  • SQS Standard は at-least-once — たまに重複
  • Visibility Timeout 内に処理を終えられないと再配信
  • Lambda 自動 retry (非同期呼び出し)
  • ネットワーク / クライアント再試行

パターン 1: 自然冪等な演算 #

# 冪等 (何度やっても結果同じ)
user.set_status("active")
s3.put_object(Bucket=b, Key=k, Body=data)

# 非冪等
user.add_credit(100)
queue.send(...)

可能なら自然冪等に設計。

パターン 2: ID + DB マーカー #

処理 ID 重複防止
def handler(event, context):
    msg = json.loads(event["body"])
    msg_id = msg["id"]

    # すでに処理した ID か?
    if redis.get(f"processed:{msg_id}"):
        return  # skip

    process(msg)
    redis.setex(f"processed:{msg_id}", 86400, "1")  # 1 日保管

Lambda Powertools の Idempotency がこのパターンを DynamoDB バックエンドで綺麗に。

パターン 3: FIFO Queue の deduplication #

MessageDeduplicationId またはコンテンツベース deduplication — 5 分以内に同じ ID なら自動拒否。

どのツールをいつ #

1 イベント、複数の受け手 #

SNS Fan-out (+ SQS を挟む) または EventBridge

EventBridge が豊富なルール / フィルタ / AWS サービス統合。シンプルな fan-out だけなら SNS+SQS。

作業キュー #

SQS

AWS サービスイベントへの反応 #

EventBridge (S3、EC2 等が自動 publish)

スケジューリング #

EventBridge Scheduler (または EventBridge Rule)

コンポーネント間の単純メッセージ (1:1) #

SQS

Email / SMS / Mobile Push #

SNS

外部 SaaS 統合 #

EventBridge (マネージド統合) または EventBridge Pipes

費用 — 短く #

価格
SQS100 万 request 当たり $0.40 (Standard)、$0.50 (FIFO)
SNSpublish 100 万当たり $0.50 (Email / SMS / Mobile は別途)
EventBridgepublish 100 万当たり $1.00 (custom イベント)、AWS 自体イベントは無料

月 1,000 万メッセージの SQS = $4。小さなワークロードは事実上無視。

よく出会う落とし穴 #

1) メッセージ重複処理 #

自然冪等でない演算 (決済 / クレジット追加等) を SQS Standard で。1 度の決済が 2 度の決済に。常に冪等パターン または FIFO。

2) Visibility Timeout のミス #

処理に 60 秒かかるのに Visibility Timeout 30 秒 → 処理中のメッセージが再びキューに浮かんで他の消費者が受け取る → 2 度処理。Visibility Timeout を処理時間 + 余裕に。

3) DLQ なし #

失敗したメッセージが永遠にキューに浮かぶ → CloudWatch アラームだけがうるさい。すべてのキューに DLQ + アラーム。DLQ 自体にもアラーム (DLQ にメッセージが入る = 人が見る必要)。

4) Lambda の SQS polling が高く見える #

Lambda が空のキューを高頻度でポーリング → SQS request 費用。long polling (WaitTimeSeconds=20) がデフォルトか確認。

5) EventBridge rule が増えすぎる #

ドメインイベント毎にルール / ルール / ルール → コンソールがカオス。ドメイン別に ユーザー定義 Event Bus (default ではない) を分離、IaC で管理。

6) SNS Email / SMS の用途 #

SNS の Email は見栄えが単調 (テキストだけ、From 変更困難) で Spam に分類されやすい。トランザクショナルメール (会員登録等) は Amazon SES が正解。SNS Email は運用者通知程度に。

7) 非同期処理結果をクライアントに知らせる方法 #

API → SQS → Lambda 処理後の結果をクライアントにどう? 2 つのパターン:

  • クライアントが polling (作業 ID で GET リクエスト)
  • WebSocket (API Gateway WebSocket API) で push

非同期システム設計時に最初に決める基準です。

まとめ #

今回つかんだもの:

  • 3 つの違い — SNS (pub/sub)、SQS (queue)、EventBridge (ルーティングルール)
  • SNS — Topic に publish、複数購読者に即時 push。Email / SMS / Mobile Push 統合
  • SQS — Queue + polling。Visibility Timeout が最も重要な設定
  • DLQ — すべてのキューに必須。maxReceiveCount 回失敗後に送付
  • Standard vs FIFO — Standard は at-least-once / 無限処理量。FIFO は順序 + 重複除去 + 処理量制限
  • EventBridge — AWS サービスイベント + custom イベント。ルールパターンでルーティング。Scheduler で cron
  • Fan-out パターン — SNS → 複数 SQS → 各 Lambda。バックプレッシャー / retry / DLQ が受け手毎に独立
  • 冪等性 — at-least-once 環境では必須。自然冪等 / DB マーカー / FIFO dedup
  • 選択ガイド — 1 イベント N 受信 (SNS / EventBridge)、作業キュー (SQS)、AWS イベント反応 (EventBridge)、スケジュール (EventBridge Scheduler)、Email (SES、SNS でない)
  • 費用 — すべて非常に安い。小さなワークロードは無視
  • 落とし穴 — 重複処理、Visibility Timeout ミス、DLQ 欠如、polling 費用 (long polling)、ルール暴走、SNS Email の用途、結果通知パターン

次回 — 秘密 / 設定 #

次のテーマは運用の真剣な一角 — パスワードと設定値をどこに保管するか です。

#6 Secrets Manager / Parameter Store では 2 つの違い、自動ローテーション、コードから取得、IaC との接続、費用比較まで — AWS のシークレット管理 2 つのツールを一気に整理します。

X