Step FunctionsでLambda延命

記事タイトルとURLをコピーする

はじめに

AWS Lambda(以下「Lambda」)って実行時間が最大5分までなんですよね。
5分以上かかる処理をさせたくて困ったこと、ありませんか?

こんにちは、運用システム課の礒です。
私は今回AWS Step Functions(以下「SFN」)で実行時間の上限対策をしてみました。

Step Functions?使ったことないよ...

ご心配なく!
まずは今回作ったステートマシン(アプリケーション全体のワークフロー)をご覧ください。



とても単純ですね。
「あ、できそう」と思っていただければ幸いです。

SFNではこのようなワークフローをJSON形式で記述・管理できます。
詳細は割愛させていただきますが、1ヶ月あたり4000回までの遷移は無料利用枠に含まれていますので是非お気軽にお試しください!

今回はそんなSFNを使って、処理完了まで繰り返しLambdaを実行し、完了したらどこかに通知を飛ばして終了するフローを作成しました。


目次

・今回作るしくみについて
・ Serverless Frameworkで構築する
    - 環境の用意
    - serverless.ymlの編集

・ まとめ

今回作るしくみについて

全体の処理内容はこのようなイメージです。

「Process」ステート

INPUT: 処理対象リスト
OUTPUT: 入力リストから処理済みの要素を削除したリスト + リスト長

メイン処理をするLambdaファンクションを呼び出します。
リストのすべての要素について処理が完了した場合は空のリストが返ります。

「Check」ステート

INPUT: リスト長
OUTPUT: リスト長が0 -> Postステートに遷移
            リスト長が1以上 -> Processステートに遷移

「Process」ステートの中で「全要素について処理が完了したら通知する」という分岐をさせて1つのLambdaファンクションで済ませてもよいのですが、
計1回しか活躍しない分岐を繰り返すのってなんだかイマイチ・・・
ということで「Check」、「Post」の2つのステートをもつSFNステートマシンにしました。

「Post」ステート

INPUT: 通知先エンドポイント情報
OUTPUT: なし

通知先のエンドポイント情報を読み、処理が完了した旨POSTするLambdaファンクションを呼び出します。

ステートマシンの説明は以上です。
この環境をServerless FrameworkというCLIツールで構築する方法を簡単にご紹介して終わりたいと思います。

Serverless Frameworkで構築する

それでは構築してみましょう。
Serverless Frameworkを使うと、裏でCloud Formationを使ってLambdaなどのリソースを構築してくれます。

本記事での手順の一部は弊社の坂本が書いた記事の手順と同じですので、適宜ご参照いただければと思います。

環境の用意

今回の作業環境は以下の通りです。

 

名前 バージョン
OS OS X
Python 3.6.1
Serverless Framework 1.26.0


上記坂本による記事の
1. Serverless Frameworkのアップデート
2. サービスの作成
3. 必要なファイルを自動生成
の手順で、ディレクトリ作成までの操作を行います。

次に、作業ディレクトリに serverless-step-functions というプラグインをインストールします。

npm install --save-dev serverless-step-functions

 
環境の準備ができてきました。
次にserverless.ymlの編集に移ります。

serverless.ymlの編集

最初に示したワークフローを作成するには、ymlファイルを次のように編集します。

service: blog

custom:
    config:
        accountId: ************

provider:
  name: aws
  runtime: python3.6
  profile: dev  # ~/.aws/credentialsの中で今回使うプロファイル名
  region: ap-northeast-1

functions:
  Process:
    handler: process.main
  Post:
    handler: post.main

plugins:
    - serverless-step-functions

stepFunctions:
  stateMachines:
    hellostepfunc1:
      name: compare-with-lambda
      events:
          - http:
              path: sfn
              method: POST
      definition:
        Comment: "compare with invoking lambda functions"
        StartAt: Process
        States:
          Process:
            Type: Task
            Resource: "arn:aws:lambda:${self:provider.region}:${self:custom.config.accountId}:function:${self:service}-${self:stage, 'dev'}-Process"
            ResultPath: $
            OutputPath: $
            Next: Check
          Check:
            Type: Choice
            Choices: [{
                Variable: "$.length",
                NumericGreaterThanEquals: 1,
                Next: Process
                }]
            Default: Post
          Post:
            Type: Task
            Resource: "arn:aws:lambda:${self:provider.region}:${self:custom.config.accountId}:function:${self:service}-${self:stage, 'dev'}-Post"
            End: True


ファイルの中で指定した値を変数のように参照することができるため、
重複部分の入力がほぼ必要ないのがいい感じですね。

この内容でデプロイしましょう!

sls deploy

 



これで今回必要なすべてのリソースが連携された状態で一気に構築できました。
めでたしめでたし!
① HTTPリクエストを受けるAPI Gateway
② そこから呼び出されるStep Functions
③ さらにそこから呼び出されるLambdaファンクション

おわりに

ブログを読んでいただきありがとうございました。

1つのLambdaファンクションで頑張ってやりくりすることもできますが、SFNでお悩みが解決することもあるかもしれません。
ワークフローが自動で視覚化されるのでパッと見で全体の概要をつかめるのも利点ですね。

SFN、みなさまも使ってみてください!