Nagle算法&&延時確認

數據流分類
  • 成塊數據
  • 交互數據
 
Rlogin須要遠程系統(服務器)回顯咱們(客戶)鍵入的字符
數據字節和數據字節的回顯都須要對方確認

 

 
rlogin 每次只發送一個字節到服務器,而Telnet 能夠選擇發送一行
數據確認是經過指望數據序號
 
Nagle算法
rlogin發送一個字節,就產生41字節長度的分組:
20字節IP首部,20字節TCP首部,1字節數據
 
防止小分組擁塞
該算法要求一個 TCP鏈接上最多隻能有一個未被確認的未完成的小分組,在該分組的確認到達以前不能發送其餘的小分組。

TCP Nagle算法&&延遲確認機制算法

 

TCP Nagle算法

http://baike.baidu.com/view/2468335.htm編程

百度百科:TCP/IP協議中,不管發送多少數據,老是要在數據前面加上協議頭,同時,對方接收到數據,也須要發送ACK表示確認。爲了儘量的利用網絡帶寬,TCP老是但願儘量的發送足夠大的數據。(一個鏈接會設置MSS參數,所以,TCP/IP但願每次都可以以MSS尺寸的數據塊來發送數據)。Nagle算法就是爲了儘量發送大塊數據,避免網絡中充斥着許多小數據塊。(減小大量小包的發送服務器

Nagle算法的基本定義是任意時刻,最多隻能有一個未被確認的小段。所謂「小段」,指的是小於MSS尺寸的數據塊,所謂「未被確認」,是指一個數據塊發送出去後,沒有收到對方發送的ACK確認該數據已收到。網絡

Nagle算法的規則(可參考tcp_output.c文件裏tcp_nagle_check函數註釋):app

(1)若是包長度達到MSS,則容許發送;less

(2)若是該包含有FIN,則容許發送;tcp

(3)設置了TCP_NODELAY選項,則容許發送;函數

(4)未設置TCP_CORK選項時,若全部發出去的小數據包(包長度小於MSS)均被確認,則容許發送;優化

(5)上述條件都未知足,但發生了超時(通常爲200ms),則當即發送。.net

Nagle算法只容許一個未被ACK的包存在於網絡,它並無論包的大小,所以它事實上就是一個擴展的停-等協議(中止等待ARQ協議),只不過它是基於包停-等的,而不是基於字節停-等的。Nagle算法徹底由TCP協議的ACK機制決定,這會帶來一些問題,好比若是對端ACK回覆很快的話,Nagle事實上不會拼接太多的數據包,雖然避免了網絡擁塞,網絡整體的利用率依然很低。

 

Nagle算法的應用場景

在Nagle算法的Wiki主頁,有這麼一段話:

In general, since Nagle's algorithm is only a defense against careless applications, it will not benefit a carefully written application that takes proper care of buffering; the algorithm has either no effect, or negative effect on the application.

可見編程模型對「減小網絡上小包數量」的影響,言外之意,Nagle算法是個有針對性的優化-針對交互式應用,不是放之四海而皆準的標準,要想有一個比較好的方案,別期望它了,仍是應用程序本身搞定纔是正解!要想Nagle算法真的可以減小網絡上小包數量而又不引入明顯延遲,對TCP數據的產生方式是有要求的,交互式應用是其初始針對的對象,,Nagle算法要求數據必須是「乒乓型」的,也就是說,數據流有明確的邊界且一來一回,相似人機交互的那種,好比telnet這種遠程終端登陸程序,數據是人從鍵盤敲入的,邊界基本上就是擊鍵,一來一回就是輸入回顯和處理回顯。Nagle算法在上面的場景中保證了下一個小包發送以前,全部發出的包已經獲得了確認,再次咱們看到,Nagle算法並無阻止發送小包,它只是阻止了發送大量的小包。

換句話說,所謂的「乒乓型」模式就是「write-read-write-read」模式-人機交互模式,可是對於Wiki中指出的「write-write-read」(不少的request/response模式C/S服務就是這樣的,好比HTTP)-程序交互模式,Nagle算法和延遲ACK(延遲確認機制)拔河的惡果就會被放大。

有一篇很好的文章http://baus.net/on-tcp_cork/《TCP_CORK: More than you ever wanted to know》,文章說,Nagle算法對於數據來自於user input的那種應用是有效的,可是對於數據generated  by applications using stream oriented protocols,Nagle算法純粹引入了延遲,這個觀點我很是贊同,由於對於人而言,TCP登陸俄遠程計算機就是一個處理機,人但願本身的操做立刻展現結果,其模式就是write-read-write-read的,可是對於程序而言,其數據產生邏輯就不像人機交互那麼固定,所以你就不能假定程序依照任何序列進行網絡IO,而Nagle算法是和數據IO的序列相關的。實際上就算接收端沒有啓用延遲ACK,Nagle算法應用於write-write-read序列也是有問題的,做者的意思是,無緣無故地引入了額外的延遲。

難道真的有這麼複雜嗎?做者沒有提出如何靠編程把問題解決,可是Nagle算法的Wiki頁面上提到了」儘可能編寫好的代碼而不要依賴TCP內置的所謂的算法「來優化TCP的行爲。

 

TCP_NODELAY 套接字選項

默認狀況下,發送數據採用Negle 算法。這樣雖然提升了網絡吞吐量,可是實時性卻下降了,在一些交互性很強的應用程序來講是不容許的,

使用TCP_NODELAY選項能夠禁止Negale 算法。 

 

延遲確認機制(TCP delayed acknowledgment)

wiki的解釋https://en.wikipedia.org/wiki/TCP_delayed_acknowledgment

1989 RFC 1122定義,全名Delayed Acknowledgment,簡稱延遲ACK,翻譯爲延遲確認。 

與Nagle算法同樣,延遲ACK的目的也是爲了減小網絡中傳輸大量的小報文該報文數是針對ACK報文的。 

 
一個來自發送端的報文到達接收端,TCP會延遲ACK的發送,但願應用程序會對剛剛收到的數據進行應答,這樣就能夠 用新數據將ACK帶過去
 
注意:
  • 有兩個未確認的包須要確認當即發送ACK

 

當Nagle算法遇到Delayed ACK

在一個有數據傳輸的TCP鏈接中,若是隻有數據發送方啓用Nagle算法,在其連續發送多個小報文時,Nagle算法機制會減小網絡中的小報文數量。這就意味着,一樣傳輸相同大小的應用數據,在網絡上的報文個數卻不一樣。 

舉個例子,發送端須要連續發送5個寫操做(應用程序將數據寫入到緩衝池的動做)的小報文,首先發送第一個,因爲Nagle算法的做用,在未收到第一個報文確認前,發送端在等待寫操做的同時進行讀操做,接收端並未啓用延遲確認(視TCP delay ACK時間爲0),儘管剛收到該報文就發出確認,但因爲網絡延時的緣由,在收集齊另外4個小報文後,發送方纔收到了第一個報文的ACK,則後面的4個報文會一塊兒發送出去(大小未超過MSS),接收端再次ACK。

 

在上述發送5個小報文的過程當中,只用了4個報文就實現了。但若是發送端未啓用Nagle算法,完成整個過程則至少須要8個報文或10個報文才能實現,這裏接收端未啓用延遲確認,以下圖所示。啓用Nagle算法和未啓用Nagle算法的場景中,從完成數據發送的時間來看,未啓用Nagle算法的方式花費的時間會更長一些,以下圖所示。這裏基本看到了Nagle算法的好處了。

 

仍是上述數據傳輸場景,發送端未啓用Nagle算法,但接收端延遲確認默認時間爲200ms,來看看這時的狀況。 RFC 1122規定,Delayed ACK對單個的小報文能夠延長確認的時間,但不容許有兩個連續的小報文不被確認。因此,當發送端連續發送兩個報文後,接收端必須給予確認。這時的數據傳輸狀況以下圖,只有當第5個報文到達後,接收端因爲延遲確認機制,會致使200ms的延時存在。

 

接下來看看,當Nagle算法遇到Delayed ACK時會是什麼狀況。按照常理推斷,兩種深思熟慮的功能設計,應該是1+1>2的效果。具體如何,仍是請事實說話。

先繼續看上面的假設場景,該場景要求發送端向接收端發送5個連續的寫操做數據,但網絡延時較大,同時發送端啓用Nagle算法,接收端Delayed ACK默認爲200ms。 

發送方先發出一個小報文,接收端收到後,因爲延遲確認的機制,等待發送方的下一個報文到達。而發送方因爲Nagle算法機制,在未接收到第一個報文的確認前,不會發送已讀取到的報文。  在這種場景下,暫不考慮應用處理時間,完成整個數據傳輸所需時間爲2RTT+400ms,貌似狀況不是特別糟糕。

 

若是上述其餘條件不變,發送方應用寫操做延時稍微變大,或發送端的應用操做延時稍大,咱們再看看,完成這個操做的延時狀況。 

發送方先發出一個小報文,接收端收到後,因爲延遲確認的機制,等待發送方的下一個報文到達。因爲發送方應用數據寫操做延時較大,在通過RTT+200ms後,讀取到了下一個須要發送的內容,此時接收到了第一個報文的確認,而網絡中未有沒被確認的報文,發送方須要再將第二個小報文發送出去,以此類推,直到最後一個小報文被髮送,且接收到該報文的確認,此時整個數據傳輸過程完成。 

在這種情景下,完成整個數據傳輸所需時間則爲5RTT+5*200ms,明顯增大了很多。若是相同情境下,有成千上萬的小報文發送,則總體使用時間至關可觀了。

 

在實際狀況下,若是發送方程序作了一系列的寫、寫、讀操做的現象,這樣的操做都會觸發Nagle和延遲ACK算法之間的交互做用,應該儘可能避免。

===========================END===========================

相關文章
相關標籤/搜索