3流プログラマのメモ書き

元開発職→社内SE→派遣で営業支援→開発戻り浦島太郎状態の三流プログラマのIT技術メモ書き。 このメモが忘れっぽい自分とググってきた技術者の役に立ってくれれば幸いです。

TCP/IP Time_Wait の時間について

netstat -an で現在のセッション情報が見えるわけですが、とある Windows サーバでかなり TIME_WAIT が発生してました。

netstat のステータスで LISTENING が待ちうけ中、ESTABLISHED が通信中(コネクション確立)ってのは知ってたんですが、TIME_WAIT ってのはよくわかってなかったので調べてみました。

ということで、まずTCPでのコネクションの確立と切断処理を@IT:連載 基礎から学ぶWindowsネットワーク 第16回 信頼性のある通信を実現するTCPプロトコル(3)で確認します。

↑には分かりやすい状態遷移図があるので非常に参考になります。

これを見ると TIME_WAIT というのはコネクションのアクティブクローズ時(自身から切断要求時)に、コネクションしてたのと同じポートが再利用されないための待ち時間のようです。

この待ち時間を過ぎてからセッションが完全に閉じる CLOSED の状態になります。

(ちなみに、TCPの接続クローズ処理は@IT:連載 基礎から学ぶWindowsネットワーク 第15回 信頼性のある通信を実現するTCPプロトコル(2)でシーケンス図が載せられており、分かりやすいです。)

コネクションを大量に張るサービスをしてるサーバだと TIME_WAIT が多いと使用できるポートが減ってしまうためよろしくありません。

この TIME_WAIT の時間ですが、UnixLinuxではデフォルト60秒らしいですが、Windowsだと120秒のようです。(Windows2000は240秒のようです。)

この値を減らすことで限りあるポートを有効に活用できコネクションの接続数を増加させることができそうです。

(ただTCPについて書いてるRFC793をみるとこの TIME_WAIT 値は最大セグメント生存時間(MSL)の2倍がいいようで、通常MSLは2分なので、RFC793に基づくと TIME_WAIT 値は4分(240秒)となります。つまり、Windows2000の実装はRFC準拠というわけですね。)

さて、この TIME_WAIT の値の設定方法ですが、Windowsだとレジストリで設定できるようです。

レジストリの HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters に TcpTimedWaitDelay(DWORD) を作成し、その値に TIME_WAIT の値を秒単位で設定します。

WindowsTCPチューニングでよく言われるのはこの TIME_WAIT の調整と使用できるポート数の制限値の調整です。

デフォルトだと5000みたいなので、この値を増やしてやるといいようですね。設定は上記(TcpTimedWaitDelay)と同じレジストリパスに MaxUserPort (DWORD) を作成し値を入れてやるといいようです。

Linuxの場合は下記のようにしてやると TIME_WAIT の値を設定できるようです。

/proc/sys/net/ipv4/tcp_tw_recycle ファイルの値を1とする。

/proc/sys/net/ipv4/tcp_fin_timeout ファイルに TIME_WAIT の値を秒単位で記述。

なかなか TCP/IP のチューニングは難しいです。

参考:

TCP/IP で TIME_WAIT が残る時間を短くする

Windowsにおけるソケットの最大値とTIME_WAITの時間を修正しよう: sanonosa システム管理コラム集

TIME_WAITとBindExceptionの抑制 - Kazzzの日記

MSサポート:Windows XP での TCP/IP と NBT の構成パラメータ Windowsレジストリで設定できるTCP/IPのパラメータ一覧です。これみると他にもいろいろできそうです。

UNIXしま専科 - ブログ Linuxで60s*2ML=120秒というはあってる?

CommuniGate Pro: Scalability

TIME_WAITとMSL - sato-bb.net