AWS

SNSからLambdaを呼び出す

スポンサーリンク
SNSでLambdaを呼び出す AWS
スポンサーリンク
スポンサーリンク

SNSからLambdaを呼び出す

以下のページでSNSについて取り上げました。

上記のページでは、サブスクライバーとしてメールアドレスを指定しました。

今回はサブスクライバーにLambda関数を指定する方法を確認します。

構築する環境

Diagram of invoking Lambda from SNS

構成は冒頭にご紹介したページと概ね同様です。

Lambda関数2からSNSトピックにメッセージを送信します。
つまりこの関数はパブリッシャーとして動作します。
この関数の働きは、現在日時からUNIX時間を取得し、メッセージとしてこれを送信します。

SNSトピックのサブスクライバーとしてLambda関数1を指定します。
この関数の働きは、メッセージとして渡されたUNIX時間が偶数/奇数か判定します。

CloudFormationテンプレートファイル

上記の構成をCloudFormationで構築します。
以下のURLにCloudFormationテンプレートを配置しています。

awstut-fa/fa-100.yaml at main · awstut-an-r/awstut-fa
Contribute to awstut-an-r/awstut-fa development by creating an account on GitHub.

テンプレートファイルのポイント解説

(参考)Lambda関数でSNSにパブリッシュする

Resources: Function2: Type: AWS::Lambda::Function Properties: Architectures: - !Ref Architecture Environment: Variables: REGION: !Ref AWS::Region TOPIC: !Ref TopicArn Code: ZipFile: | import boto3 import datetime import os import time topic = os.environ['TOPIC'] region = os.environ['REGION'] client = boto3.client('sns', region_name=region) def lambda_handler(event, context): now = datetime.datetime.now() now_str = now.strftime('%Y-%m-%d %H:%M:%S.%f') unix_time = str(time.mktime(now.timetuple())) print(now_str, unix_time) response = client.publish( TopicArn=topic, Subject=now_str, Message=unix_time ) print(response) FunctionName: !Sub "${Prefix}-function-02" Handler: !Ref Handler Runtime: !Ref Runtime Role: !GetAtt FunctionRole2.Arn FunctionRole2: Type: AWS::IAM::Role DeletionPolicy: Delete Properties: AssumeRolePolicyDocument: Version: 2012-10-17 Statement: - Effect: Allow Action: sts:AssumeRole Principal: Service: - lambda.amazonaws.com ManagedPolicyArns: - arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole Policies: - PolicyName: SNSPublishPolicy PolicyDocument: Version: 2012-10-17 Statement: - Effect: Allow Action: - sns:Publish Resource: - !Ref TopicArn
Code language: YAML (yaml)

Lambda関数からSNSにメッセージをパブリッシュします。
詳細は冒頭でご紹介したページをご確認ください。

なおCloudFormationでLambda関数を作成する方法については、以下のページをご確認ください。

今回はインラインで実行するコードを記載します。

SNSサブスクライバーにLambda関数を指定する

Resources: Topic: Type: AWS::SNS::Topic Properties: Subscription: - Endpoint: !Ref FunctionArn1 Protocol: lambda TopicName: !Ref Prefix
Code language: YAML (yaml)

Subscriptionプロパティでサブスクライバーを設定します。
今回はLambda関数でSNSメッセージを受け取りますから、Endpointプロパティに関数のARNを、Protocolプロパティに「lambda」を指定します。

サブスクライバーにLambda関数を指定する場合、内部的にはSNSが関数を呼び出すという挙動になります。
そのためSNSに関数を呼び出す権限を与える必要があります。

Resources: SNSPermission: Type: AWS::Lambda::Permission Properties: FunctionName: !Ref Function1 Action: lambda:InvokeFunction Principal: sns.amazonaws.com SourceArn: !Ref Topic
Code language: YAML (yaml)

以下のAWS公式ページを参考にして設定しました。

同じアカウントで Lambda 関数を Amazon SNS のトピックにサブスクライブする

Lambda関数でSNSメッセージを受け取る

Resources: Function1: Type: AWS::Lambda::Function Properties: Architectures: - !Ref Architecture Code: ZipFile: | def lambda_handler(event, context): subject = event['Records'][0]['Sns']['Subject'] message = event['Records'][0]['Sns']['Message'] print(subject, message) unix_time = int(float(message)) if (unix_time % 2) == 0: print('{int} is even !'.format(int=unix_time)) else: print('{int} is odd !'.format(int=unix_time)) FunctionName: !Sub "${Prefix}-function-01" Handler: !Ref Handler Runtime: !Ref Runtime Role: !GetAtt FunctionRole1.Arn
Code language: YAML (yaml)

eventオブジェクト内に、SNSから発信されたメッセージが格納されています。
今回は受け取ったUNIX時間の偶数/奇数を判定します。

環境構築

CloudFormationを使用して、本環境を構築し、実際の挙動を確認します。

CloudFormationスタックを作成し、スタック内のリソースを確認する

CloudFormationスタックを作成します。
スタックの作成および各スタックの確認方法については、以下のページをご確認ください。

各スタックのリソースを確認した結果、今回作成された主要リソースの情報は以下の通りです。

  • SNSトピック:fa-100
  • Lambda関数2:fa-100-function-02
  • Lambda関数1:fa-100-function-01

作成されたリソースをAWS Management Consoleから確認します。
SNSトピックを確認します。

Detail of SNS 1.
Detail of SNS 2.

正常にSNSトピックが作成されていることがわかります。
そしてLambda関数1がサブスクライバーとして登録されていることもわかります。

Lambda関数を確認します。

Detail of Lambda 1.
Detail of Lambda 2.

2つの関数も正常に作成されていることがわかります。
関数1に注目すると、SNSからの呼び出しが許可されていることもわかります。

動作確認

1回目

準備が整いましたので、関数2を実行します。
関数2のTestタブから「Test」をクリックして実行します。

Detail of Lambda 3.

関数が正常に実行されたことがわかります。
現在日時からUNIX時間が計算されて、それをSNSメッセージとして発信したことがわかります。
今回のUNIX時間は「1669204672」でした。

続いて関数1のログを確認します。

Detail of Lambda 4.

関数が実行された形跡があります。
つまりパブリッシャーである関数2からSNSメッセージが発行されたことによって、サブスクライバーである関数1が自動的に呼び出されたということです。

UNIX時間の偶数/奇数判定の結果、「1669204672 is even !」が出力されました。

2回目

もう一度、同じ操作を行います。

以下が両関数の実行ログです。

Detail of Lambda 5.
Detail of Lambda 6.

今度は関数2でUNIX時間「1669204701」を持つSNSメッセージが発信されました。
これを受けて自動的に関数1が実行され、奇数と判定されて「1669204701 is odd !」が出力されました。

まとめ

SNSサブスクライバーにLambda関数を指定する方法を確認しました。

タイトルとURLをコピーしました