応答を待ち続けないためのタイムアウト

タイムアウトは、応答がない相手への待ち時間に上限を設けて、それを超えたら処理を打ち切る仕組みです。

電話をかけて相手が出なければ、いつまでも受話器を耳に当てて待つわけにはいきません。何回か呼び出して出なければ切って、次にどうするかを考えます。システムにも、この「切るまでの時間」が要ります。それがタイムアウトです。応答を待つ時間に上限を付け、超えたら処理を諦めて先へ進みます。

外部の API やサービスへのリクエスト、データベースへの問い合わせ、ネットワーク越しのファイルの取得。相手から返事が来ない可能性がある場面では、たいていタイムアウトが設定されています。一定時間操作のない利用者のログイン状態を切るのも、同じ考え方です。

待ち続けるとほかの人まで待たされる

返事をしない相手を待ち続けると、その間、つながりっぱなしの接続が一つ残ります。同じ相手への依頼が次々に来れば、待っている接続がどんどん積み上がり、やがてほかの利用者への応答まで遅れ始めます。最悪の場合は、処理を受け持つ手(スレッド)がすべて待ち状態でふさがり、サービス全体が止まります(スレッド枯渇)。

タイムアウトを入れておけば、一定時間で待つのをやめてエラーとして扱い、次の処理へ進めます。外部との通信には、必ずタイムアウトを入れておくのが基本です。

「つながるまで」と「返事が来るまで」

待ち時間には2つの段階があります。相手につながるまでの上限(接続タイムアウト)と、つながったあとにデータが返ってくるまでの上限(読み取りタイムアウト)です。電話でいえば、呼び出し音が鳴り続ける時間と、相手が出たあと黙り込んでいる時間。原因も対処も違うので、分けて設定します。

諦めたあとどうするか

上限を短くしすぎると、少し時間がかかっているだけの正常な処理まで失敗にしてしまいます。応答が返るまでの普段の時間(レイテンシ)を見たうえで、許せる上限を決めます。

タイムアウトしたときに、もう一度試す(リトライ)のか、エラーとして返すのか。これも先に決めておきます。利用者に見せるなら、何が起きて、次に何をすればよいかが伝わる表示にします。

タイムアウトが急に増えたら、それは相手の処理が遅れている、あるいはネットワークに問題が起きているというサインです。上限を延ばして黙らせる前に、原因を調べてください。