• HTTP 429はserver停止と混同せず送信回数と再試行の時刻を分けて確認する

HTTP 429はserver停止と混同せず送信回数と再試行の時刻を分けて確認する

公開日: 執筆:佐藤

HTTP 429 Too Many Requestsは、利用者またはprogramが一定の時間に送ったrequestが多すぎることを示すstatusです。site全体が停止したことを示す503とは分けて考えます。429を受けたときは、同じrequestをすぐ繰り返さず、どこから何を何回送ったか、いつ再試行できるか、誰が制限を設定しているかを確認してください。

429は、login、問い合わせform、外部API、画像取得、広告dataの取得などで起こります。requestを止める理由は、serverや外部serviceを守るためであり、利用者が悪意を持っていると直ちに決める表示ではありません。自動処理の設定ミス、buttonの二重押し、pluginの繰り返し通信でも起こり得ます。原因を確かめる前に制限を外したり、requestを増やしたりしません。

429と503は返している内容が違う

RFC 6585は、429を利用者が一定時間に送ったrequestが多すぎる場合のstatus codeとして定めています。responseには、状況の説明と、再試行までの時間を示すRetry-After headerを含めてもよいとしています。一方、503 Service Unavailableはserviceを一時的に利用できない状態として使われます。どちらも利用者がpageを開けない場合がありますが、直す場所は同じではありません。

status 主に示す状態 最初に確認すること すぐ繰り返さない理由
429 Too Many Requests 一定時間のrequestが多すぎる 送信元、URL、回数、制限時間 再送が制限を長引かせる場合がある
503 Service Unavailable serviceを一時的に利用できない server、maintenance、hosting、復旧時刻 serverへ負荷を加え続ける場合がある
401または403 認証または許可の問題 account、password、権限、URL request回数だけを替えても進めない
500台のerror server側の処理で失敗 error log、plugin、database、外部service 同じ操作で情報を増やさず原因を分ける

説明用の仮例として、WordPressのpluginが外部serviceから商品dataを取得するsiteを考えます。pluginが一分ごとに同じdataを取りに行き、外部serviceから429を受けた場合、WordPressのpageが壊れたとは限りません。まず、取得するURL、実行時刻、実行回数、外部serviceが示す再試行時刻を確認します。requestの間隔を短くして解決しようとすると、さらに制限されるおそれがあります。

反対に、siteの全pageが503を返しているなら、外部serviceのrate limitより、hosting、serverのmaintenance、database、過負荷を確認します。429と503を同じ「server error」として扱うと、外部serviceへ問い合わせるべき問題と、hostingへ連絡すべき問題が混ざります。browserに出たmessageだけで判断せず、HTTP statusと対象URLを残します。

requestを送る人と送るprogramを分けて調べる

429の原因を調べるときは、利用者がbrowserから送ったrequestと、siteが自動的に送ったrequestを分けます。担当者が管理画面でbuttonを何度も押したのか、formが二重送信されたのか、pluginがscheduled taskで繰り返しているのか、外部applicationが同じAPIを呼んでいるのかで、直し方が変わります。

まず、次の情報を一組で残します。

  1. 429が返った日時とtime zone。
  2. requestしたURLと、requestを送ったpageまたはprogram。
  3. response statusと、表示されたmessageまたはRetry-After。
  4. 直前に行った操作と、同じ操作を繰り返した回数。
  5. requestの送り先を管理するserviceまたは担当者。

この記録があれば、制作会社やservice提供者へ状況を伝えられます。「APIが止まった」だけでは、どのURLの何回目のrequestか分かりません。URL、時刻、status、操作を渡せば、相手は制限の範囲を確認できます。

問い合わせformでも、送信buttonを連続で押したときに同じ内容を何度も送らないようにする必要があります。JavaScriptでbuttonを一時的に押せなくする表示は役に立ちますが、browserの表示だけに頼りません。server側でも同じ送信が続いた場合の扱いを決め、利用者へ「送信を受け付けました」か「時間をおいて試してください」かを正しく表示します。画面だけが成功を示し、受信側へ届かない状態を作りません。

外部APIを使う場合は、利用規約や説明で決められたrequest上限を確認します。上限の数字を知らないまま、taskの実行間隔を短くすることは避けます。必要なdataをまとめて取れるか、同じdataをcacheできるか、更新が必要な時刻だけ取得できるかを考えます。APIを呼べることと、何度でも呼んでよいことは別です。

再試行は時間を決めて一度だけ行う

429を受けた直後に、自動処理が短い間隔で再試行し続けると、状況を悪化させる場合があります。Retry-Afterがあるなら、その時間を記録し、示された時刻まで待ちます。headerがない場合も、すぐに連続して送らず、serviceの説明、管理画面のnotice、担当者への確認を先にします。

再試行するときは、同じURLを一度だけ実行し、結果を記録します。成功したか、再び429か、別のstatusかを分けて見ます。失敗するたびに設定、URL、認証、pluginを同時に変えると、何が原因だったか分からなくなります。requestの回数を減らし、変更を一つに絞ります。

たとえば、広告dataを毎時取得するjobが429を返した場合、まずjobを止めるか間隔を延ばします。その後、外部serviceが示す制限と利用中のaccountを確認し、次の実行時刻を決めます。dataをすぐ取り直せない間も、公開siteに表示している金額や在庫が古くなるなら、利用者へ誤った案内を出さない方法を別に決めます。通信の制限と、表示内容の更新責任はつながっていますが、同じ設定ではありません。

制限を外す前に必要なrequestを絞る

429を出さないために、全てのrequest制限を外すことは勧めません。loginやformに制限を設けると、機械的な大量送信による負荷を減らせる場合があります。外部serviceが定めたlimitも、そのserviceを多くの利用者で使うための条件です。制限を変える必要がある場合は、どのURL、どのaccount、どの時間帯、どの仕事へ必要かを説明できる状態にします。

siteを制作会社へ任せている場合も、429を直すためにhostingや外部serviceのaccountを無計画に共有しません。serverを管理する人、WordPressを更新する人、API keyを管理する人、公開するdataを確認する人を分けます。連携の作業を委託しても、どのserviceと契約し、誰が上限変更を頼めるかはsite側で把握します。

最初の一手は、429を受けたURLと時刻を一行で残し、同じ操作を止めることです。その後で送信元と再試行時刻を確かめれば、server停止の対応と混同せずに進められます。

戻る