在TCP/IP協議中,不管發送多少數據,老是要在數據前面加上協議頭,同時,對方接收到數據,也須要發送ACK表示確認。爲了儘量的利用網絡帶寬,TCP老是但願儘量的發送足夠大的數據。這裏就涉及到一個名爲Nagle的算法,該算法的目的就是爲了儘量發送大塊數據,避免網絡中充斥着許多小數據塊。node
TCP_NODELAY就是用於啓用或關於Nagle算法。若是要求高實時性,有數據發送時就立刻發送,就將該選項設置爲true關閉Nagle算法;若是要減小發送次數減小網絡交互,就設置爲false等累積必定大小後再發送。默認爲false。nginx
淺談tcp_nodelay的做用web
今天在用nginx做web緩存的時候,發如今http里加入這樣個參數,能有效的提升數據的實時響應性,那就是tcp_nodelay.下面咱們來講說tcp_nodelay的原理:算法
TCP_NODELAY和TCP_CORK基本上控制了包的「Nagle化」,這裏咱們主要講TCP_NODELAY.Nagle化在這裏的含義是採用Nagle算法把較小的包組裝爲更大的幀。JohnNagle是Nagle算法的發明人,後者就是用他的名字來命名的,他在1984年首次用這種方法來嘗試解決福特汽車公司的網絡擁塞問題(欲瞭解詳情請參看IETF RFC 896)。他解決的問題就是所謂的silly window syndrome,中文稱「愚蠢窗口症候羣」,具體含義是,由於廣泛終端應用程序每產生一次擊鍵操做就會發送一個包,而典型狀況下一個包會擁有一個字節的數據載荷以及40個字節長的包頭,因而產生4000%的過載,很輕易地就能令網絡發生擁塞,。Nagle化後來成了一種標準而且當即在因特網上得以實現。它如今已經成爲缺省配置了,但在咱們看來,有些場合下把這一選項關掉也是合乎須要的。 apache
如今讓咱們假設某個應用程序發出了一個請求,但願發送小塊數據,好比sns遊戲中的點擊肯定按鈕。咱們能夠選擇當即發送數據或者等待產生更多的數據而後再一次發送兩種策略。若是咱們立刻發送數據,那麼交互性的以及客戶/服務器型的應用程序將極大地受益。例如,當咱們正在發送一個較短的請求而且等候較大的響應時,相關過載與傳輸的數據總量相比就會比較低,並且,若是請求當即發出那麼響應時間也會快一些。以上操做能夠經過設置套接字的TCP_NODELAY選項來完成,這樣就禁用了Nagle算法,在nginx中設置tcp_nodelay on,注意放在http標籤裏。編程
另一種狀況則須要咱們等到數據量達到最大時才經過網絡一次發送所有數據,這種數據傳輸方式有益於大量數據的通訊性能,典型的應用就是文件服務器。應用Nagle算法在這種狀況下就會產生問題。可是,若是你正在發送大量數據,你能夠設置TCP_CORK選項禁用Nagle化,其方式正好同TCP_NODELAY相反(TCP_CORK 和 TCP_NODELAY 是互相排斥的)。下面就讓咱們仔細分析下其工做原理。 緩存
假設應用程序使用sendfile()函數來轉移大量數據(nginx裏能夠設置sendfile on)。應用協議一般要求發送某些信息來預先解釋數據,這些信息其實就是報頭內容。典型狀況下報頭很小,並且套接字上設置了TCP_NODELAY。有報頭的包將被當即傳輸,在某些狀況下(取決於內部的包計數器),由於這個包成功地被對方收到後須要請求對方確認。這樣,大量數據的傳輸就會被推遲並且產生了沒必要要的網絡流量交換。
可是,若是咱們在套接字上設置了TCP_CORK(能夠比喻爲在管道上插入「塞子」)選項,具備報頭的包就會填補大量的數據,全部的數據都根據大小自動地經過包傳輸出去。當數據傳輸完成時,最好取消TCP_CORK選項設置給鏈接「拔去塞子」以便任一部分的幀都能發送出去。這同「塞住」網絡鏈接同等重要。 服務器
總而言之,若是你確定能一塊兒發送多個數據集合(例如HTTP響應的頭和正文),那麼咱們建議你設置TCP_CORK選項,這樣在這些數據之間不存在延遲。能極大地有益於WWW、FTP以及文件服務器的性能,同時也簡化了你的工做.網絡
最近用了用libsoup庫,用它來寫個HttpServ玩。結果發現性能不行,居然比nginx/apache慢了20倍。拿wireshark一看,發現每一個TCP回覆都要耗時幾百毫秒。這就一會兒讓我想到了Nagle算法(通常的Nagle算法都是延時200ms)。因而下載libsoup的庫,看代碼,果真沒有setsockopt。因而設置了TCP_NODELAY,結果速度一會兒就上去了,與nginx相差無幾(WEB主要是耗IO,在高併發的時候才能顯示出代碼優化的好處)。
而這個Nagle算法,在Windows上的效果尤爲明顯。之前使用GIO中的GSocket,也是如此。
對於初學socket編程的人來講,可能會忘記這裏還有個「陷阱」。Nagle算法適用於小包、高延遲的場合,而對於要求交互速度的b/s或c/s就不合適了。socket在建立的時候,默認都是使用Nagle算法的,這會致使交互速度嚴重降低,因此須要setsockopt函數來設置TCP_NODELAY爲1.
不過取消了Nagle算法,就會致使TCP碎片增多,效率可能會下降。因此,這也是要有所取捨的。併發