理解TIME_WAIT_網路編程

來源:互聯網
上載者:User

轉自 www.firefoxbug.com/index.php/archives/2795/



前言

TIME_WAIT 是在TCP協議中很模糊的概念,它可能使socke能陷入的一種時間相對比較長的狀態,過多的TIME_WAIT會影響新socket的建立。TIME_WAIT為什麼會存在。它的作用又是什麼。下面我們就來理解下TIME_WAIT。

這張圖詳細的列出了TCP建立串連和中斷連線的各個TCP狀態之間的轉換。紅色的代表server,藍色的代表client。下面列出各自的TCP狀態轉換條件 TCP建立串連 Client: 向server發送 SYN 包,表示請求建立串連,進入 SYN_SENT 狀態; Server: 接收來自client的 SYN 包,發送 SYN/ACK 包,代表client->server單向tcp串連已經建立, 進入 SYN_RCVD 狀態; Client: 接收到來自server的 SYN/ACK 包,發送給server ACK 包,進入 Established 狀態; Server: 收到client的 ACK 包,代表 server->client 的單向tcp串連也建立,此時進入 Established 狀態; TCP中斷連線

先引入兩個概念,首先調用close()是"主動關閉"(active close),另一個是"被動關閉"(passive close)。一般我們連上ftp或者http,中斷連線的都是用戶端。看上面的圖,"主動關閉"端狀態要經曆3個狀態,而TIME_WAIT是屬於“主動關閉”端最後的一個tcp狀態。

client: 主動調用close(),發送 FIN 包,此時client就"主動關閉"端,進入 FIN_WAIT_1 狀態; Server: server自然成為"被動關閉"端,收到來自client的 FIN 包,發送 ACK 包,代表client->server單向tcp串連已經關閉,進入 CLOSE_WAIT 狀態; Client: 接收到來自server的 ACK 包,啥都不做,client->server單向的tcp串連已經斷開,不能再發送應用程式層資料,進入 FIN_WAIT_2 狀態; Server: server端給client端發送 FIN 包,代表準備關閉server->client的tcp串連,server進入LAST_ACK 狀態; Client: 收到來自server的 FIN 包,發送 ACK 包,此時進入 TIME_WAIT 狀態; Server: 收到Client的 ACK 包,就進入closed狀態,Server端此次socket tcp串連完全連接埠; Client: 持續TIME_WAIT狀態"一段時間"; 理解TIME_WAIT

理解了上面的原理之後,接著就是正式介紹TIME_WAIT。TIME_WAIT的時間大多數情況下都是2倍的MSL(Maximum Segment Lifetime),MSL是一個資料包在網路上能生存的最長生命週期,一旦超過MSL的包就會被丟棄。從上面可以看到,TIME_WAIT是“主動關閉”端的最後一個狀態,引入TIME_WAIT的原因有:

1. 確保"主動關閉"端最後發出的 ACK 到達"被動關閉"端2. 保證新tcp串連和老tcp串連不會干擾
原因1: 確保"主動關閉"端最後發出的 ACK 到達"被動關閉"端

看上面tcp中斷連線的圖,由client主動調用close(),發出FIN包,然後接收到server的ACK/FIN包,用戶端最後發一個FIN包,進入TIME_WAIT。

設想一下,如果沒有TIME_WAIT,client端發送最後的FIN包后里面關閉串連,如果由於網路原因,最後發出的FIN包沒有順利到達server(此時的server一直處於LAST_ACK狀態等待最後FIN),server長時間沒有接收到FIN包,會認為之前由server發出的ACK/FIN包client沒有收到,server會重新發送一個ACK/FIN包,這時候client收到ACK/FIN包,發現連接埠已經關閉,協議棧直接回複RST包,導致server端接收到RST包報錯,影響應用進程。

所以 TIME_WAIT 的作用可以保證最後的ACK包必然能到達對方,確保最後的串連正常連接埠。也解釋了TIME_WAIT時間是2*MSL的原因。 原因2: 保證新tcp串連和老tcp串連不會干擾

看看下面的圖

End Point2發送FIN包後,沒有進入TIME_WAIT狀態,此時新的tcp請求又來了,而且src_ip,src_port,dst_ip,dst_port都是一樣的,新的串連建立TCP請求後,老的串連包可能會干擾新串連的包,導致亂序。所以引入TIME_WAIT,2*MSL能讓老串連的包徹底在網路中消失,保證新串連絕對乾淨。 TIME_WAIT數量多。

TIME_WAIT是佔資源的,包括連接埠資源,協議棧隊列,所以大量的TIME_WAIT會影響socket建立新串連,這點特別在高效能的Web伺服器中很講究,那麼有辦法去減少TIME_WAIT數量嗎。嘿嘿,看了上面TIME_WAIT存在的原因後,還想去調整tcp_tw_recycle或者tcp_tw_reuse等參數嗎。這很有可能會引發未知的TCP錯誤,而且很詭異,很難排查。所以在高效能的Web伺服器裡面,必然會去設定HTTP的KeepAlive,不然Web伺服器立馬就被大量的TIME_WAIT影響服務。 調整TIME_WAIT數量

要調整TIME_WAIT的數量,網上都是這幾個參數,要修改的話還是悠著點吧。

net.ipv4.tcp_tw_reuse = 0 表示開啟重用。允許將TIME-WAIT sockets重新用於新的TCP串連,預設為0,表示關閉;開啟tcp_tw_reuse的時候要注意,是用戶端還是服務端,如果是net.ipv4.tcp_tw_recycle = 0  表示開啟TCP串連中TIME-WAIT sockets的快速回收,預設為0,表示關閉。net.ipv4.tcp_fin_timeout = 30  表示如果通訊端由本端要求關閉,這個參數決定了它保持在FIN-WAIT-2狀態的時間。net.ipv4.tcp_tw_timeout = 15 標識TIME_WAIT的回收時間。
tcp_tw_recycle

tcp_tw_recycle必須和tcp_timestamps一起開啟,預設情況linux的tcp_timestamps都是開啟的,tcp_tw_recycle到底是多久回收sockets。正常是700ms。

tcp_tw_recycle的坑:當多個用戶端通過NAT方式連網並與服務端互動時,服務端看到的是同一個IP,也就是說對服務端而言這些用戶端實際上等同於一個,可惜由於這些用戶端的時間戳記可能存在差異,於是乎從服務端的視角看,便可能出現時間戳記錯亂的現象,進而直接導致時間戳記小的資料包被丟棄

注意:在NAT模型中,tcp_tw_recycle開啟可能會導致丟包 tcp_tw_reuse tcp_tw_reuse選項和tcp_timestamps選項也必須同時開啟; 重用TIME_WAIT的條件是收到最後一個包後超過1s 總結

TIME_WATI出現在TCP串連"主動關閉"端,理論上會持續2*MSL(根據不通系統而定,因為IP有TTL),TIME_WAIT的出現是為瞭解決兩個問題

1. 確保串連能正確斷開(確保"主動關閉"端最後發出的 ACK 到達"被動關閉"端)2. 確保新的tcp串連和老的tcp串連不會干擾

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.