TIME_WAIT 狀態


根據TCP協議,主動發起關閉的一方,會進入TIME_WAIT狀態,持續2*MSL(Max Segment Lifetime)預設240秒,在這個 post 中簡潔的介紹了為什需要這個狀態。

值得一說的是,對於基於TCPHTTP協議,關閉TCP連接的是Server端,這樣,Server端會進入TIME_WAIT狀態,可想而知,對於訪問量大的Web Server,會存在大量的TIME_WAIT狀態,假如server一秒鐘接收1000個請求,那就會積壓240*1000=240,000TIME_WAIT的記錄,維護這些狀態給Server帶來負擔。當然現代操作系統都會用快速的查找算法來管理這些TIME_WAIT,所以對於新的TCP連接請求,判斷是否hit中一個TIME_WAIT不會太費時間,但是有這多狀態要維護總是不好。

HTTP協議1.1版規定default行為是Keep-Alive
也就是會重用TCP連接傳輸多個request/response,一個主要原因就是發現了這個問題。
還有一個方法減緩TIME_WAIT壓力就是把系統的2*MSL時間減少,
因為240秒的時間實在是長了點,對於Windows,修改注冊表,
HKEY_LOCAL_MACHINE \SYSTEM\CurrentControlSet\Services\Tcpip\Parameters上添加一個DWORD類型的值TcpTimedWaitDelay,一般認為不要少於60,不然可能會有麻煩。

對於大型的服務,一台server搞不定,需要一個LB(Load Balancer)把流量分配到若干端服務器上,如果這個LB是以NAT方式工作的話,可能會帶來問題。
假如所有從LBServerIP包的source address都是一樣的(LB的對內地址),那麼LB到後端ServerTCP連接會受限制,
因為頻繁的TCP連接建立和關閉,會在Server上留下 TIME_WAIT狀態,而且這些狀態對應的remote address都是LB的,LBsource port撐死也就60000多個 (2^16=65536,1~1023是保留端口,還有一些其他端口預設也不會用),每個LB上的端口一旦進入ServerTIME_WAIT黑名單,就有240秒不能再用來建立和Server的連接,
這樣LBServer最多也就能支持300個左右的連接。
如果沒有LB,不會有這個問題,因為這樣server看到的remote addressinternet上廣闊無垠的集合,對每個address60000多個port實在是夠用了。
一開始我覺得用上LB會很大程度上限制TCP的連接數,
但是實驗表明沒這回事,LB面的一台Windows Server 2003每秒處理請求數照樣達到了600個,難道TIME_WAIT狀態沒起作用?
Net Monitornetstat觀察后發現,ServerLBXXXX端口之間的連接進入TIME_WAIT狀態后,再來一個LBXXXX端口的SYN包,Server照樣接收處理了,而不是想像的那樣被drop掉了。
翻書,從書堆里面找出覆滿塵土的大學時代買的《UNIX Network Programming, Volume 1, Second Edition: Networking APIs: Sockets and XTI》,中間提到一句,對於BSD-derived實現,只要SYNsequence number比上一次關閉時的最大sequence number還要大,那TIME_WAIT 狀態一樣接受這個SYN,難不成Windows也算BSD-derived? 有了這點線索和關鍵字(BSD),找到這個post,在NT4.0的時候,還是和BSD-derived不一樣的,不過Windows Server 2003已經是NT5.2了,也許有點差別了。

做個試驗,用Socket API編一個Client端,每次都Bind到本地一個端口比如2345,重的建立TCP連接往一個Server發送Keep-Alive=falseHTTP請求,Windows的實現讓sequence number不斷的增長,所以雖然Server對於Client 2345端口連接保持TIME_WAIT狀態,但是總是能夠接受新的請求,不會拒絕
那如果SYNSequence Number變小會怎麼樣呢?樣用Socket API,不過這次用Raw IP,發送一個小sequence numberSYN包過去,Net Monitor里面看到,這個SYNServer接收如泥牛如海,一點反應沒有,被drop掉了。

按照書上的說法,BSD-derivedWindows Server 2003的做法有安全隱,不過至少這樣至少不會出現TIME_WAIT阻止TCP請求的問題,當然,客戶端要配合,保證不TCP連接的sequence number要上漲不要下降。



沒有留言:

張貼留言