GAEでバッチ処理

Nov 7, 2018   #GAE  #golang 

はじめに

Google App Engine(GAE)を使って、バッチ処理が実行できたのでメモです。
GAEではcron.yamlに設定を記載することで時間を指定した処理を行うことができます。

サンプル

今回は、slackにメッセージを送信するアプリを定期的に実行させてみます。

slackにメッセージを送る部分は以下のサイトに詳しく記載されているので省略します。
CrossBridge Lab | GolangでSlackの特定のチャンネルにメッセージを送る

今回はGAE上でGolangを動かしてみましたよの構成を元に、GAEのプロジェクトを構築します。
ルートディレクトリ(app.yamlと同じ階層)にcrom.yamlを作成します。

cron.yaml

cron.yamlには、以下のように開始時刻や間隔で実行するタイミングを指定することが出来ます。

cron:
- description: "毎朝7時(日本時間)に実行"
  url: /morning
  timezone: Asia/Tokyo
  schedule: every day 7:00

- description: "毎週日曜8時(日本時間)に実行"
  url: /morning
  timezone: Asia/Tokyo
  schedule: every sunday 8:00

- description: "毎日0時を起点とし、1時間単位で実行"
  url: /morning
  timezone: Asia/Tokyo
  schedule: every 1 hours

その他のスケジュール指定方法や、HTTPリクエスト失敗時のリトライ回数は公式のドキュメントに詳しく記載されています。

注意点

GAEではdev_server.pyでローカルにサーバを立ち上げて、動作確認をすることができます。しかし、ローカル環境では、cron.yamlは動作しません。
localhost:8000 からGAEローカル環境の管理画面を開くことができます。
管理画面にcron.yamlで設定したスケジュールが一覧で表示されるので、Run nowをクリックすることで手動で実行することができます。

Cronの設定を本番環境にデプロイするときは、gcloud app deploy cron.yamlのようにcrom.yamlを指定します。
指定しないと、crom.yamlが読み込まれないため、いつまで待っても処理が実行されません。 Cronが設定されているかどうかは、コンソール画面のcronジョブから確認することが出来ます。

仮に他のユーザからHTTPでのリクエストがあった場合、想定していない時間に処理が実行される可能性があります。
そのため、GAEのcronサービスからのHTTPアクセス以外からのアクセスは除外する必要があります。
GAEのcronサービスからのHTTPアクセスにはHTTPヘッダにX-Appengine-Cron: trueが含まれているので、HTTPリクエストを受け取ったタイミングで、チェックする必要があります

例えば、GolangでGAEのcronサービス以外からのHTTPリクエストを弾くには、以下のように書きます。
(弾いた後の処理がお粗末ですが…)

// cron以外からのアクセスは弾く
if r.Header.Get("X-Appengine-Cron") != "true" {
	os.Exit(1)
}

感想

GAEはhttp(s)でのリクエストに対してレスポンスを返すだけのサービスだと思っていたので、時間指定で処理を実行してくれるのはとても意外でした。

タイミングをevery monday 09:00schedule: 1,8,15,22 of month 09:00のように指定するのはわかりやすくていいですね。 個人的には、crontabの分 時 日 月 曜日でタイミングを指定する方法よりは、直感的に感じました。

今回のサンプルファイルはgithubで公開してます。
https://github.com/foresukecom/gae_cron

その他

迂闊先生(@ukkariukatu)の「のみじょし」5巻が出てました!これは買わないと。
紙の本と同じタイミングでKindle版も発売されるのはありがたい限りです😆
…先日までみっちゃんと同い年だったんですが、いつの間にか僕の方が年上になってました。