Zappaのスケジューリング機能を試してみる

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

はじめに

Python向けのServerless Frameworkの一つであるZappaは、Web ApplicationをAWSにデプロイする機能の他にも、様々な機能が用意されています。

今回はそのうち、Lambdaにデプロイされた関数を定期的に実行する機能を試してみました。

スケジューリング機能

Zappaのドキュメントにも書かれている通り、zappa_settings.jsoneventsにLambda上の関数と周期を指定することで、関数の定期実行を行うことができるようになります。

{
    "production": {
       ...
       "events": [{
           "function": "your_module.your_function", // The function to execute
           "expression": "rate(1 minute)" // When to execute it (in cron or rate format)
       }],
       ...
    }I
}

実際には、CloudWatch上に対応するEventが作成され、そこから定期的にLambdaの関数が呼ばれる様になります。このため、周期の指定にはCloudWatch Eventと同様の形式(rateまたはcron)での指定が必要となります。詳細についてはこちらをご参照ください。

試してみた

zappa_settings.jsonおよびlambda scriptを準備し、スケジューリング機能を確認してみました。

# zappa_settings.json

{
    "dev": {
        "app_function": "zappa_schedule.app",
        "s3_bucket": "zappa-xxxxxxx",
        "events": [{
           "function": "zappa_schedule.tick_tack",
           "expression": "rate(1 minute)"
       }],
       "keep_warm": false
    }
}
# zappa_schedule.py

from __future__ import print_function
from flask import Flask

app = Flask(__name__)

@app.route("/")
def hello():
    return "hello, zappa"

def tick_tack(event, context):
    print("tick...")
    print("tack...")

    return "done"

if __name__ == "__main__":
    app.run()

デプロイ後、CloudWatch Eventを確認してみるとイベントが追加されていることがわかります。

また、$ zappa tailコマンドを叩くと以下の様に1分ごとに実行されていることがわかります。

[1483189583435] [DEBUG] 2016-12-31T13:06:23.435Z edf9f92b-cf59-11e6-85e9-9dc43c31d156 Zappa Event: {u'account': u'123456789012', u'region': u'ap-northeast-1', u'detail': {}, u'detail-type': u'Scheduled Event', u'source': u'aws.events', u'version': u'0', u'time': u'2016-12-31T13:06:08Z', u'id': u'2573e9a9-d9cc-4d9e-ae8c-c76da11dc9a9', u'resources': [u'arn:aws:events:ap-northeast-1:123456789012:rule/zappa-schedule-dev-zappa_schedule.tick_tack']}
[1483189583435] tick...
[1483189583435] tack...
[1483189643444] [DEBUG] 2016-12-31T13:07:23.444Z 11bf3ac5-cf5a-11e6-a210-c93784eaf835 Zappa Event: {u'account': u'123456789012', u'region': u'ap-northeast-1', u'detail': {}, u'detail-type': u'Scheduled Event', u'source': u'aws.events', u'version': u'0', u'time': u'2016-12-31T13:07:08Z', u'id': u'611617a8-e754-4ebf-996d-c948a0a72f00', u'resources': [u'arn:aws:events:ap-northeast-1:123456789012:rule/zappa-schedule-dev-zappa_schedule.tick_tack']}
[1483189643456] tick...
[1483189643456] tack...

デプロイされたLambda Functionの中身を覗いてみると、zappa_settings.jsonで指定した関数の名前を、CloudWatch Eventのリソース名から特定して実行していることがわかります。

# handler.py

class LambdaHandler(object):
    ...
    def handler(self, event, context):
        if event.get('detail-type') == u'Scheduled Event':
            whole_function = event['resources'][0].split('/')[-1].split('-')[-1]

            # This is a scheduled function.
            if '.' in whole_function:
                app_function = self.import_module_and_get_function(whole_function)

                # Execute the function!
                return self.run_function(app_function, event, context)

                # Else, let this execute as it were.
                ...

ちなみに、zappa_settings.jsonkeep_warmtrueに設定した場合、同様に定期的にスケジュールされたイベントがlambda Functionに対して実行されます。

おわりに

Zappaのスケジューリング機能がどの様に実行されているかを調べてみました。