serverless-v1.0.0-rc.1を試してみた(3) – 複数のFunctionの管理

モバイルアプリサービス部の五十嵐です。

今回は1つのserverlessプロジェクトで複数のLambdaを管理してみます。JAWSやserverless 0.x系にはモジュールという単位でLambdaを管理できましたが、1.0系ではその機能がありません。ではどうやって複数のLambdaを管理するのでしょうか。

今回作成したソースコードはこちら

環境

  • serverless 1.0.0-rc.1
  • node.js 4.3.2
  • npm 2.14.12

複数のFunctionを作成する

複数のLambdaを定義するには、設定ファイルに複数のfunctionを記述すればよいです。極端な例ですが以下でも良いです。全く同じ機能でARNは異なるLambdaが2つ作成されます。

functions:
  hello1:
    handler: handler.hello
  hello2:
    handler: handler.hello
# sls deploy
Serverless: Packaging service...
Serverless: Uploading CloudFormation file to S3...
Serverless: Uploading service .zip file to S3...
Serverless: Updating Stack...
Serverless: Checking Stack update progress...
...........
Serverless: Stack update finished...

Service Information
service: sample
stage: dev
region: us-east-1
endpoints:
  None
functions:
  sample-dev-hello2: arn:aws:lambda:us-east-1:XXX:function:sample-dev-hello2
  sample-dev-hello1: arn:aws:lambda:us-east-1:XXX:function:sample-dev-hello1

形式に直すと以下のとおりです。

functions:
  <名前>:
    handler: <ファイル名(拡張子を除く)>.<エントリーポイントの関数名>
  <名前>:
    handler: <ファイル名(拡張子を除く)>.<エントリーポイントの関数名>

実際には実行コードのファイルは別々に分け、共通する機能があれば別ファイルに切り出して参照させるかと思います。

今回はhandler2.jsというファイルをプロジェクトに追加しています。また、タイムアウト時間を60秒に変更しています。

functions:
  slashCommands:
    handler: handler.slashCommands
    events:
      - http:
          path: slack/slash-commands
          method: post
          request:
            template:
              application/x-www-form-urlencoded: '{ "body": $input.json("$") }'
            passThrough: NEVER
  echo:
    handler: handler2.echo
    timeout: 60 # optional, default is 6

Functionごとのパッケージを作成する

前回までの定義は以下のとおりです。

# you can add packaging information here
package:
  exclude:
   - config/default_sample.json
   - event.json

これでは共通の設定しかできないので無駄なモジュールなどが含まれてしまいます。それを防ぐために、functionごとにパッケージに入れる/入れないを設定できるようになっています。(参照: serverless/10-packaging.md

まず package:individually: true を設定します。これにより、functionごとにパッケージが作成されるようになります。個々のパッケージは、 packege:function:packege: をマージした結果になります。重複する設定がある場合、 function:packege: のほうが優先されます。

以下のように記述することで必要最小限のパッケージを作ることができました。

# you can add packaging information here
package:
  individually: true
  exclude:
   - config
   - event.json
   - node_modules
   - handler.js
   - handler2.js

functions:
  slashCommands:
    handler: handler.slashCommands
    package:
      include:
        - handler.js
        - config/default.json
        - node_modules/config
    events:
      - http:
          path: slack/slash-commands
          method: post
          request:
            template:
              application/x-www-form-urlencoded: '{ "body": $input.json("$") }'
            passThrough: NEVER
  echo:
    handler: handler2.echo
    package:
      include:
        - handler2.js
    timeout: 60 # optional, default is 6

Function毎のコマンド操作

デプロイは --function(-f) <名前> オプションを付けることでFunctionごとにデプロイできます。 logs などのコマンドも同様です。ただし注意しなくてはならないのは、serverlessのCloudFormationは1つだけということです。 remove コマンドを実行したり、AWSコンソールからCloudFormationを削除すると全てのFunctionが削除されます。

まとめ

複数のLambda Functionを扱えることが分かりました。考えてみれば、実際にFunctionを数十個も連携させるようなLambdaはなかなかないわけですから、モジュールという単位は大きすぎたのかもしれませんね。現実的には多くても数個なので、この程度で十分なのかもしれません。また、まだ取り上げていない機能としてpluginsという機能があります。これはCLIコマンドを拡張するための機能のようです。

これらの変更点から、2度にわたる大きな仕様変更(JAWSからserverless0.x系、0.x系から1.x系)の歴史が垣間見えるような気がしました。