特定のポートでサーバーと対話する小さなプログラムを作成しました。プログラムは正常に動作しますが、次のようになります。
プログラムが予期せず終了した後、そのソケット接続がCLOSE_WAIT
状態で表示されてから。プログラムを実行しようとすると、ハングし、強制的に閉じる必要があり CLOSE_WAIT
ます。これにより、さらに多くのソケット接続が蓄積されます。
これらの接続をフラッシュする方法はありますか?
特定のポートでサーバーと対話する小さなプログラムを作成しました。プログラムは正常に動作しますが、次のようになります。
プログラムが予期せず終了した後、そのソケット接続がCLOSE_WAIT
状態で表示されてから。プログラムを実行しようとすると、ハングし、強制的に閉じる必要があり CLOSE_WAIT
ます。これにより、さらに多くのソケット接続が蓄積されます。
これらの接続をフラッシュする方法はありますか?
回答:
CLOSE_WAIT
プログラムがまだ実行中であり、ソケットを閉じていないことを意味します(そして、カーネルはそれが閉じるのを待っています)。に追加-p
しnetstat
てpidを取得し、それをより強力に殺します(SIGKILL
必要に応じて)。それはあなたのCLOSE_WAIT
ソケットを取り除くはずです。ps
pidを見つけるために使用することもできます。
SO_REUSEADDR
サーバーとTIME_WAIT
ソケット用なので、ここでは適用されません。
クリストクラークによって説明されているように。
CLOSE_WAITは、接続のローカルエンドがもう一方のエンドからFINを受信したが、OSはローカルエンドのプログラムが実際に接続を閉じるのを待機していることを意味します。
問題は、ローカルマシンで実行されているプログラムがソケットを閉じていないことです。TCPチューニングの問題ではありません。プログラムが接続を開いたままにしている間、接続は(そして非常に正確に)永久にCLOSE_WAITにとどまることができます。
ローカルプログラムがソケットを閉じると、OSはFINをリモートエンドに送信できます。リモートエンドは、FINのACKを待つ間、LAST_ACKに移行します。それが受信されると、接続は終了し、接続テーブルから削除されます(終了がCLOSE_WAITの場合、TIME_WAIT状態になることはありません)。
close()
またはclosesocket()
を使用します。
最新のTomcatサーバー(7.0.40)でも同じ問題が発生しています。数日間、1回応答しなくなります。
開いている接続を確認するには、次を使用できます。
sudo netstat -tonp | grep jsvc | grep --regexp="127.0.0.1:443" --regexp="127.0.0.1:80" | grep CLOSE_WAIT
この投稿で述べたように、を使用/proc/sys/net/ipv4/tcp_keepalive_time
して値を表示できます。値は秒単位のようで、デフォルトは7200(つまり、2時間)です。
それらを変更するには、を編集する必要があります/etc/sysctl.conf
。
Open/create `/etc/sysctl.conf`
Add `net.ipv4.tcp_keepalive_time = 120` and save the file
Invoke `sysctl -p /etc/sysctl.conf`
Verify using `cat /proc/sys/net/ipv4/tcp_keepalive_time`
CLOSE_WAIT接続が多すぎるということは、最初のコードに問題があることを意味しますが、これは適切な方法ではありません。
あなたはチェックアウトしたいかもしれません:https://github.com/rghose/kill-close-wait-connections
このスクリプトが行うことは、接続が待機していたACKを送信することです。
これは私のために働いたものです。
ss
コマンドでソケットを強制的に閉じることができます。インクルードss
コマンドは、ソケット統計をダンプするために使用されるツールであり、netstatと同様の方法で(より単純で高速ですが)情報を表示します。
CLOSE_WAIT状態のソケットを強制終了するには、これを(rootとして)実行します。
$ ss --tcp state CLOSE-WAIT --kill
プログラムが新しいプロセスを生成した場合、そのプロセスが開いているすべてのハンドルを継承する可能性があることにも注意してください。独自のプログラムが終了した後でも、それらの継承されたハンドルは、孤立した子プロセスを介して存続できます。また、netstatでは必ずしも同じように表示されるとは限りません。しかし、それでも、この子プロセスが動作している間、ソケットはCLOSE_WAITでハングします。
ADBを実行している場合がありました。ADB自体は、サーバープロセスがまだ実行されていない場合、サーバープロセスを生成します。これは最初はすべてのハンドルを継承していましたが、調査中にハンドルを所有しているとは表示されませんでした(macOSとWindowsの両方に同じことが当てはまりました。Linuxについてはよくわかりません)。