Cloud Tasks の dispatch_deadline 設定してますか?
こんにちは、Cloud Support の Rnrn です。今まで Medium に記事を投稿していましたが、Zenn の Publication ができたということで今回はこちらを使ってみようと思います。今日の記事では、Cloud Tasks 関連のお問い合わせを頂いた際に設定をおすすめすることが多い dispatch_deadline をご紹介します。
設定していないと起こる問題
Cloud Tasks でよくあるトラブルの 1 つに「Cloud Tasks に追加したタスクが数時間経っても実行されない」というものがあります。よくよく調査してみると、実際には実行されていないのではなく、長時間実行されたままであることに気づいていないだけというケースが少なくありません。deadline についてあまり意識していないと想定外に長時間実行される可能性があることは忘れてしまいがちですよね 😶
Cloud Tasks では 任意の HTTP ターゲットもしくは Google App Engine (GAE) ターゲットの指定が可能ですが、上記のパターンは特に GAE ターゲットを利用しているときに発生しやすいように思えます。デフォルトの deadline が 24 時間の場合 (※1) 、最長で 1 日のあいだ GAE や Cloud Tasks でログが出ないため「数時間様子を見てもログがないしやっぱり実行されていなさそうだ」と考えてしまいがちだからです。
※1: 詳しくはドキュメントを確認するのが一番ですが、GAE ターゲットを利用した時のデフォルトの deadline は GAE の種類及びスケーリングタイプに依存しています。特にマニュアル及びベーシックスケーリングの GAE スタンダードでは deadline が 24 時間となります。
なぜ長時間実行されっぱなしになるか
ではそもそも、なぜ deadline いっぱいまでタスクの処理が継続してしまうのでしょうか。これについては様々な原因が考えられます。例えば、ターゲットの GAE の処理で外部 API に HTTP コールをしていてずっとレスポンスを待っているが返答が返ってこなかったり、GAE 側のスケールが何らかの理由で失敗してしまったなど。
このとき、もちろん原因を追求するのも大切ですが、例えば依存サービスの一時的な障害の影響を受けるなど原因がわかったところでそれが 100% 回避できないものであることは多々あります。また、Cloud Tasks は At-least-once 配信ベースであり、上記の GAE のスケーリングのような一時的な内部インフラ起因での失敗についてもリトライで対処する設計になっています。このとき、通常は即時エラーが返ってきますが、まれにレスポンスが返らずタイムアウトまで待ってしまうこともあります。そうなるとリトライまで時間がかかってしまうのですが、Cloud Tasks はタスクの配信タイミングについては保証をしていないため、これも想定範囲内の挙動となります。
つまり、ここで Cloud Tasks の観点から大事になるのは個々の原因ではなく、なにか問題が起こったときに早く処理を切り上げてリトライできるようにすることです。
早くリトライさせるために
問題が起こったときに早く処理を切り上げてリトライできるようにするため、Cloud Tasks では dispatch_deadline を設定することをおすすめしています。これはキュー単位ではなく個々のタスクに設定するもので、dispatch_deadline に達するとターゲットからレスポンスが返ってきていなくてもタスクは DEADLINE_EXCEEDED
により失敗として記録され、リトライ設定に応じてリトライがスケジュールされます。
dispatch_deadline に達してリクエストがキャンセルされたときの挙動はターゲットワーカー次第になります。dispatch_deadline のリンクに記載がある通り、GAE の場合はワーカーの最大実行時間は Cloud Tasks の dispatch_deadline ではなく GAE サービスのタイムアウトを見ています。
例えば dispatch_deadline よりサービスのタイムアウトが長く設定されている時にGAE でのタスクの処理が dispatch_deadline を超えるまで続いてしまった場合、Cloud Tasks でリトライがスケジュールされている間も元のリクエストが GAE 上で実行され続けてしまいます。以上から、dispatch_deadline はアプリケーションのハンドラーのタイムアウトより数秒長い程度に設定することを推奨しています。
まとめ
これまで見てきたように、dispatch_deadline を正しく設定しておくと不測の事態が起きても無駄に待つことなくタスクを早めにリトライさせることができるようになります。もし Cloud Tasks を使っていてまだ設定していないようであれば、ぜひ設定してみてくださいね ⏰
Discussion