Amazon SAA-C03: アプリケーション統合、メッセージング、ストリーミング — 学習ガイド
こちらの一部です: AWS SAA-C03 — 完全学習ガイド. 検証済みの解答で練習: Amazon試験ハブ, または時間制限付き模擬試験に挑戦: ExamRoll.io.
Amazon SQS: デカップリング、順序付け、配信セマンティクス
Amazon SQSは、フルマネージドのプル型メッセージキューであり、その主要なアーキテクチャ上の役割は、プロデューサーとコンシューマーを分離(デカップリング)することです。同期的な呼び出しチェーンは、プロデューサーのレイテンシーと可用性をすべての下流の依存関係に束縛します。SQSキューを間に挟むことで、これを非同期的なハンドオフに変換します。プロデューサーはトラフィックの到着レートに応じてエンキューし、コンシューマーは安全に処理できるレートでデキューします。これは、RDSインスタンスに過負荷をかける書き込みバーストに対する標準的な解決策です。キューがバーストを吸収し、限定された数のコンシューマー群が制御された同時実行数でキューを処理し、データベースの接続数を抑制します。
キューには2つのタイプがあり、どちらを選択するかによってスループットと配信保証の両方が決まります。
| 機能 | スタンダード | FIFO |
|---|---|---|
| 順序付け | ベストエフォート | MessageGroupId ごとに厳密 |
| 配信 | 少なくとも1回 (重複の可能性あり) | 5分間の重複排除ウィンドウ内で1回のみ |
| スループット | ほぼ無制限 | 300 TPS (バッチ処理で3,000); 高スループットモードで70,000 |
| キュー名 | 任意 | .fifoで終わる必要あり |
スタンダードキューは、少なくとも1回配信され、順序はベストエフォートでのみ保証されます。コンシューマーが可視性タイムアウトが切れる前にメッセージを削除できなかった場合や、分散バックエンドがシャード間でメッセージを再送した場合に、重複が発生する可能性があります。テストで重複が見られなかったとしても、特にブローカーのフェイルオーバー時には、サービスはアーキテクチャ上、再配信が許可されています。スタンダードキューが「通常は」1回だけ配信すると想定するのは、運用上のリスクではなく、設計上の欠陥です。大規模になると、重複は最終的に必ず発生します。したがって、コンシューマーのロジックはべき等である必要があります。具体的には、DynamoDBで条件付き書き込みを使いMessageIdやビジネスキーを追跡する、下流のAPI呼び出しでべき等キーを使用する、あるいはupsertセマンティクスに依存する、といった方法があります。
FIFOキューは、MessageGroupId内での厳密な順序付けと、MessageDeduplicationId(明示的に指定するか、本文のSHA-256ハッシュ)による1回のみの処理を提供し、5分間のウィンドウ内で重複を抑制します。MessageGroupIdが極めて重要な概念です。同じグループIDを共有するすべてのメッセージは、一度に1つのコンシューマーに厳密な順序で配信され、一方で異なるグループIDは並行して処理できます。各顧客のイベントはシーケンシャルである必要があるが、顧客間は独立している注文処理システムの場合、MessageGroupId = customerIdとします。すべてに単一のグループIDを使用すると、ワークロード全体が直列化され、スループットが損なわれます。重複排除IDは、ユーザーがハングしたチェックアウトを再送信した際の重複注文を防ぐための正しいプリミティブです。クライアントは決定論的なべき等性トークン(チェックアウトセッションに紐づくUUIDなど)を生成し、SQSはそのウィンドウ内に到着した重複した送信を破棄します。
PaymentsQueue:
Type: AWS::SQS::Queue
Properties:
QueueName: payments.fifo
FifoQueue: true
ContentBasedDeduplication: true
DeduplicationScope: messageGroup
FifoThroughputLimit: perMessageGroupId
VisibilityTimeout: 60
RedrivePolicy:
deadLetterTargetArn: !GetAtt PaymentsDLQ.Arn
maxReceiveCount: 5
要件で「順序付け」や「重複なし」が明記されているにもかかわらずスタンダードキューを選択するのは、典型的な誤りです。異なるバックエンドホストからのメッセージが入り混じって到着するため、キューが保持しなかった順序を、アプリケーションロジックで復元することは不可能です。ワークロードが順序付け(トランザクション台帳、ステートマシンの遷移)や1回のみのセマンティクス(支払いキャプチャ、在庫のデクリメント)を要求する場合は、必ずFIFOを選択してください。
可視性タイムアウト、ポイズンメッセージ、ペイロード制限
コンシューマーがメッセージを受信すると、SQSは可視性タイムアウト(デフォルト30秒、最大12時間)の間、そのメッセージを他のコンシューマーから見えなくします。コンシューマーがタイムアウトが切れる前にメッセージを削除すれば、メッセージは消去されます。そうでない場合、つまりコンシューマーがクラッシュしたり、処理に時間がかかりすぎたりした場合は、メッセージは再び可視になり、再配信されます。実際の処理時間よりも短い可視性タイムアウトを設定することは、重複処理の主な原因です。例えば、デフォルトの30秒タイムアウトのキューに対して45秒かかるLambdaは、すべてのメッセージを少なくとも2回再処理します。タイムアウトは、少なくともp99の処理時間に設定してください(Lambda駆動のキューに対するAWSのガイダンスは、関数タイムアウトの少なくとも6倍です)。また、処理時間が予測不能なジョブの場合は、タイムアウトを動的に延長します。
sqs.change_message_visibility(
QueueUrl=queue_url,
ReceiptHandle=handle,
VisibilityTimeout=300 # extend by 5 minutes
)
**デッドレターキュー(DLQ)**は、ポイズンピルメッセージ(処理できないメッセージ)をキャプチャします。ソースキューのRedrivePolicyでmaxReceiveCount(通常3〜5)を指定します。これを超えると、SQSはオフラインでの調査のためにメッセージをDLQに移動します。DLQはソースキューのタイプと一致させる必要があります(FIFO ↔ FIFO)。DLQがないと、不正な形式のメッセージは無限にループします。これはFIFOでは特に有害です。順序付けの性質上、問題のメッセージが処理されるまで、同じグループ内の後続メッセージの配信がブロックされるため、1つの不正なメッセージがグループ全体の処理を停止させます。
SQSメッセージは256 KBに制限されています。より大きなペイロード(例えば、レンダリングされたドキュメントを含むジョブなど)には、SQS Extended Client Libraryを使用します。これはペイロードをS3に書き込み、キューにはバケット/キーの参照のみをエンキューします。コンシューマーライブラリは受信時に透過的にペイロードを取得します。ペイロードを複数のメッセージに分割しないでください(原子性と順序性が失われます)。また、2MBのBLOBをbase64エンコードして収まることを期待しないでください。
キュー駆動のオートスケーリング
SQSキューの後ろにあるEC2やECS上のコンシューマー群にとって、正しいスケーリングシグナルはCPUではなく、キューのバックログです。CPUは到着レートに遅れて反応し、飽和状態のコンシューマーを「ビジーだが対処できている」と誤解します。標準的なスケーリングメトリクスはApproximateNumberOfMessagesVisibleですが、生のキューの深さで直接スケーリングするのは粗すぎます。推奨されるアプローチは、インスタンスあたりのバックログというカスタムメトリクスです。
backlogPerInstance = ApproximateNumberOfMessagesVisible / RunningInstances
これをCloudWatchに発行し、Auto ScalingグループやECSサービスのターゲット追跡ポリシーを駆動することで、各ワーカーが一定のバックログ(例:10メッセージ)を維持するようにします。これにより、バースト時にスムーズなスケールアウトが実現し、キューの深さが小さいがコンシューマーがすでに飽和している場合の振動を防ぎます。スケールインには、ApproximateAgeOfOldestMessageと組み合わせることで、古いメッセージが残っている間にキャパシティを終了させてしまうのを避けることができます。
Amazon SNS: ファンアウト、フィルタリング、クロスアカウント配信
SNSはプッシュベースのパブリッシュ/サブスクライブサービスです。パブリッシャーはトピックに書き込み、SNSはすべてのサブスクリプション(SQSキュー、Lambda関数、HTTP(S)エンドポイント、Eメール、SMS、Kinesis Data Firehose、モバイルプッシュ)にプッシュします。主要な耐久性パターンはSNS → SQSファンアウトです。これは、1つのトピックに複数のSQSキューをサブスクライブさせることで、各ダウンストリームサービスが独自の耐久性のあるバッファ、リトライポリシー、DLQを持つようにするものです。一方で、パブリッシャーはトピックのことだけを認識していれば済みます。コンシューマーサービスが数時間ダウンした場合、そのキューはメッセージを蓄積し、復旧時にそれを処理します。SNS単体ではこのようなバッファリング機能がなく、リトライポリシーを使い果たしてしまいます。
Producer ──▶ SNS topic ──┬──▶ SQS Queue A ──▶ Service A
├──▶ SQS Queue B ──▶ Service B
└──▶ SQS Queue C ──▶ Service C
メッセージフィルタリングにより、各サブスクリプションはJSONフィルターポリシーを宣言でき、SNSは一致するメッセージのみを配信します。これにより、すべてのコンシューマーがすべてのメッセージを受信してクライアント側でフィルタリングするというアンチパターンを回避できます。
{
"eventType": ["order_placed", "order_cancelled"],
"region": ["us-east-1", "us-west-2"]
}
2つの動作特性が重要です。第一に、標準SNSトピックはメッセージ間の順序を保証しません。サブスクライバーごとのリトライタイマーや独立したネットワークパスにより、順序の入れ替わりは日常的に発生します。順序が重要な場合は、SQS FIFOキューをサブスクライブしたSNS FIFOトピックを使用します。メッセージグループIDはエンドツーエンドで伝播します。そうでない場合、サブスクライバーはべき等であり、順序の入れ替わりに耐性を持つ必要があります。第二に、HTTP(S)サブスクリプションは配信ポリシーに従ってリトライします(デフォルト:3回の即時リトライ後、最大1時間までの指数関数的バックオフ、その後破棄)。サブスクライバーは15秒以内に2xxで応答し、x-amz-sns-message-type署名を検証し、信頼性の低いエンドポイントの場合は、配信されなかったメッセージがサイレントにドロップされるのではなく確実にキャプチャされるように、常にSNS DLQ(SQSにリドライブされる)を持つ必要があります。
クロスアカウント呼び出しはよくある落とし穴です。アカウントAがトピックに発行し、それがアカウントBのLambdaにファンアウトする場合、2つのポリシーが必要です。SNSトピックポリシー(またはサブスクリプションの方向)でサブスクリプションを許可する必要があり、かつLambdaのリソースベースのポリシーで、sns.amazonaws.comからのlambda:InvokeFunctionを、トピックに一致するSourceArn条件付きで許可する必要があります。Lambdaのリソースポリシーの欠落が最も一般的な失敗モードです。この場合、サブスクリプションは正常に見えますが、呼び出しは403で拒否されます。トピックがカスタマーマネージドKMSキーで暗号化されている場合、キーポリシーは発行元のプリンシパルとsns.amazonaws.comに対してkms:Decryptとkms:GenerateDataKeyも許可する必要があります。
{
"Effect": "Allow",
"Principal": {"Service": "sns.amazonaws.com"},
"Action": "lambda:InvokeFunction",
"Resource": "arn:aws:lambda:us-east-1:222222222222:function:ProcessOrder",
"Condition": {"ArnLike": {"AWS:SourceArn": "arn:aws:sns:us-east-1:111111111111:orders"}}
}
Amazon EventBridge: ルーティングされるイベントバス
EventBridge(旧CloudWatch Events)は、コンテンツベースのルーティング、スキーマ検出、SaaSパートナーのイベントソース、アーカイブ/リプレイ機能でpub/subを拡張します。イベントはイベントバス(デフォルト、カスタム、またはパートナー)を流れ、JSON構造に基づいてフィルタリングするイベントパターンを持つルールと照合されます。ルールは、入力パスと入力テンプレートを介してペイロードを変換し、デッドレターターゲットをアタッチし、Lambda、Step Functions、ECSタスク、SQS、SNS、Kinesis、APIデスティネーションなど20以上のネイティブターゲットに配信できます。
{
"source": ["com.acme.orders"],
"detail-type": ["OrderPlaced"],
"detail": {"amount": [{"numeric": [">", 500]}]}
}
SNSとの違いはアーキテクチャ上のものです。SNSは、単純な属性フィルタリングと低レイテンシーで、同種のサブスクライバーへの高スループットなブロードキャストに最適化されています。EventBridgeは、異種のイベント駆動型アーキテクチャに最適化されています。つまり、多くのプロデューサーが異なるイベントスキーマを発行し、コンシューマーはトピックではなくパターンによってサブスクライブします。モノリスをマイクロサービスに分解している場合、特にプロデューサーにSaaSパートナーや(Config、GuardDuty、CodePipeline、CloudTrailなど)ネイティブにイベントを発行するAWSサービスが含まれる場合は、通常EventBridgeが適切な選択です。非常に大量で低レイテンシーの、同一のサブスクライバーへのファンアウトには、依然としてSNSが優れています。なぜなら、EventBridgeはイベントごとのレイテンシーがわずかに高く、デフォルトのスループット上限が低いためです。
Amazon MQ: 既存プロトコル向けのブローカー型メッセージング
Amazon MQは、ActiveMQまたはRabbitMQを実行するマネージドブローカーです。これは、AMQP 0-9-1、AMQP 1.0、MQTT、STOMP、OpenWire、またはJMSに依存するオンプレミスのワークロードを、アプリケーションを書き換えることなく移行するために存在します。決済システムがトランザクションのexactly-onceセマンティクスを持つサードパーティのJMSブローカーを使用している場合、それをAmazon MQに移行することで、インフラ管理をなくしつつ、ワイヤープロトコルと配信保証を維持できます。グリーンフィールドのAWSネイティブ設計にはSQS/SNS/EventBridgeを選択し、プロトコルの互換性が制約となる場合にのみAmazon MQを選択してください。
Kinesis Data Streams
**Kinesis Data Streams (KDS)**は、高スループットのストリーミング取り込み(クリックストリーム、IoTテレメトリ、ログ集約など)のための、耐久性があり、順序付けされた、パーティション化されたログです。レコードはPartitionKeyによってシャードに配置されます。順序はストリーム全体ではなく、シャード内で保証されます。各シャードは、1 MB/sまたは1,000レコード/sの書き込みと、2 MB/sの読み取り(または拡張ファンアウトでそれ以上)をサポートします。レコードはデフォルトで24時間保持され、最大365日まで延長可能です。そのため、複数の独立したコンシューマーが同じ履歴を再生できます。これは、SQSがack時に削除するため不可能なことです。
オンデマンドモードは、ストリームごとに最大200 MiB/sの書き込みまで自動的にスケールアップすることで、シャードの計算を不要にし、予測不可能なトラフィックに最適です。プロビジョニングモードは、キャパシティが既知の定常状態ではより安価です。
ワークロードが、FIFOが対応できないスループット(FIFOはKDSが処理できる数百万レコード/秒をはるかに下回る)で順序付けされた再生可能な取り込みを要求する場合、複数の独立したコンシューマーが同じストリームを読み取る必要がある場合、または「処理全体で元の順序を維持する」という文言が高いボリュームと組み合わされている場合に、SQS FIFOよりもKDSを選択します。
Kinesis Data Firehose
Kinesis Data Firehoseは、完全マネージド型の配信サービスです。KinesisストリームまたはダイレクトPUTから読み込み、サイズ(1~128MB)または時間(60~900秒)のいずれかが先に達した時点でバッファリングし、オプションでLambdaを呼び出してレコードごとの変換(PIIのスクラビング、フォーマットの正規化)を行い、Glueスキーマを使用してJSONをParquetまたはORCにオンザフライで変換でき、KMSで暗号化して、S3、Redshift、OpenSearch、またはSplunkに配信します。シャードがなく、実行するコンシューマーも不要で、GB単位の従量課金制です。
データレイクへのスケーラブルな取り込みの定番パターンは、耐久性のあるバッファとしてData Streams(オンデマンド)を、S3への配信のためにFirehoseを組み合わせるものです。
Producers → Kinesis Data Streams (on-demand) → Firehose (60s buffer, Parquet) → S3 → Athena/Glue
何百万ものモバイルイベントを取り込み、暗号化し、Parquet形式でS3に格納する場合、正しい答えはParquet変換とKMSキーを使用したFirehoseです。KDSにカスタムコンシューマーと手書きのParquetライターを組み合わせる方法は、コードとインフラが劇的に多くなるため適切ではありません。Firehoseはニアリアルタイムであり、コンシューマー側でのリプレイをサポートしていません。リプレイが必要な場合は、KDSをパスに残してください。
Kinesis Data Analytics(現在はManaged Service for Apache Flink)は、ストリームに対してSQLまたはFlinkジョブを実行し、ウィンドウ集約を行います。
Lambdaとの連携と再試行セマンティクス
Lambdaはこれらのサービスと連携しますが、再試行の動作が大きく異なります。
| ソース | バッチ処理 | 順序 | 失敗時 |
|---|---|---|---|
| SQS Standard | 最大10,000メッセージ | なし | 可視性タイムアウト後に返される。maxReceiveCountを超えるとDLQへ |
| SQS FIFO | グループごと | グループごと | 成功またはDLQに送られるまでグループがブロックされる |
| Kinesis Streams | 最大10,000レコード | シャードごと | 成功、レコードの有効期限切れ、またはMaximumRetryAttempts/OnFailureの送信先に到達するまで再試行がシャードをブロックする |
| Firehose | N/A (変換) | N/A | 失敗したレコードはS3のエラープレフィックスに格納される |
SQSの場合、Lambda関数のタイムアウトをキューの可視性タイムアウト以下に保ち、可視性タイムアウトを関数タイムアウトの少なくとも6倍に設定します。Kinesisの場合、BisectBatchOnFunctionErrorを有効にし、OnFailureの送信先(SQSまたはSNS)を設定して、単一のポイズンレコードがシャード全体を無期限に停止させないようにします。
選択判断表
| 要件 | 正しい選択肢 | 他の選択肢が不適切な理由 |
|---|---|---|
| 順序保証、厳密に1回のアプリメッセージング、最小限の運用 | SQS FIFO | Standard SQSには順序保証/重複排除機能がない。MQはブローカーの管理が追加で必要 |
| 既存のAMQP/JMS/MQTTクライアントを維持 | Amazon MQ | SQS/SNSは独自のAPIを使用する |
| 1つのイベントを多数のAWSコンシューマーに耐久性をもってファンアウト | SNS → 複数のSQS | プロデューサーとコンシューマーを直接結合するとモノリス構成に戻ってしまう。SNSのみではコンシューマーがダウンしているとメッセージが失われる |
| フィルタ/変換を用いて異種イベントをルーティング | EventBridge | SNSのフィルターポリシーには、変換、パートナーソース、スキーマレジストリの機能がない |
| 同一のサブスクライバーへの非常に高いスループットのファンアウト | SNS | EventBridgeはレイテンシーが高く、デフォルトのスループットが低い |
| 大量の順序付きストリームを取り込み、リプレイする | Kinesis Data Streams | SQSの保持期間は最大14日で、オフセットによるリプレイはできない |
| コードなしでストリームをS3/Redshift/OpenSearchに配信 | Firehose | Data Streamsだけではコンシューマーアプリケーションが必要になる |
| ストリーミングJSONをS3上でParquetに変換 | Glueスキーマを使用したFirehose | KDSのカスタムコンシューマーでは、Parquetライターを記述・運用する必要がある |
← アナリティクス、データレイク、ML、特殊なワークロード · すべてのドメイン · セキュリティ、IAM、KMS、ガバナンス →
これらの問題を練習する → · ExamRoll.ioで時間制限付き練習 →
Pass the whole exam — not just this question
You found this answer. Get every verified question and explanation in one place, and save hours of prep. Free to start.
試験に合格する →