web-dev-qa-db-ja.com

呼び出し元はHTTPリクエストによって呼び出されたコードの実行を中止できますか?

私が作成しているAPIにHTTPリクエストを送信するサードパーティは、APIが1秒未満で応答することを要求しています。私の質問は、1秒以上かかる場合にコードの実行を中止する方法(文字通りany方法、httpおよび/またはtcp/ipプロトコルの範囲内)があるかどうかです。

8
nicks

HTTPはそのようには機能しません。クライアントが要求を送信し、サーバーが応答を返します。他の通信は発生しません。サーバーは、メインの応答の前に1xxの情報応答を送信できます。ただし、クライアントが送信されたリクエストに関する更新を送信する方法はありません。

(同じ接続で複数の要求を多重化できるHTTP/2の場合は状況が大きく異なります。クライアントは、サーバーからPush_PROMISEを受信した後、ストリームをキャンセルして、不要になったことを示すことができます。HTTP/ 2は無視しますこの答えの残りのために。)

また、ネットワークはそのように機能しません。特に、2番目の 分散コンピューティングの誤り :「レイテンシはゼロ」を参照してください。そうではない。その1秒のタイムアウトのうち、接続の確立と要求の送信に400ミリ秒、応答に600ミリ秒が費やされた可能性があります。パケットの1つがドロップされ、すべてを再送信する必要があり、クライアントはオーストラリアにいるためです。サーバーに十分な時間がない可能性があるという問題は別として、サーバーは応答待ち時間を事前に知ることができないため、サーバーがどれだけの時間を持っているかも知りません。

文字通りこれらのタイムアウトを実装することは不可能であることを考えると、どのようなソリューションで十分でしょうか?

タイムアウト後に応答に値がない場合、クライアントは単に接続を閉じることができます。これにより、応答が無視されますが、応答が妨げられることはありません。

HTTPリクエストが送信されるTCP接続を閉じると、サーバーに通知されます。ただし、この通知は遅延して到着するだけなので、遅すぎる可能性があります。また、Webフレームワークが何も実行していない可能性がありますクライアントソケットが閉じている場合、閉じたソケットに書き込もうとすると、「ピアによって接続がリセットされました」というエラーが表示されます。

応答の処理に1秒以上費やしたくない場合は、そのタイムアウトの実装は完全にユーザーの責任であり、ネットワークやHTTPとは関係ありません。

サーバーにタイムアウトを提供するようにクライアントに要求することができます。これにより、サーバーが期限に間に合わない場合はサーバーを中止できます。これは、カスタムヘッダーとして、またはURLのクエリパラメーターとして指定できます。この期限は絶対的な時点であり、送信遅延が利用可能な時間を消費するように期間ではありません。ただし、1秒未満の精度は困難です。サーバーとクライアントを正しい時刻に同期させ、適切なクロックを使用する必要があります。セットアップによっては、正しく構成されている場合でも、各時間ソースが100msオフになる場合があります。これは、時間の予算のかなりの部分をすでに消費しています。

9
amon

彼らは接続を閉じることができると思いますが、それによって実際にコードが異常終了するかどうかはわかりません。コードの記述方法によって異なります。

また、「時間がかかりすぎるので気にしないでください」という別のメッセージを送信することもできますが、その場合はおそらく、明示的なCANCEL_REQUESTメッセージを処理する準備が整っているはずです。