やったこと
API デザインパターン 29章 リクエストの再試行 読了
学んだこと
ポイント
どんな時に再試行するべきか
クライアント側で再試行する際の有力なアルゴリズムは何か
API側で、クライアントに、再試行タイミングを伝える方法
学び
一過性、またはタイミングに起因するエラーは、再試行によってエラーを解消できる可能性がある
クライアント側で再試行する場合は、指数バックオフを実装すると良い
実装の際は、以下の制限を加えること
最大試行回数
最大遅延時間
また、以下を実装すると良い
ランダムジッター
Retry-After HTTP ヘッダーを使用して、クライアント側に、再試行タイミングを伝える
値は、「遅延させる秒数」が有力
メモ
Web APIで発生するエラーの内、クライアントではコントロールできない何かに起因するエラーは、リクエストの再試行にて解決することがある。
しかし、むやみに再試行すると、別の問題を引き起こす可能性がある。
本章では、クライアントが、いつ、どのように再試行するか、よりよいメカニズムを探る。
クライアントではコントロールできない何かに起因するエラーの例
サーバー側の過負荷
サービス提供に必要なコンポーネントが、(予定されていた)一時的なダウンタイムに入っている
概要
「多くのリクエストにレスポンスを返しつつ、できるだけ再試行を少なくする」ことを目標とする。
そのためには、以下の基本方針に従う。
クライアント側で指数バックオフを実装し、再試行してもらう
API側で最適な再試行タイミングを把握できるなら、再試行タイミングをクライアントに指示する
例
API が一分に1回だけしか処理を実行できないなら、API側は次回実行できるタイミングを把握できるはず
実装
再試行可能か
一般的に、エラーレスポンスには、以下の3つのカテゴリーがある。
絶対に再試行できないもの
403,405,412,501 辺り
再試行できるかもしれないが慎重に検討すべきもの
500, 502, 504 辺り
何の問題もなく再試行できるもの
408, 421, 425, 429 503 辺り
エラーコードから、再試行するべきか判断すること。
指数バックオフ
指数バックオフには、以下の制限を追加すると良い。
最大試行回数
最大遅延時間
最大遅延時間を超えて待機しないようにする
また、以下を実装することが推奨される。
ランダムジッターの導入
指数バックオフに従った時間に、ランダムな値を加えた時間だけ待機するようにする
複数のリクエストが、同じタイミングで指数バックオフを実行し、同一時間でリクエストが集中する状況を回避する
これにより、指数バックオフが最終的に失敗するという保証を得ることが出来る。
これは、「何度か再試行しましたが、成功する応答を得られませんでした」という意味になる。
Retry-After
API側で把握している最適な再試行タイミングをクライアントに伝える場合、 Retry-After HTTPヘッダーを使用する。
書式は、以下の二つのいずれか。
タイムスタンプ
遅延させる秒数
秒数指定の方が、利用者に受け入れられやすい。
トレードオフ
指数バックオフの実装は、クライアント側にゆだねられることになる。
言い換えると、API提供側では制御できない
指数バックオフの導入によって失うものはないとされている。
つまり、現時点で欠点は発見されていない。
扱うこと
失敗したAPIリクエストを再試行しても安全かどうかを判断する方法
再試行のタイミングを決めるための高度な指数バックオフ方式
リクエストの集中を回避する方法
APIがクライアントに再試行のタイミングを指示できる方法
まとめ
一過性、あるいはタイミングに起因するエラーは再試行する価値がある
一方、恒久的な状態に依存するエラー(403など)は、再試行する価値は薄い
自動的にリクエストを再試行する場合、指数バックオフを利用すること
リクエストが同じ時間に到着することに起因する問題(殺到する群れ問題)を避けることが出来る
APIが、再試行するべき(≒成功する可能性のある)タイミングを知っている場合、Retry-After HTTPヘッダを使用して、クライアントに伝える