この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。
SNSとSQSを組み合わせるファンアウトはよく使われます。いざ、実際に使うときになって、ふと思ってしまいました。
「あれ? 同じデータが来るよね? 一部だけじゃないよね?」と。
99%問題なしと思っていますが、念のため、実際に試してみました。
おすすめの方
- SNSとSQSのファンアウトで並列にイベント実行されるか知りたい方
- SNSとSQSのファンアウトをCloudFormatinで作成したい方
実験用のサーバーレスアプリを作成する
ざっくり構成図
1つのSNSに2つのSQSと2つのLambdaを繋げます。このときのLambdaのログを確認します。
sam init
sam init \
--runtime python3.8 \
--name sns-sqs-test \
--app-template hello-world \
--package-type Zip
SAMテンプレート
下記を作成しています。
- SNSトピック
- SQS
- SQSポリシー
- Lambda1とロググループ
- Lambda2とロググループ
なお、Lambda1とLambda2は、同じソースコードを使用します。
template.yaml
AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Description: sns-sqs-test
Resources:
# SNS
TestTopic:
Type: AWS::SNS::Topic
Properties:
Subscription:
- Protocol: sqs
Endpoint: !GetAtt Test1Queue.Arn
- Protocol: sqs
Endpoint: !GetAtt Test2Queue.Arn
# SQS
Test1Queue:
Type: AWS::SQS::Queue
Properties:
VisibilityTimeout: 10
Test2Queue:
Type: AWS::SQS::Queue
Properties:
VisibilityTimeout: 10
QueuePolicy:
Type: AWS::SQS::QueuePolicy
Properties:
Queues:
- !Ref Test1Queue
- !Ref Test2Queue
PolicyDocument:
Statement:
- Action:
- "sqs:SendMessage"
Effect: "Allow"
Resource: "*"
Principal:
Service: sns.amazonaws.com
# Lambda
Test1Function:
Type: AWS::Serverless::Function
Properties:
CodeUri: hello_world/
Handler: app.lambda_handler
Runtime: python3.8
Timeout: 10
Events:
SQS:
Type: SQS
Properties:
BatchSize: 1
Queue: !GetAtt Test1Queue.Arn
Test1FunctionLogGroup:
Type: AWS::Logs::LogGroup
Properties:
LogGroupName: !Sub /aws/lambda/${Test1Function}
Test2Function:
Type: AWS::Serverless::Function
Properties:
CodeUri: hello_world/
Handler: app.lambda_handler
Runtime: python3.8
Timeout: 10
Events:
SQS:
Type: SQS
Properties:
BatchSize: 1
Queue: !GetAtt Test2Queue.Arn
Test2FunctionLogGroup:
Type: AWS::Logs::LogGroup
Properties:
LogGroupName: !Sub /aws/lambda/${Test2Function}
Lambdaコード
event
の内容をログ出力するだけです。
app.py
import json
def lambda_handler(event, context):
print(json.dumps(event))
デプロイ
sam build
sam deploy \
--stack-name Sns-Sqs-Test-Stack \
--s3-bucket cm-fujii.genki-deploy \
--capabilities CAPABILITY_NAMED_IAM \
--no-fail-on-empty-changeset
SNSでメッセージを発行して、動作を確認する
SNSトピックにメッセージを発行する
1つのメッセージを発行します。2つのLambdaに同じメッセージが届くことを期待します。
Lambda1のログを確認する
バッチリ届いていました。
Lambda2のログを確認する
2つ目のLambdaにも、問題なく届いていました。
というわけで、メッセージは並列に届く
さいごに
SNSとSQSを組合わあせたアーキテクチャについては、下記のブログが非常に参考になります。ぜひご覧ください。