Nagle算法



Nagle算法:

當有一個TCP數據段不足MSS,比如要發送700Byte數據,MSS爲1460Byte的情況。nagle算法會延遲這個數據段的發送,等待,直到有足夠的數據填充成一個完整數據段。也許有人會問,這有什麼影響呢?沒有太大的影響,總體上來說,這種措施能節省不必要的資源消耗。但是要發送的總體數據很小時,這種措施就是拖後腿了。比如,用戶請求一個網頁,大約十幾KB的數據,TCP先發送了八九個數據包,剩下幾百字節一直不發送,要等到另一個RTT才發送,這時候前面發送數據的ACK已經返回了。這樣的用戶體驗是很不好的。 所以,現在很多服務器都選擇主動關閉nagle算法,因爲帶寬夠大,資源消耗不是問題,速度反而是個大問題。

Nagle算法的規則:
(1)如果包長度達到MSS,則允許發送;
(2)如果該包含有FIN,則允許發送;
(3)設置了TCP_NODELAY選項,則允許發送;
(4)未設置TCP_CORK選項時,若所有發出去的小數據包(包長度小於MSS)均被確認,則允許發送;
(5)上述條件都未滿足,但發生了超時(一般爲200ms),則立即發送。

Nagle算法只允許一個未被ACK的包存在於網絡,它並不管包的大小,因此它事實上就是一個擴展的停-等協議,只不過它是基於包停-等的,而不是基於字節停-等的。Nagle算法完全由TCP協議的ACK機制決定,這會帶來一些問題,比如如果對端ACK回覆很快的話,Nagle事實上不會拼接太多的數據包,雖然避免了網絡擁塞,網絡總體的利用率依然很低。
Nagle算法是silly window syndrome(SWS)預防算法的一個半集。SWS算法預防發送少量的數據,Nagle算法是其在發送方的實現,而接收方要做的是不要通告緩衝空間的很小增長,不通知小窗口,除非緩衝區空間有顯著的增長。這裏顯著的增長定義爲完全大小的段(MSS)或增長到大於最大窗口的一半。
注意:BSD的實現是允許在空閒鏈接上發送大的寫操作剩下的最後的小段,也就是說,當超過1個MSS數據發送時,內核先依次發送完n個MSS的數據包,然後再發送尾部的小數據包,其間不再延時等待。(假設網絡不阻塞且接收窗口足夠大)
舉個例子,比如之前的blog中的實驗,一開始client端調用socket的write操作將一個int型數據(稱爲A塊)寫入到網絡中,由於此時連接是空閒的(也就是說還沒有未被確認的小段),因此這個int型數據會被馬上發送到server端,接着,client端又調用write操作寫入‘\r\n’(簡稱B塊),這個時候,A塊的ACK沒有返回,所以可以認爲已經存在了一個未被確認的小段,所以B塊沒有立即被髮送,一直等待A塊的ACK收到(大概40ms之後),B塊才被髮送。整個過程如圖所示:
這裏還隱藏了一個問題,就是A塊數據的ACK爲什麼40ms之後才收到?這是因爲TCP/IP中不僅僅有nagle算法,還有一個TCP確認延遲機制 。當Server端收到數據之後,它並不會馬上向client端發送ACK,而是會將ACK的發送延遲一段時間(假設爲t),它希望在t時間內server端會向client端發送應答數據,這樣ACK就能夠和應答數據一起發送,就像是應答數據捎帶着ACK過去。在我之前的時間中,t大概就是40ms。這就解釋了爲什麼'\r\n'(B塊)總是在A塊之後40ms才發出。
當然,TCP確認延遲40ms並不是一直不變的,TCP連接的延遲確認時間一般初始化爲最小值40ms,隨後根據連接的重傳超時時間(RTO)、上次收到數據包與本次接收數據包的時間間隔等參數進行不斷調整。另外可以通過設置TCP_QUICKACK選項來取消確認延遲。




發佈了14 篇原創文章 · 獲贊 23 · 訪問量 10萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章