TCP協議之網絡延時

影響TCP 網絡時延的因素
硬件速度
網絡和服務器的負載
請求和響應報文的尺寸
客戶端和服務器之間的距離
TCP 協議的技術複雜性
TCP協議產生的時延
TCP 鏈接創建握手;
TCP 慢啓動擁塞控制;
數據彙集的 Nagle 算法;
用於捎帶確認的 TCP 延遲確認算法;
TIME_WAIT 時延和端口耗盡。
TCP鏈接創建
TCP鏈接的創建,須要經歷3個報文的交互過程,溝通相關鏈接參數,這個過程稱爲三次握手(three-way handshake)。算法

所以,若是在每次發送數據以前,都從新創建一次TCP鏈接,那麼創建鏈接的耗時將對性能產生較大的影響(特別是在發送少許數據的狀況下)。shell

 

三次握手四次揮手(參考自coolshell)緩存

優化方法服務器

創建長鏈接,屢次數據的發送複用同一條鏈接。網絡

TCP慢啓動
若是在發送方和接收方之間存在多個路由器和速率較慢的鏈路,此時多個發送方一開始便向網絡發送多個報文段,因爲受網絡傳輸和服務端處理能力的影響,一些中間路由器必須緩存分組,並有可能最終耗盡存儲器的空間,於是更多的報文發送將使網絡出現擁塞。tcp

TCP慢啓動(slow start),就是用於防止因特網的忽然過載和擁塞的一種流量控制機制。函數

慢啓動爲發送方的TCP增長了一個窗口:擁塞窗口(congestion window),簡稱cwnd。性能

剛創建鏈接時,擁塞窗口被初始化爲1個報文段。每收到一個ACK,擁塞窗口就增長一個報文段。發送方取擁塞窗口與接收方通告窗口中的最小值做爲發送上限。優化

也就是說,TCP鏈接會隨着時間進行自我「調諧」,起初會限制鏈接的最大速度,若是數據成功傳輸,會隨着時間的推移提升傳輸的速度。操作系統

注:擁塞窗口是發送方使用的流量控制,而通告窗口則是接收方使用的流量控制。(和滑動窗口同樣麼?)

優化方法

採用長鏈接,避免每次創建鏈接後的慢啓動。

Nagle算法
在廣域網上,小分組會增長網絡擁塞出現的可能性。Nagle算法(根據其發明者John Nagle命名)旨在收集這些小分組,以一個分組的方式發出去,以提升網絡效率。

該算法要求一個TCP鏈接上最多隻能有一個未被確認的未完成的小分組,在該分組的確認到達以前不能發送其餘的小分組。

該算法的優越之處在於它是自適應的:確認到達得越快,數據也就發送得越快。

Nagle 算法會引起如下性能問題

當報文沒法填滿一個分組時,須要等待其餘額外數據;
Nagle算法會阻止數據的發送,直到有確認分組抵達爲止,但確認分組自身會被延遲確認算法延遲 100 ~ 200 毫秒。
算法僞代碼

if there is new data to send
  if the window size >= MSS and available data is >= MSS
    send complete MSS segment now
  else
    if there is unconfirmed data still in the pipe
      enqueue data in the buffer until an acknowledge is received
    else
      send data immediately
    end if
  end if
end if
優化方法

對於實時性要求較高的應用場景,能夠經過設置TCP_NODELAY參數來關閉Nagle算法,提升性能。

延時確認算法
一般TCP在接收到數據時並不當即發送ACK;相反,它推遲發送,以便將ACK與須要沿該方向發送的數據一塊兒發送。

有時稱這種現象爲數據捎帶ACK,因爲確認報文一般很小,因此TCP容許在發往相同方向的輸出數據分組中對其進行「捎帶」。

絕大多數實現採用的時延爲200ms,也就是說,TCP將以最大200ms的時延等待是否有數據一塊兒發送。

一般,延遲確認算法會引入至關大的時延。

優化方法

根據所使用操做系統的不一樣,能夠調整或禁止延遲確認算法。(這個方法我沒嘗試過)

TIME_WAIT狀態
TIME_WAIT狀態也稱爲2MSL等待狀態。

當某個 TCP 端點關閉 TCP 鏈接時, 會在內存中維護一個小的控制塊,用來記錄最近所關閉鏈接的 IP 地址和端口號。

這類信息只會維持一小段時間,一般是所估計的報文段最大生存時間的的兩倍(稱爲2MSL,一般爲2分鐘左右),以確保在這段時間內不會建立具備相同地址和端口號的新鏈接。

實際上,這個算法能夠防止在兩分鐘內建立、關閉並從新建立兩個具備相同IP地址和端口號的鏈接。

將 2MSL 的值取爲 2 分鐘是有歷史緣由的。很早之前,路由器的速度還很慢,人們估計,在將一個分組的複製副本丟棄以前,它能夠在因特網隊列中保留最多一分鐘的時間。如今,最大分段生存期要小得多了。

報文段最大生存時間MSL(Maximum Segment Lifetime),是指任何報文段被丟棄前在網絡中的最長生存時間。

RFC 793 [Postel 1981c]指出MSL爲2分鐘。然而,實現中的經常使用值是30秒,1分鐘或2分鐘。

優化方法

打開tcp_tw_reuse,讓程序能夠重用處於TIME_WAIT狀態的端口。若是使用tcp_tw_reuse,必需設置tcp_timestamps=1(默認值)。(這個對於快速重啓某些服務頗有用,特別是服務端程序)
打開tcp_tw_recycle,讓處於TIME_WAIT狀態的套接字更快的回收。

貼一個nagle算法更詳細的講解

Nagle算法用於對緩衝區內的必定數量的消息進行自動鏈接。該處理過程(稱爲Nagling),經過減小必須發送的封包的數量,提升了網絡應用程序系統的效率。

1. Nagle算法的規則

  (可參考tcp_output.c文件裏tcp_nagle_check函數註釋):
1)若是包長度達到MSS(MSS是最大分段大小Maxitum Segment Size ,MTU是最大傳輸單元Maxitum Transmission Unit),則容許發送;
2)若是該包含有FIN,則容許發送;
3)設置了TCP_NODELAY選項,則容許發送;
4)未設置TCP_CORK選項時,若全部發出去的包均被確認,或全部發出去的小數據包(包長度小於MSS)均被確認,則容許發送。
   對於規則4),就是說一個TCP鏈接上最多隻能有一個未被確認的小數據包,在該分組的確認到達以前,不能發送其餘的小數據包。若是某個小分組的確認被延遲了,那麼後續小分組的發送就會相應的延遲。也就是說延遲確認影響的並不僅是被延遲確認的那個數據包,而是後續全部的應答包。

2. Nagle算法的門檻

   實際上Nagle算法並非很複雜,他的主要職責是數據的累積,實際上有三個門檻:

1)緩衝區中的字節數達到了必定量;

2)等待了必定的時間(通常的Nagle算法都是等待200ms);

3)緊急數據發送。

   這三個門檻的任何一個達到都必須發送數據了。通常狀況下,若是數據流量很大,第二個條件是永遠不會起做用的,但當發送小的數據包時,第二個門檻就發揮做用了,防止數據被無限的緩存在緩衝區不是好事情哦。 

3. Nagle算法的選項配置

   TCP_NODELAY和TCP_CORK都是禁用Nagle算法,只不過NODELAY徹底關閉而TCP_CORK徹底由本身決定發送時機。Linux文檔上說二者不要同時設置。

3.1 TCP_NODELAY 選項

設置該選項: setsockopt(s,IPPRO_TCP,TCP_NODELAY,(const char*)&on,sizeof(int));
讀取該選項: getsockopt(s,IPPRO_TCP,TCP_NODELAY,(char*)&on,&optlen);  

  

   默認狀況下, 發送數據採用Nagle 算法. Nagle 算法是指發送方發送的數據不會當即發出,而是先放在緩衝區, 等緩存區滿了再發出. 發送完一批數據後, 會等待接收方對這批數據的迴應,而後再發送下一批數據。 

   Nagle 算法適用於發送方須要發送大批量數據, 而且接收方會及時做出迴應的場合, 這種算法經過減小傳輸數據的次數來提升通訊效率。

   若是發送方持續地發送小批量的數據, 而且接收方不必定會當即發送響應數據, 那麼Nagle算法會使發送方運行很慢。

3.2 TCP_CORK選項

   TCP連接的過程當中,默認開啓Nagle算法,進行小包發送的優化。優化網絡傳輸,兼顧網絡延時和網絡擁塞。這個時候能夠置位TCP_NODELAY關閉Nagle算法,有數據包的話直接發送保證網絡時效性。

   在進行大量數據發送的時候能夠置位TCP_CORK關閉Nagle算法保證網絡利用性。儘量的進行數據的組包,以最大mtu傳輸,若是發送的數據包大小太小則若是在0.6~0.8S範圍內都沒能組裝成一個MTU時,直接發送。若是發送的數據包大小足夠間隔在0.45內時,每次組裝一個MTU進行發送。若是間隔大於0.4~0.8S則,每過來一個數據包就直接發送。

   Nagle組織包的長度是由系統決定的,有時候咱們知道咱們會每一個1分鐘產生1字節,共1000字節。若是徹底由Nagle算法來發送的話,可能仍是會1字節1字節發送[這是一種極端狀況,假設返回ACK時間不是很長]。這個時候首先設置TCP_CORK可以阻塞住TCP[儘可能阻塞住],等咱們write完1000字節以後,取消TCP_CORK,這個時候就可以將1000字節一次發出。

總結:

   TCP_CORK選項與TCP_NODELAY同樣,是控制Nagle化的。      

1)打開TCP_NODELAY選項,則意味着不管數據包是多麼的小,都當即發送(不考慮擁塞窗口)。
2)若是將TCP鏈接比喻爲一個管道,那TCP_CORK選項的做用就像一個塞子。            

   設置TCP_CORK選項,就是用塞子塞住管道,而取消TCP_CORK選項,就是將塞子拔掉。            

   當TCP_CORK選項被設置時,TCP連接不會發送任何的小包,即只有當數據量達到MSS時,纔會被髮送。

   通常當數據傳輸完成時,一般須要取消該選項,以防被塞住,這樣纔可讓不夠MSS大小的包能及時發出去。

相關文章
相關標籤/搜索