私は特定のポートでサーバーと対話する小さなプログラムを書きました。プログラムは問題なく動作しますが、
プログラムが予期せず終了した後、そしてそのソケット接続はCLOSE_WAIT
状態で表示されます。プログラムを実行しようとするとハングアップし、強制的に閉じる必要があります。これはmoreCLOSE_WAIT
ソケット接続でさえも累積します。
これらの接続をフラッシュする方法はありますか?
CLOSE_WAIT
はあなたのプログラムがまだ実行中で、ソケットを閉じていないことを意味します(そしてカーネルはそれが行われるのを待っています)。 pidを取得するためにnetstat
に-p
を追加してから、より強力に(必要に応じてSIGKILL
を使用して)それを強制終了します。それはあなたのCLOSE_WAIT
ソケットを取り除くでしょう。 pidを見つけるためにps
を使うこともできます。
SO_REUSEADDR
はサーバーとTIME_WAIT
ソケットのためのものなので、ここでは適用されません。
Crist Clark で説明されているように。
CLOSE_WAITは、接続のローカルエンドが相手側からFINを受信しましたが、OSはローカルエンドのプログラムが実際にその接続を閉じるのを待っていることを意味します。
問題は、ローカルマシンで実行されているプログラムがソケットを閉じていないことです。これはTCP調整の問題ではありません。プログラムが接続を開いたままにしている間、接続は(そしてまったく正しく)CLOSE_WAITに永遠にとどまることができます。
ローカルプログラムがソケットを閉じると、OSはリモートエンドにFINを送信して、FINのACKを待つ間にLAST_ACKに遷移します。それが受け取られれば、接続は終了し、接続テーブルから落ちます(あなたの端がCLOSE_WAITにあればあなたがするないTIME_WAIT状態に終わらない) 。
CLOSE_WAIT接続が多すぎると、最初はコードに問題があることを意味しますが、これは受け入れられません。
あなたがチェックアウトすることをお勧めします: https://github.com/rghose/kill-close-wait-connections
このスクリプトが行うことは、接続が待っていたACKを送信することです。
これは私のために働いたものです。
最新の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`
クライアント側とサーバー側の両方のSocket
インスタンスは、明示的にclose()
を呼び出す必要があることに注意してください。どちらか一方の端だけがclose()
を呼び出す場合も、ソケットはCLOSE_WAIT状態のままになります。