GAE cronジョブにはtimeoutがないのでCloud Schedulerを使おう
App Engineの定期実行で困っていたこと
Google App Engine でバッチジョブを動かしていて、ある時「何のエラーも出ていないが処理が止まってしまう」状態に遭遇した。いわゆるフリーズ / ストールしている状態。
そういや昔は Windows の OS そのものが連続何日間稼働で無反応になるだの、Webサーバが無反応になるだの色々あったけど、最近はこういうことに気を使う必要があるケースはほとんどなかったなーなどと思いながら、はてどうしたもんかと考えていた。
- このプロセスは24h稼働させっぱなしではなく、必要なタイミングに自動で起動して自動で終了する予定なので、常時外形監視のような形でエラーを拾うのもなかなか面倒な仕組みになってしまう1
- プロセスは何のログも吐かなくなってしまうので、プログラムコード自体を修正せずに中の情報を引き出すのは難しい
- 正常に動作しているログは逐一出力しているが、「特定のタイミングで一定時間以上正常なログが途切れている」みたいな条件での監視をアリもののサービスだけで実現するのはなかなか難しそう
ということで、プロセスそのものに注目してエラーが起きていることを知るのはちょっと難しそうだった。
そもそもcronジョブはプロセスのストールを想定できていないように見える
逆に、「なんで次回以降の定期実行のスケジュールで異常に気付けないのか?」と考えたのだが、実は GAE の cron スケジュールではそれが正常な動作なのだった。
cron.yaml を使用したジョブのスケジューリング | Google App Engine スタンダード環境のドキュメント | Google Cloud
ジョブの開始時刻が厳密に決まっているので、ジョブ インスタンスの実行時間が定義された時間間隔よりも長くなった場合、cron サービスはジョブをスキップすることがあります。つまり、前のジョブが完了もタイムアウトもしなかった場合、その時間の範囲に含まれる開始時刻はスキップされます。
マジか。ということは
- スケジュール実行させる側はプロセスが成功か失敗かの返事を返さない限り、エラーが起きているか否かの判定をせずに黙って無視する
- プロセスがストールしているのでプロセス側に注目してもスケジュール実行側に注目してもそのままではエラーの発生を拾えない
ということになる。
GAEのtimeout
もっとも、
- GAE Standard Env. の auto scaling の timeout は 10min
- GAE Flex Env の timeout は 60min
なので、その時間以内に終了する予定のものが完了しなかった場合についてはストールすれば timeout を比較的容易に検知できそうだ。しかし
GAE Standard Env. の basic scaling と manual scaling では 24時間まで実行できる。
- App Engine 環境を選択する | App Engine ドキュメント | Google Cloud
- インスタンスの管理方法 | Google App Engine スタンダード環境のドキュメント | Google Cloud
ということは例えば
1時間では収まらないけど2時間以内に完了する予定のプロセスが途中でストールする可能性があります、という場合に実際にApp Engine側の機能でtimeoutを知ることができるのは24時間後
になってしまうということを意味する。これではさすがに困る。
Cloud SchedulerならScheduler側でtimeoutを知ることができる
例えば App Engine のプロセスを定期実行しようと思うと
gcloud scheduler jobs <create|update> app-engine --schedule <schedule>
で設定することになる
gcloud scheduler jobs create app-engine | Google Cloud CLI Documentation
が、ここに
--attempt-deadline 2h
のようにオプションを追加すれば少なくとも Cloud Scheduler 側では想定時間以内に終了しなかったことは分かる。App Engine 側が timeout しているわけではないが、少なくとも想定時間以内に終わりませんでしたという情報は取得可能だ。
これを監視してアラートを上げるだけでも、
24時間後に気づくなんてことはなくせる。
まぁそもそも Google Cloud はもう全体的に定期実行は Cloud Scheduler と統合されていっているのだから、さっさと乗り換えましょうということだった。
定期実行の設定と外形監視の設定を常に同期させないと簡単に誤検知が起きるし、正確に終了時刻が予定通りに動作するとも限らない。誤検知が続くと監視そのものの意味が大幅に薄れてしまう。 ↩