echo("備忘録");

IT技術やプログラミング関連など、技術系の事を備忘録的にまとめています。

【Serverless Framework】Lambda Destinations機能をServerless Frameworkで実装する

はじめに

昨年11月末にAWSから「Lambda Destinations(Lambda非同期呼び出しの宛先指定)」機能が発表されました。

そしてこの機能について、3月中旬に「Serverless Frameworkが正式サポート」したと公式ブログで発表がありました。
そこで、早速この機能をServerless Frameworkで使ってみました。

serverless.com

前提:「Lambda Destinations(Lambda非同期呼び出しの宛先指定)」って?

概要としては、以下の機能になります。

  • Lambda実行結果に従って、次のアクション(=実行リソース)を指定できる。
    • 正常終了(Success)/異常終了(Failure)で個別に指定可能
  • 指定可能なアクション(=実行リソース)は、以下の通り
    • Simple Queue Service(SQS)
    • Simple Notification Service(SNS)
    • Lambda
    • Event Bridge
  • 非同期実行のLambda(=各種イベントで実行されるLambda)のみ設定可能
    • API Gateway(≒Rest API)経由で実行されるような、同期実行のLambdaでは実行不可(※)

API Gateway経由Lambdaでも、非同期で実施することは可能です。

https://d2908q01vomqb2.cloudfront.net/1b6453892473a467d07372d45eb05abc2031647a/2019/11/25/lambda-destinations1.png

【参考】

実践:Serverless Frameworkで実装してみる

※前提として、前掲のServerless Framework公式ブログに記載の通り、Serverless Frameworkのバージョンを1.66.0以上にしてください。

serverless.ymlの「functions」セクションで、以下のようなLambda関数を定義します。 (今回はSuccess/Failure共に、アクションはLambda関数にしています)

functions:  
  Challange:  
    handler: challange.index  
    events:  
      # API Gatewayは通常は同期実行(Lambda Destination対象外)だけど、テスト用に実装
      - http:  
          path: /challange  
          method: get  
      ## 実際はこんな感じで、何かのイベントで実行するように実装する(元リソースの定義は省略)  
      - schedule: rate(10 minutes)  
    # 「onSuccess」/「onFailure」に成功時/失敗時の定義名を記載する
    destinations:  
      onSuccess: Success  
      onFailure: Failure  
  
  # 成功時のリソースの定義を記載(Lambdaの場合はハンドラを定義)  
  Success:  
    handler: succeeded.index  
  
  # 失敗時のリソースの定義を記載(Lambdaの場合はハンドラを定義)
  Failure:  
    handler: failed.index  

定義としては、以上です。

なお上記関数ですが、下記の内容となります。(シンプルすぎるので内容は省略)

  • challange.index:onSuccess検証時は何もせずにreturnするだけ、onFailure検証時は何かErrorをthrowする。
  • succeeded.index/failed.index:console.log()でログを1行書き出すだけ

invokeでテスト実行する

上記serverless.ymlをデプロイしたら、実際にテストをしてみます。
※デプロイ成功していれば、「Challange」Lambda内に下記の通り「非同期呼び出し」ソースが二つ追加されます。
f:id:Makky12:20200418175220p:plain

デプロイを確認したら「invoke」コマンドでテストを行います。

ここで気を付けるのは、invoke」コマンドを非同期(=イベント)で呼び出すには「--type」オプションに「Event」オプションを指定しないといけない点です。

これを忘れると「--type=RequestResponse」(=同期呼び出し)として実行されるため、Lambda Destinationは正常に機能しません。
(堀家さん、ありがとうございます。)

# test.jsonはchallange.index実行時のevent引数の内容をそのまま指定  
# 「--type Event」を忘れないこと!
> slss invoke --function Challange --path test.json --type Event

正常に実行されると、特に何も表示されずにコマンドが終了しますので、CloudWatch Logを確認します。

CloudWatch Logを確認すると、成功時/エラー発生時共に正しくアクション先Lambdaが実施され、ログが書き出されていることが分かります。

  • 上が成功時、下がエラー発生時
  • 画像は1つにまとめてますが、実際はどちらもchallange.index、及びsucceeded.index(またはfailed.index)のログです。
  • エラー発生時にchallange.indexのログが3つあるのは、2回リトライ処理を実施しているためです。

f:id:Makky12:20200418185809p:plain
f:id:Makky12:20200418185830p:plain

なお、Serverless Framework公式の下記動画でも、Serverless FrameworkによるLambda Destinationsの実装が詳しく紹介されています。 www.youtube.com

まとめ

以上がServerless FrameworkでLambda Destinationsを実装する方法です。

Lambda Destinationsですが、成功時/失敗時の処理を個別に切り出せるので、下記のようなメリットがあると思います。

  • 成功時&エラー時の処理を、同一ソースに書かなくてよい。
  • 上記により、ソースの可視性&保守性の向上につながる
  • リトライ処理を考慮した成功時&エラー時の処理を実装できる

こういう便利な機能は、どんどん活用していきたいですね。

告知

4/24(金)にオンラインで開催される「Infra Study Meetup #1 ~Infrastructure as Code~」に「Infrastructure as Codeを導入して良かった点」という内容でオンライン登壇させて頂きますので、よろしくお願いいたします。(てか4/18(土)時点で、参加者2000人超えそうな勢いなんだけど...)

forkwell.connpass.com

それでは、今回はこの辺で。