面試時(shí)看到應聘者簡(jiǎn)歷中寫(xiě)精通網(wǎng)絡(luò ),TCP編程,我常問(wèn)一個(gè)問(wèn)題,TCP建立連接需要幾次握手?95%以上的應聘者都能答對是3次。問(wèn)TCP斷開(kāi)連接需要幾次握手,70%的應聘者能答對是4次通訊。再問(wèn)CLOSE_WAIT,TIME_WAIT是什么狀態(tài),怎么產(chǎn)生的,對服務(wù)有什么影響,如何消除?有一部分同學(xué)就回答不上來(lái)。不是我扣細節,而是在通訊為主的前端服務(wù)器上,必須有能力處理各種TCP狀態(tài)。比如統計在本廠(chǎng)的一臺前端機上高峰時(shí)間TCP連接的情況,統計命令:
結果:

除了ESTABLISHED,可以看到連接數比較多的幾個(gè)狀態(tài)是:FIN_WAIT1, TIME_WAIT, CLOSE_WAIT, SYN_RECV和LAST_ACK;下面的文章就這幾個(gè)狀態(tài)的產(chǎn)生條件、對系統的影響以及處理方式進(jìn)行簡(jiǎn)單描述。
TCP狀態(tài)如下圖所示:

可能有點(diǎn)眼花繚亂?再看看這個(gè)時(shí)序圖

下面看下大家一般比較關(guān)心的三種TCP狀態(tài)
服務(wù)端收到建立連接的SYN沒(méi)有收到ACK包的時(shí)候處在SYN_RECV狀態(tài)。有兩個(gè)相關(guān)系統配置:
默認值是5
對于遠端的連接請求SYN,內核會(huì )發(fā)送SYN + ACK數據報,以確認收到上一個(gè) SYN連接請求包。這是所謂的三次握手( threeway handshake)機制的第二個(gè)步驟。這里決定內核在放棄連接之前所送出的 SYN+ACK 數目。不應該大于255,默認值是5,對應于180秒左右時(shí)間。通常我們不對這個(gè)值進(jìn)行修改,因為我們希望TCP連接不要因為偶爾的丟包而無(wú)法建立。
一般服務(wù)器都會(huì )設置net.ipv4.tcp_syncookies=1來(lái)防止SYN Flood攻擊。假設一個(gè)用戶(hù)向服務(wù)器發(fā)送了SYN報文后突然死機或掉線(xiàn),那么服務(wù)器在發(fā)出SYN+ACK應答報文后是無(wú)法收到客戶(hù)端的ACK報文的(第三次握手無(wú)法完成),這種情況下服務(wù)器端一般會(huì )重試(再次發(fā)送SYN+ACK給客戶(hù)端)并等待一段時(shí)間后丟棄這個(gè)未完成的連接,這段時(shí)間的長(cháng)度我們稱(chēng)為SYN Timeout,一般來(lái)說(shuō)這個(gè)時(shí)間是分鐘的數量級(大約為30秒-2分鐘)。
這些處在SYNC_RECV的TCP連接稱(chēng)為半連接,并存儲在內核的半連接隊列中,在內核收到對端發(fā)送的ack包時(shí)會(huì )查找半連接隊列,并將符合的requst_sock信息存儲到完成三次握手的連接的隊列中,然后刪除此半連接。大量SYNC_RECV的TCP連接會(huì )導致半連接隊列溢出,這樣后續的連接建立請求會(huì )被內核直接丟棄,這就是SYN Flood攻擊。
能夠有效防范SYN Flood攻擊的手段之一,就是SYN Cookie。SYN Cookie原理由D. J. Bernstain和 Eric Schenk發(fā)明。SYN Cookie是對TCP服務(wù)器端的三次握手協(xié)議作一些修改,專(zhuān)門(mén)用來(lái)防范SYN Flood攻擊的一種手段。它的原理是,在TCP服務(wù)器收到TCP SYN包并返回TCP SYN+ACK包時(shí),不分配一個(gè)專(zhuān)門(mén)的數據區,而是根據這個(gè)SYN包計算出一個(gè)cookie值。在收到TCP ACK包時(shí),TCP服務(wù)器在根據那個(gè)cookie值檢查這個(gè)TCP ACK包的合法性。如果合法,再分配專(zhuān)門(mén)的數據區進(jìn)行處理未來(lái)的TCP連接。
發(fā)起TCP連接關(guān)閉的一方稱(chēng)為client,被動(dòng)關(guān)閉的一方稱(chēng)為server。被動(dòng)關(guān)閉的server收到FIN后,但未發(fā)出ACK的TCP狀態(tài)是CLOSE_WAIT。出現這種狀況一般都是由于server端代碼的問(wèn)題,如果你的服務(wù)器上出現大量CLOSE_WAIT,應該要考慮檢查代碼。
根據TCP協(xié)議定義的3次握手斷開(kāi)連接規定,發(fā)起socket主動(dòng)關(guān)閉的一方 socket將進(jìn)入TIME_WAIT狀態(tài)。TIME_WAIT狀態(tài)將持續2個(gè)MSL(Max Segment Lifetime),在Windows下默認為4分鐘,即240秒。TIME_WAIT狀態(tài)下的socket不能被回收使用. 具體現象是對于一個(gè)處理大量短連接的服務(wù)器,如果是由服務(wù)器主動(dòng)關(guān)閉客戶(hù)端的連接,將導致服務(wù)器端存在大量的處于TIME_WAIT狀態(tài)的socket, 甚至比處于Established狀態(tài)下的socket多的多,嚴重影響服務(wù)器的處理能力,甚至耗盡可用的socket,停止服務(wù)。
為什么需要TIME_WAIT?TIME_WAIT是TCP協(xié)議用以保證被重新分配的socket不會(huì )受到之前殘留的延遲重發(fā)報文影響的機制,是必要的邏輯保證。
和TIME_WAIT狀態(tài)有關(guān)的系統參數有一般由3個(gè),本廠(chǎng)設置如下:
net.ipv4.tcp_tw_recycle = 1
net.ipv4.tcp_tw_reuse = 1
net.ipv4.tcp_fin_timeout = 30
net.ipv4.tcp_fin_timeout,默認60s,減小fin_timeout,減少TIME_WAIT連接數量。
net.ipv4.tcp_tw_reuse = 1表示開(kāi)啟重用。允許將TIME-WAIT sockets重新用于新的TCP連接,默認為0,表示關(guān)閉;
net.ipv4.tcp_tw_recycle = 1表示開(kāi)啟TCP連接中TIME-WAIT sockets的快速回收,默認為0,表示關(guān)閉。
下一篇:http://maoyidao.iteye.com/blog/1744309 “通訊系統經(jīng)驗談【二】解讀內核參數 - socket/文件句柄資源限制參數”會(huì )向大家介紹本廠(chǎng)網(wǎng)絡(luò )相關(guān)設置中的其他選項,特別是系統資源限制相關(guān)的內核配置。
聯(lián)系客服