SAA対策
SQS・SNS・EventBridgeで疎結合設計を理解する
SAAで重要な疎結合設計について、SQS、SNS、EventBridgeの役割と使い分けを整理します。
SAAでは、システムを疎結合にする設計がよく問われます。その代表サービスがSQS、SNS、EventBridgeです。
結論
SQSはキュー、SNSはPub/Sub通知、EventBridgeはイベントルーティングです。システム同士を直接つなぎすぎないことで、障害に強く拡張しやすい構成になります。
疎結合とは
疎結合とは、コンポーネント同士の依存を弱くする設計です。AサービスがBサービスを直接呼び出す構成だと、Bが遅いとAも影響を受けやすくなります。
たとえば注文APIが在庫更新、メール送信、分析記録を同期で呼び出すと、いずれかの処理遅延や一時障害が注文完了まで波及します。間にキューやイベントを挟むと、処理を非同期化でき、片方の障害が全体停止に直結しにくくなります。送信側は受け手の実装詳細を知らずに済み、後から処理を追加する余地も残せます。
SQSの役割
SQSはメッセージキューです。処理待ちのメッセージを一時的にため、後続のコンシューマーが取り出します。急なリクエスト増加でも、受信側が処理できる速度に合わせて消費できるため、処理能力の差を吸収するバッファとして使えます。
画像変換、注文処理、バッチ処理など、処理を非同期にしたい場面で使います。メッセージは重複して届く可能性を前提に、コンシューマー側は同じメッセージを再実行しても結果が壊れないように設計します。SQSの基本的な仕組みはAWS公式のAmazon SQSの説明も参照してください。
失敗時はDLQと再試行を設計する
処理に失敗したメッセージを無期限に再試行すると、正常な後続処理を妨げることがあります。再試行回数や待機時間は処理の性質に合わせ、繰り返し失敗するメッセージはDead-Letter Queue(DLQ)へ退避します。DLQを監視し、原因を修正してから必要なメッセージだけを再処理する流れまで決めておくことが重要です。
SNSの役割
SNSは通知のPub/Subサービスです。1つのメッセージを複数の購読先へ配信できます。
メール通知、Lambda起動、SQSへの配信など、同じ通知を複数方向へ広げたいときに使います。たとえば「注文確定」を受けて、メール送信用キューと分析用キューへそれぞれ渡すfanout構成では、購読先ごとに処理速度や障害を分離できます。
EventBridgeの役割
EventBridgeはイベントバスです。AWSサービス、SaaS、独自アプリから発生するイベントをイベントパターンのルールで振り分けます。サービス名やイベント種別、詳細フィールドに応じて、必要なターゲットだけを起動できます。
定期実行にも使えるため、毎日1問配信のような機能ではEventBridge + Lambdaの構成が候補になります。独自ドメインイベントを使うと、送信側は「何が起きたか」を発行し、受信側は必要なイベントだけを購読できます。Amazon EventBridgeの公式ドキュメントでイベントバスとルールの関係を確認すると整理しやすくなります。
どのサービスを選ぶか
| 要件 | 第一候補 | 判断の理由 |
|---|---|---|
| 受信側の処理速度の差を吸収したい | SQS | メッセージをため、コンシューマーが自分の速度で処理できる |
| 同じ通知を複数の受信先に配りたい | SNS | 1回の発行を複数の購読先へ配信できる |
| イベント内容で柔軟に振り分けたい | EventBridge | ルールでイベントを選別し、AWSサービスやアプリへ送れる |
実際には、SNSから複数のSQSキューへ配信する、EventBridgeのルールからSQSへ渡す、といった組み合わせもあります。まず「バッファリング」「一斉配信」「イベントによるルーティング」のどれが主目的かを決めると選択しやすくなります。
設計時に確認する順番
サービス名から選ぶと、「イベントだからEventBridge」「通知だからSNS」と短絡しやすくなります。先に送信側、受信側、失敗時の振る舞いを順番に整理します。
まず、送信側は受信処理の完了を待つ必要があるかを確認します。待たなくてよい処理なら、同期API呼び出しではなくメッセージやイベントで引き渡せます。次に、同じ情報を受け取る処理が1つか複数かを考えます。受信先が増減し、送信側を変更したくない場合には、SNSのトピックやEventBridgeのイベントバスが候補になります。
さらに、受信側が処理できない時間帯や一時的な急増を想定します。処理を確実に後回しにしたいならSQSを置き、消費側のLambdaやワーカーを段階的に増やせるようにします。イベント内容の属性によって、複数のAWSサービスや別チームのアプリケーションへ振り分けたいなら、EventBridgeのルールが適します。
最後に、メッセージが一度で処理されない前提を明確にします。外部APIの応答待ち、データ形式の不備、受信先の一時停止など、失敗の理由はさまざまです。どの失敗を自動再試行し、どの失敗をDLQへ送って人が調査するかを分けることで、障害時に同じメッセージが循環し続ける事態を避けられます。
具体例: 注文後処理を分離する
注文を受け付けるAPIが、決済結果の記録、在庫更新、購入者への連絡、売上分析までを1回のリクエストで完了させようとすると、後段の処理が増えるほど応答時間と障害影響が読みにくくなります。この場合、注文APIは必要な同期確認だけを終え、注文確定イベントを発行する設計を検討できます。
メール通知と分析記録のように複数の処理へ同じ事実を配るなら、SNSまたはEventBridgeを起点にします。メール送信が一時的に遅れても注文確定を失敗にしないため、通知用のSQSを購読先に置く方法があります。注文種別や金額帯などイベント内容で起動先を変えたい場合は、EventBridgeのルールで対象を選びます。処理順序が要件なら、標準キューではなくSQS FIFOキューを選び、同じ順序で処理したい単位をMessageGroupIdでそろえます。
この例で重要なのは、SNS、SQS、EventBridgeのどれか1つだけを正解にすることではありません。送信側に必要な応答、受信側の数、処理量の変動、失敗の扱いによって、役割を組み合わせます。SAAでも、要件にない機能を足した構成より、要求された性質を最も直接満たすサービスが選択肢になります。
メッセージ設計と監視
イベントやキューに渡すデータには、何が起きたか、いつ起きたか、対象を一意に識別する値を含めます。ただし、受信側だけが必要とする詳細まで送信側が抱え込むと、イベント形式の変更が多くの受信側へ影響します。必要最小限のイベントを渡し、詳細が必要な処理では信頼できるデータソースを参照する方針も検討します。
監視では、キューに処理待ちが蓄積していないか、DLQにメッセージが到達していないか、処理エラーが継続していないかを見ます。メッセージ数だけでは原因が分からないため、処理時間、失敗理由、対象IDを追えるログも必要です。監視のしきい値や保持期間はワークロードによって変わるため、固定値として覚えるよりも、利用者への影響が出る前に検知できるかを基準に調整します。
選択肢を読むときの判断軸
SAAの問題文で「疎結合」「受信側の障害を吸収」「急増したリクエストを後で処理」とあれば、まずSQSを候補にします。「同じ通知を複数の購読先へ」「配信先を追加しても送信側を変えない」とあればSNSのfanoutが有力です。「イベントパターンで条件分岐」「AWSサービスのイベントを別サービスへ連携」とあればEventBridgeを検討します。
一方で、同期応答が必須の処理をSQSだけで置き換えても、呼び出し元が直ちに結果を受け取る要件は満たせません。FIFOなどの順序性、重複排除、配信保証の細部も、問題文で要求されているときに初めて比較します。FIFOキューでも順序はMessageGroupIdごとの範囲であり、コンシューマー側では同じ処理が再実行されても壊れない冪等性を持たせます。まず非同期化の目的を読み取り、必要な制約を追加で満たす構成を選びます。
非同期処理で利用者へ結果を返す方法
非同期化した処理では、受付時点で完了結果を返せない場合があります。利用者に進行状況を見せる必要があるなら、受付APIは処理IDを返し、別の取得APIで状態を確認できるようにする方法があります。完了時に通知を送る、画面側で一定間隔に状態を問い合わせるなど、利用者への伝え方は要件に応じて選びます。
このとき、キューに入ったことと業務処理が完了したことを混同しないことが重要です。送信成功は後段への引き渡しを示すだけで、在庫更新やメール送信の成功を意味しません。状態を保持する場所、失敗した場合の表示、再実行を誰が行うかを設計に含めると、障害時の問い合わせにも対応しやすくなります。
変更に強いイベントの作り方
イベントは将来の受信側も利用する契約です。いきなり既存の必須フィールドを削除したり、意味を変えたりすると、送信側とは別に運用されている受信側が失敗します。フィールドの追加は比較的安全でも、受信側は未知のフィールドを無視できる設計にしておく必要があります。
イベント種別、発生元、バージョンの扱いを決め、誰が形式を変更できるかを共有します。これは大規模な仕組みを最初から導入するという意味ではありません。少なくとも、送信側の都合だけで受信側の処理を壊さないという疎結合の原則を、データ形式にも適用します。
実装後の見直しポイント
最初は受信側が1つでも、処理を追加すると同期呼び出しが増えがちです。新しい処理を足すときは、送信元のコードを変更しないと追加できないか、失敗が元のリクエストを失敗させるかを確認します。後者なら、既存のキューやイベントバスに購読先を増やせないかを検討します。
ただし、すべてを非同期にする必要はありません。残高確認や入力検証のように、その場で結果がなければ次の操作に進めない処理は同期で行います。業務上の完了時点と、技術的に後回しにできる処理を切り分けることが、複雑にしすぎない疎結合設計につながります。
受信側を新設するときは、既存メッセージの形式、DLQの監視、アラートの担当を引き継げるかも確認します。イベントを発行するだけでは、失敗した処理を誰も見つけられない状態になり得ます。少量のイベントから始め、通常時と失敗時のログを確認してから対象を広げると、送信側への影響を抑えながら構成を育てられます。
SAAで混同しやすい点
- SQSは受信側がメッセージを取り出して処理するキューであり、複数サービスへの同報配信が主目的ではありません。
- SNSは通知のfanoutに向きますが、受信処理の負荷を吸収したい場合は購読先にSQSを置く構成を検討します。
- EventBridgeはイベント内容に基づくルーティングに強く、単純な処理待ち行列として選ぶサービスではありません。
- 非同期化しても処理失敗は消えません。冪等性、再試行、DLQ、監視をセットで考えます。
SAAで問われるポイント
- SQSは非同期キュー
- SNSは複数購読者への通知
- EventBridgeはイベントルーティングとスケジュール実行
- 疎結合は耐障害性と拡張性を高める
- 同期処理を非同期化する選択肢と、失敗時の再処理方法を考える
関連用語
次に読む記事
次に学ぶ内容
ブログ記事だけでなく、AWS用語集・サービス比較・模擬問題・構成図を組み合わせると、資格知識と実装イメージをつなげて理解できます。