Nagle算法延时确认
- 成塊數(shù)據(jù)
- 交互數(shù)據(jù)
?
? rlogin 每次只發(fā)送一個(gè)字節(jié)到服務(wù)器,而Telnet 可以選擇發(fā)送一行 數(shù)據(jù)確認(rèn)是通過(guò)期望數(shù)據(jù)序號(hào) Nagle算法 rlogin發(fā)送一個(gè)字節(jié),就產(chǎn)生41字節(jié)長(zhǎng)度的分組: 20字節(jié)IP首部,20字節(jié)TCP首部,1字節(jié)數(shù)據(jù) 防止小分組擁塞 該算法要求一個(gè) TCP連接上最多只能有一個(gè)未被確認(rèn)的未完成的小分組,在該分組的確認(rèn)到達(dá)之前不能發(fā)送其他的小分組。TCP Nagle算法&&延遲確認(rèn)機(jī)制
?
TCP Nagle算法
http://baike.baidu.com/view/2468335.htm
百度百科:TCP/IP協(xié)議中,無(wú)論發(fā)送多少數(shù)據(jù),總是要在數(shù)據(jù)前面加上協(xié)議頭,同時(shí),對(duì)方接收到數(shù)據(jù),也需要發(fā)送ACK表示確認(rèn)。為了盡可能的利用網(wǎng)絡(luò)帶寬,TCP總是希望盡可能的發(fā)送足夠大的數(shù)據(jù)。(一個(gè)連接會(huì)設(shè)置MSS參數(shù),因此,TCP/IP希望每次都能夠以MSS尺寸的數(shù)據(jù)塊來(lái)發(fā)送數(shù)據(jù))。Nagle算法就是為了盡可能發(fā)送大塊數(shù)據(jù),避免網(wǎng)絡(luò)中充斥著許多小數(shù)據(jù)塊。(減少大量小包的發(fā)送)
Nagle算法的基本定義是任意時(shí)刻,最多只能有一個(gè)未被確認(rèn)的小段。所謂“小段”,指的是小于MSS尺寸的數(shù)據(jù)塊,所謂“未被確認(rèn)”,是指一個(gè)數(shù)據(jù)塊發(fā)送出去后,沒(méi)有收到對(duì)方發(fā)送的ACK確認(rèn)該數(shù)據(jù)已收到。
Nagle算法的規(guī)則(可參考tcp_output.c文件里tcp_nagle_check函數(shù)注釋):
(1)如果包長(zhǎng)度達(dá)到MSS,則允許發(fā)送;
(2)如果該包含有FIN,則允許發(fā)送;
(3)設(shè)置了TCP_NODELAY選項(xiàng),則允許發(fā)送;
(4)未設(shè)置TCP_CORK選項(xiàng)時(shí),若所有發(fā)出去的小數(shù)據(jù)包(包長(zhǎng)度小于MSS)均被確認(rèn),則允許發(fā)送;
(5)上述條件都未滿足,但發(fā)生了超時(shí)(一般為200ms),則立即發(fā)送。
Nagle算法只允許一個(gè)未被ACK的包存在于網(wǎng)絡(luò),它并不管包的大小,因此它事實(shí)上就是一個(gè)擴(kuò)展的停-等協(xié)議(停止等待ARQ協(xié)議),只不過(guò)它是基于包停-等的,而不是基于字節(jié)停-等的。Nagle算法完全由TCP協(xié)議的ACK機(jī)制決定,這會(huì)帶來(lái)一些問(wèn)題,比如如果對(duì)端ACK回復(fù)很快的話,Nagle事實(shí)上不會(huì)拼接太多的數(shù)據(jù)包,雖然避免了網(wǎng)絡(luò)擁塞,網(wǎng)絡(luò)總體的利用率依然很低。
?
Nagle算法的應(yīng)用場(chǎng)景
在Nagle算法的Wiki主頁(yè),有這么一段話:
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.
可見(jiàn)編程模型對(duì)“減少網(wǎng)絡(luò)上小包數(shù)量”的影響,言外之意,Nagle算法是個(gè)有針對(duì)性的優(yōu)化-針對(duì)交互式應(yīng)用,不是放之四海而皆準(zhǔn)的標(biāo)準(zhǔn),要想有一個(gè)比較好的方案,別指望它了,還是應(yīng)用程序自己搞定才是正解!要想Nagle算法真的能夠減少網(wǎng)絡(luò)上小包數(shù)量而又不引入明顯延遲,對(duì)TCP數(shù)據(jù)的產(chǎn)生方式是有要求的,交互式應(yīng)用是其初始針對(duì)的對(duì)象,,Nagle算法要求數(shù)據(jù)必須是“乒乓型”的,也就是說(shuō),數(shù)據(jù)流有明確的邊界且一來(lái)一回,類似人機(jī)交互的那種,比如telnet這種遠(yuǎn)程終端登錄程序,數(shù)據(jù)是人從鍵盤敲入的,邊界基本上就是擊鍵,一來(lái)一回就是輸入回顯和處理回顯。Nagle算法在上面的場(chǎng)景中保證了下一個(gè)小包發(fā)送之前,所有發(fā)出的包已經(jīng)得到了確認(rèn),再次我們看到,Nagle算法并沒(méi)有阻止發(fā)送小包,它只是阻止了發(fā)送大量的小包。
換句話說(shuō),所謂的“乒乓型”模式就是“write-read-write-read”模式-人機(jī)交互模式,但是對(duì)于Wiki中指出的“write-write-read”(很多的request/response模式C/S服務(wù)就是這樣的,比如HTTP)-程序交互模式,Nagle算法和延遲ACK(延遲確認(rèn)機(jī)制)拔河的惡果就會(huì)被放大。
有一篇很好的文章http://baus.net/on-tcp_cork/《TCP_CORK: More than you ever wanted to know》,文章說(shuō),Nagle算法對(duì)于數(shù)據(jù)來(lái)自于user input的那種應(yīng)用是有效的,但是對(duì)于數(shù)據(jù)generated ?by applications using stream oriented protocols,Nagle算法純粹引入了延遲,這個(gè)觀點(diǎn)我非常贊同,因?yàn)閷?duì)于人而言,TCP登錄俄遠(yuǎn)程計(jì)算機(jī)就是一個(gè)處理機(jī),人希望自己的操作馬上展示結(jié)果,其模式就是write-read-write-read的,但是對(duì)于程序而言,其數(shù)據(jù)產(chǎn)生邏輯就不像人機(jī)交互那么固定,因此你就不能假定程序依照任何序列進(jìn)行網(wǎng)絡(luò)IO,而Nagle算法是和數(shù)據(jù)IO的序列相關(guān)的。實(shí)際上就算接收端沒(méi)有啟用延遲ACK,Nagle算法應(yīng)用于write-write-read序列也是有問(wèn)題的,作者的意思是,平白無(wú)故地引入了額外的延遲。
難道真的有這么復(fù)雜嗎?作者沒(méi)有提出如何靠編程把問(wèn)題解決,但是Nagle算法的Wiki頁(yè)面上提到了”盡量編寫好的代碼而不要依賴TCP內(nèi)置的所謂的算法“來(lái)優(yōu)化TCP的行為。
?
TCP_NODELAY 套接字選項(xiàng)
默認(rèn)情況下,發(fā)送數(shù)據(jù)采用Negle 算法。這樣雖然提高了網(wǎng)絡(luò)吞吐量,但是實(shí)時(shí)性卻降低了,在一些交互性很強(qiáng)的應(yīng)用程序來(lái)說(shuō)是不允許的,
使用TCP_NODELAY選項(xiàng)可以禁止Negale 算法。?
?
延遲確認(rèn)機(jī)制(TCP delayed acknowledgment)
wiki的解釋https://en.wikipedia.org/wiki/TCP_delayed_acknowledgment
1989 RFC 1122定義,全名Delayed Acknowledgment,簡(jiǎn)稱延遲ACK,翻譯為延遲確認(rèn)。?
與Nagle算法一樣,延遲ACK的目的也是為了減少網(wǎng)絡(luò)中傳輸大量的小報(bào)文數(shù),但該報(bào)文數(shù)是針對(duì)ACK報(bào)文的。?
一個(gè)來(lái)自發(fā)送端的報(bào)文到達(dá)接收端,TCP會(huì)延遲ACK的發(fā)送,希望應(yīng)用程序會(huì)對(duì)剛剛收到的數(shù)據(jù)進(jìn)行應(yīng)答,這樣就可以用新數(shù)據(jù)將ACK捎帶過(guò)去。 注意:- 當(dāng)有兩個(gè)未確認(rèn)的包需要確認(rèn)時(shí),立即發(fā)送ACK
?
當(dāng)Nagle算法遇到Delayed ACK
在一個(gè)有數(shù)據(jù)傳輸?shù)腡CP連接中,如果只有數(shù)據(jù)發(fā)送方啟用Nagle算法,在其連續(xù)發(fā)送多個(gè)小報(bào)文時(shí),Nagle算法機(jī)制會(huì)減少網(wǎng)絡(luò)中的小報(bào)文數(shù)量。這就意味著,同樣傳輸相同大小的應(yīng)用數(shù)據(jù),在網(wǎng)絡(luò)上的報(bào)文個(gè)數(shù)卻不同。?
舉個(gè)例子,發(fā)送端需要連續(xù)發(fā)送5個(gè)寫操作(應(yīng)用程序?qū)?shù)據(jù)寫入到緩沖池的動(dòng)作)的小報(bào)文,首先發(fā)送第一個(gè),由于Nagle算法的作用,在未收到第一個(gè)報(bào)文確認(rèn)前,發(fā)送端在等待寫操作的同時(shí)進(jìn)行讀操作,接收端并未啟用延遲確認(rèn)(視TCP delay ACK時(shí)間為0),盡管剛收到該報(bào)文就發(fā)出確認(rèn),但由于網(wǎng)絡(luò)延時(shí)的原因,在收集齊另外4個(gè)小報(bào)文后,發(fā)送方才收到了第一個(gè)報(bào)文的ACK,則后面的4個(gè)報(bào)文會(huì)一起發(fā)送出去(大小未超過(guò)MSS),接收端再次ACK。
?
在上述發(fā)送5個(gè)小報(bào)文的過(guò)程中,只用了4個(gè)報(bào)文就實(shí)現(xiàn)了。但如果發(fā)送端未啟用Nagle算法,完成整個(gè)過(guò)程則至少需要8個(gè)報(bào)文或10個(gè)報(bào)文才能實(shí)現(xiàn),這里接收端未啟用延遲確認(rèn),如下圖所示。啟用Nagle算法和未啟用Nagle算法的場(chǎng)景中,從完成數(shù)據(jù)發(fā)送的時(shí)間來(lái)看,未啟用Nagle算法的方式花費(fèi)的時(shí)間會(huì)更長(zhǎng)一些,如下圖所示。這里基本看到了Nagle算法的好處了。
?
還是上述數(shù)據(jù)傳輸場(chǎng)景,發(fā)送端未啟用Nagle算法,但接收端延遲確認(rèn)默認(rèn)時(shí)間為200ms,來(lái)看看這時(shí)的情況。?RFC 1122規(guī)定,Delayed ACK對(duì)單個(gè)的小報(bào)文可以延長(zhǎng)確認(rèn)的時(shí)間,但不允許有兩個(gè)連續(xù)的小報(bào)文不被確認(rèn)。所以,當(dāng)發(fā)送端連續(xù)發(fā)送兩個(gè)報(bào)文后,接收端必須給予確認(rèn)。這時(shí)的數(shù)據(jù)傳輸情況如下圖,只有當(dāng)?shù)?個(gè)報(bào)文到達(dá)后,接收端由于延遲確認(rèn)機(jī)制,會(huì)導(dǎo)致200ms的延時(shí)存在。
?
接下來(lái)看看,當(dāng)Nagle算法遇到Delayed ACK時(shí)會(huì)是什么情況。按照常理推斷,兩種深思熟慮的功能設(shè)計(jì),應(yīng)該是1+1>2的效果。具體如何,還是請(qǐng)事實(shí)說(shuō)話。
先繼續(xù)看上面的假設(shè)場(chǎng)景,該場(chǎng)景要求發(fā)送端向接收端發(fā)送5個(gè)連續(xù)的寫操作數(shù)據(jù),但網(wǎng)絡(luò)延時(shí)較大,同時(shí)發(fā)送端啟用Nagle算法,接收端Delayed ACK默認(rèn)為200ms。?
發(fā)送方先發(fā)出一個(gè)小報(bào)文,接收端收到后,由于延遲確認(rèn)的機(jī)制,等待發(fā)送方的下一個(gè)報(bào)文到達(dá)。而發(fā)送方由于Nagle算法機(jī)制,在未接收到第一個(gè)報(bào)文的確認(rèn)前,不會(huì)發(fā)送已讀取到的報(bào)文。 ?在這種場(chǎng)景下,暫不考慮應(yīng)用處理時(shí)間,完成整個(gè)數(shù)據(jù)傳輸所需時(shí)間為2RTT+400ms,貌似情況不是特別糟糕。
?
如果上述其他條件不變,發(fā)送方應(yīng)用寫操作延時(shí)稍微變大,或發(fā)送端的應(yīng)用操作延時(shí)稍大,我們?cè)倏纯?#xff0c;完成這個(gè)操作的延時(shí)情況。?
發(fā)送方先發(fā)出一個(gè)小報(bào)文,接收端收到后,由于延遲確認(rèn)的機(jī)制,等待發(fā)送方的下一個(gè)報(bào)文到達(dá)。由于發(fā)送方應(yīng)用數(shù)據(jù)寫操作延時(shí)較大,在經(jīng)過(guò)RTT+200ms后,讀取到了下一個(gè)需要發(fā)送的內(nèi)容,此時(shí)接收到了第一個(gè)報(bào)文的確認(rèn),而網(wǎng)絡(luò)中未有沒(méi)被確認(rèn)的報(bào)文,發(fā)送方需要再將第二個(gè)小報(bào)文發(fā)送出去,以此類推,直到最后一個(gè)小報(bào)文被發(fā)送,且接收到該報(bào)文的確認(rèn),此時(shí)整個(gè)數(shù)據(jù)傳輸過(guò)程完成。?
在這種情景下,完成整個(gè)數(shù)據(jù)傳輸所需時(shí)間則為5RTT+5*200ms,明顯增大了不少。如果相同情境下,有成千上萬(wàn)的小報(bào)文發(fā)送,則整體使用時(shí)間相當(dāng)可觀了。
?
在實(shí)際情況下,如果發(fā)送方程序做了一系列的寫、寫、讀操作的現(xiàn)象,這樣的操作都會(huì)觸發(fā)Nagle和延遲ACK算法之間的交互作用,應(yīng)該盡量避免。
===========================END===========================
轉(zhuǎn)載于:https://www.cnblogs.com/Aiapple/p/7289389.html
總結(jié)
以上是生活随笔為你收集整理的Nagle算法延时确认的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 3.3、自定义错误页面
- 下一篇: 【计算机网络】湖科大微课堂 笔记目录(完