通訊端與網路程式設計

Nagle 演算法(Nagle's algorithm)

/ NAY-gul /

想像每個信封只寄一張撲克牌。每張小卡都要一個完整的信封、郵票和一趟運送——對幾乎沒有內容的東西來說是巨大的額外開銷。Nagle 演算法是 TCP 避免這種浪費的方式:它不為每一次微小的寫入發射一個網路封包,而是把小塊資料聚在一起,當成一個更飽滿的封包送出,於是網路不會被那些幾乎全是標頭、幾乎沒有酬載的封包淹沒。

這條規則出自 John Nagle,1984 年提出,很簡單:若一條 TCP 連線上已經有尚未被確認的資料在飛行中,就把任何新的小資料先留在緩衝區裡,直到那些在外的資料被確認、或你已累積到一整個區段的量,再送出。一個 40 位元組的 TCP/IP 標頭只載運單一個 1 位元組的按鍵,等於每個內容位元組浪費 40 位元組的開銷,所以在慢速連結上,把許多這類寫入合併成一個封包是大勝。關鍵是:被緩衝的位元組仍會抵達——Nagle 只是稍微延遲它們,並不丟棄——而一次滿尺寸的寫入或一個抵達的確認,會立刻釋放被留住的資料。

為什麼重要:Nagle 演算法和某些互動式的請求-回應應用相處不佳。經典陷阱是它與延遲確認(delayed acknowledgment)的衝突:發送端留住一個小請求等著一個確認,而接收端留住那個確認等著更多資料或計時器,兩邊就僵住數十毫秒。這在多來多往的協定裡會表現成神秘的延遲,標準的解法是設定 TCP_NODELAY 通訊端選項,停用 Nagle,讓小寫入立刻送出去。誠實的提醒:別反射性地停用它——Nagle 仍保護網路不被微小封包洪流淹沒,所以只有當你的應用真的需要小訊息的低延遲、而且自己已經把寫入合理地批次化時,關掉它才是對的。

一個遠端 shell 把每個按鍵當成一個 1 位元組的寫入送出。開著 Nagle 時,幾個快速按鍵可能被併成一個封包,而一個微小寫入可能暫停到前一個位元組被確認為止。設定 TCP_NODELAY 讓每個按鍵立刻送出,用一點效率換來更俐落的打字反應。

Nagle 把微小寫入批次化;TCP_NODELAY 關掉批次以求低延遲。

Nagle 從不遺失資料——它只稍微延遲小寫入。惡名昭彰的卡頓來自它與延遲 ACK 的交互作用。只有在小訊息的低延遲真的要緊時,才用 TCP_NODELAY 停用它。

又称
Nagle algorithmTCP_NODELAYsmall-packet coalescingNagle 演算法