サーバーに多くの短期間の接続を行うクライアントがあると仮定しましょう。
クライアントが接続を閉じると、クライアント側に多くのポートがTIME_WAIT
状態になります。クライアントはローカルポートを使い果たすため、すぐに新しい接続を試みることは不可能になります。
サーバーが接続を閉じると、サーバー側に多くのTIME_WAIT
が表示されます。しかし、これは害を及ぼしますか?クライアント(または他のクライアント)はローカルポートを使い果たすことがないため、接続試行を続けることができ、サーバー側でTIME_WAIT
状態の数が増加します。最終的にはどうなりますか?何か悪いことが起こりますか? (スローダウン、クラッシュ、接続の切断など)
私の質問は「TIME_WAIT
の目的は何ですか?」ではないことに注意してください。しかし、「サーバー上に非常に多くのTIME_WAIT
状態があるとどうなりますか?」 TCP/IPで接続が閉じられたときに何が起こるか、そしてTIME_WAIT
状態が必要な理由はすでに知っています。トラブルシューティングをしようとはしていませんが、潜在的な問題を知りたいだけです。
簡単に言うと、netstat -nat | grep :8080 | grep TIME_WAIT | wc -l
が100000
を出力するとします。どうなるの? O/Sネットワークスタックの速度は低下しますか? 「開いているファイルが多すぎます」エラー?または、心配することは何もありませんか?
TIME_WAIT
の各ソケットは、カーネル内のメモリを消費します。通常は、ESTABLISHED
ソケットよりもいくらか少なくなりますが、それでもかなりの量です。十分に大きな数を設定すると、カーネルメモリが使い果たされるか、少なくともメモリが他の目的に使用される可能性があるため、パフォーマンスが低下する可能性があります。 TIME_WAIT
ソケットは開いているファイル記述子を保持しないため(適切に閉じられていると仮定)、「開いているファイルが多すぎる」エラーを心配する必要はありません。
ソケットは、特定のsrc
/dst
IPアドレスとポートも結び付けるため、TIME_WAIT
間隔の間は再利用できません。 (これはTIME_WAIT
状態の目的です。)同じポートペアで再接続する必要がない限り、ポートの接続は通常は問題になりません。ほとんどの場合、片側は一時ポートを使用し、片側のみが既知のポートに固定されます。ただし、同じ2つのIPアドレスを繰り返し頻繁に接続している場合、非常に多くのTIME_WAIT
ソケットが一時的なポートスペースを使い果たす可能性があります。これはこの特定のIPアドレスペアにのみ影響し、他のホストとの接続の確立には影響しないことに注意してください。
各接続は、タプル(サーバーIP、サーバーポート、クライアントIP、クライアントポート)によって識別されます。重要なのは、TIME_WAIT
接続(サーバー側またはクライアント側)は、それぞれこれらのタプルの1つを占有します。
とともに TIME_WAIT
sクライアント側では、これ以上接続できない理由を簡単に確認できます。ローカルポートはもうありません。ただし、サーバー側にも同じ問題が適用されます-TIME_WAIT
state 単一のクライアントの場合、それ以上の接続を受け入れることができませんそのクライアントから、古い接続と新しい接続の違いを知る方法がないため接続-両方の接続は同じタプルによって識別されます。この場合、サーバーはRST
sをそのクライアントからの新しい接続試行に送り返すだけです。
これまでの調査結果:
サーバーがシステムコールを使用してソケットを閉じた場合でも、TIME_WAIT状態になった場合、そのファイル記述子は解放されません。ファイル記述子は、TIME_WAIT状態がなくなると(つまり、2 * MSL秒後に)解放されます。したがって、TIME_WAITが多すぎると、サーバープロセスで「開いているファイルが多すぎる」エラーが発生する可能性があります。
O/S TCP/IPスタックは適切なデータ構造(ハッシュテーブルなど)で実装されているため、TIME_WAITの総数がO/S TCP/IPスタックのパフォーマンスに影響を与えることはないと思います。 TIME_WAIT状態のソケットを所有するプロセス(サーバー)のみが影響を受けます。
多くの異なるクライアントIPからサーバーIPへの接続が多数ある場合、接続追跡テーブルの制限に遭遇する可能性があります。
チェック:
sysctl net.ipv4.netfilter.ip_conntrack_count
sysctl net.ipv4.netfilter.ip_conntrack_max
すべてのsrc ip/portおよびdest ip/portタプルでは、追跡テーブルにnet.ipv4.netfilter.ip_conntrack_maxのみを含めることができます。この制限に達すると、ログに「nf_conntrack:テーブルがいっぱいです。パケットをドロップします」というメッセージが表示されます。サーバーは、追跡テーブルに再びスペースができるまで、新しい着信接続を受け入れません。
この制限は、一時ポートがなくなるかなり前にあなたを襲うかもしれません。
私のシナリオでは、ファイルを繰り返しスケジュールするスクリプトを実行し、私の製品はいくつかの計算を行い、クライアントに応答を送信します。つまり、クライアントは各ファイルの応答を取得するために繰り返しhttp呼び出しを行います。 time_wait状態で、クライアントで例外がスローされ、HTTP接続が開かれます。
Error : [Errno 10048] Only one usage of each socket address (protocol/network address/port) is normally permitted
その結果、アプリケーションがハングしました。スレッドが待機状態になったのか、何が起こったのかはわかりませんが、すべてのプロセスを強制終了するか、アプリケーションを再起動して動作させる必要があります。
デフォルトでは240秒であるため、待機時間を30秒に短縮しようとしましたが、機能しませんでした。
そのため、アプリケーションが応答しなくなるため、基本的に全体的な影響が重要でした。