KiSAKU
技術系約4分で読めます

再試行は入れていた。それでもデプロイが落ちた

公開

再試行の処理は、半年前から入れていました。CMSが500を返したら、少し待ってもう一度投げる。3回まで。

それでも、デプロイが落ちました。

この記事で扱うこと

再試行を入れてあったのに効かなかった話です。何が返ってきていたのか、なぜ3回では足りなかったのか、そして回数ではなく間隔を増やした理由を書きます。

ページを先に作る構成では、ビルド中に問い合わせが集中する

このサイトは、訪問者が来てからCMSに聞くのではなく、デプロイのときに全ページを作ってしまう構成です。表示は速くなりますが、そのぶんビルドの最中にCMSへ何十回も問い合わせが飛びます。

記事が増えたいまは、1回のビルドで82ページぶんの問い合わせが、1分足らずのあいだに走ります。

失敗の意味が変わっていた

動的に表示していたころは、1回の問い合わせが失敗してもその1回の表示が失敗するだけでした。次に開けば直ります。

事前生成に変えたあとは、同じ1回の失敗がデプロイ全体を止めます。新しい記事も、直したところも、まとめて出なくなります。

速くするために取った選択が、別の場所の壊れやすさを生んでいたことになります。

返ってきていたのは、WordPressのエラーではなかった

ビルドのログを見ると、82ページ中40ページを作ったあたりで止まっていました。

Error: GraphQL Error (Code: 500): {"response":{"error":"<!DOCTYPE HTML PUBLIC ...

500という数字だけ見ると「WordPressが処理に失敗した」と読みたくなりますが、中身はHTMLでした。しかもWordPressのエラー画面ではなく、Apacheが出す素のエラーページです。

返ってきたもの そこから分かること
WordPressのエラー(JSON) WordPressまでは届いている。中で失敗した
Apacheの素のエラーページ WordPressに届く前に断られている

つまりPHPが動く手前の段階で弾かれていました。短時間に問い合わせが集中したことで、共用サーバー側がまとめて断る状態に入っていたのだと思います。

3回では足りなかった理由

入れてあった再試行は、こういう設定でした。

回 待ち時間 累計
1回目 — 0秒
2回目 1秒 1秒
3回目 3秒 4秒

最初から最後まで、4秒で終わります。

相手が「一瞬もたついた」だけなら、これで通ります。実際これまでは通っていました。今回そうならなかったのは、断られている状態が数秒では明けなかったからです。

同じ壁に3回ぶつかっていた

再試行は動いていました。ログにも3回ぶんの失敗が残ります。

ただ、4秒のあいだに3回投げても、3回とも同じ状態の相手に当たります。回数を増やしても、待っている時間が短ければ結果は変わりません。

回数ではなく、間隔を増やした

直したのは、待ち時間の表です。

const MAX_ATTEMPTS = 5;
const RETRY_DELAY_MS = [1000, 3000, 8000, 15000];

最後まで粘ると、1件あたり最長27秒かかります。ビルドは確実に遅くなります。

それでもこちらを選んだのは、待って通るほうが、デプロイごと落ちるより安いからです。27秒は待てば終わりますが、落ちたビルドは自分では直りません。気づいて、原因を調べて、押し直すまで止まったままになります。

なぜ回数を増やすだけでは足りないか

回数だけ10回に増やしても、間隔が1秒なら全体で10秒です。混んでいる相手にとってはさらに叩きに来ただけになります。

相手が回復するのを待つのが目的なので、増やすべきは回数ではなく間隔のほうでした。

気づくのが遅れた理由

この失敗に気づいたのは、デプロイした数時間後でした。新しく足したページを開いたら404だったからです。

ビルドが失敗しても、サイトは前の版のまま動き続けます。これ自体は正しい挙動で、壊れた版が公開されるよりずっと良い。ただし見ている側には何も起きません。止まったことは、止まった画面を見ても分からないということです。

いまは通知を入れていませんが、次に同じことが起きたときに数時間気づかない状態は残っています。ここは別に手を打つ必要があると考えています。

今回の学び

まず、速くする変更が、壊れやすさを持ち込むことがあるということ。事前生成そのものは良い選択でしたが、「1回の失敗が何を止めるか」が変わっていました。変えたときに、失敗の重さも一緒に変わります。

次に、500の中身を見ないと、誰が断ったか分からないこと。同じ500でも、アプリが失敗したのか、その手前で断られたのかで打つ手が違います。今回は中身がHTMLだったことが手がかりになりました。

そして、再試行は「回数」ではなく「どれだけ待つか」だということ。入れてあること自体は安心材料になりません。相手が何秒で回復するのかを考えないまま回数だけ決めていた、というのが本当の原因でした。

この記事を共有する

Xでポストはてブ
← ブログ一覧へ戻る