歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
Linux教程網 >> Linux基礎 >> 關於Linux >> nginx sendfile tcp_nopush tcp_nodelay參數解釋

nginx sendfile tcp_nopush tcp_nodelay參數解釋

日期:2017/3/1 16:18:17   编辑:關於Linux
nginx sendfile tcp_nopush tcp_nodelay參數解釋 sendfile 現在流行的web 服務器裡面都提供 sendfile 選項用來提高服務器性能,那到底 sendfile是什麼,怎麼影響性能的呢?sendfile實際上是 Linux2.0+以後的推出的一個系統調用,web服務器可以通過調整自身的配置來決定是否利用 sendfile這個系統調用。先來看一下不用 sendfile的傳統網絡傳輸過程: read(file,tmp_buf, len); write(socket,tmp_buf, len); 硬盤 >> kernel buffer >> user buffer>> kernel socket buffer >>協議棧 一般來說一個網絡應用是通過讀硬盤數據,然後寫數據到socket 來完成網絡傳輸的。上面2行用代碼解釋了這一點,不過上面2行簡單的代碼掩蓋了底層的很多操作。來看看底層是怎麼執行上面2行代碼的: 1、系統調用 read()產生一個上下文切換:從 user mode 切換到 kernel mode,然後 DMA 執行拷貝,把文件數據從硬盤讀到一個 kernel buffer 裡。 2、數據從 kernel buffer拷貝到 user buffer,然後系統調用 read() 返回,這時又產生一個上下文切換:從kernel mode 切換到 user mode。 3、 系統調用write()產生一個上下文切換:從 user mode切換到 kernel mode,然後把步驟2讀到 user buffer的數據拷貝到 kernel buffer(數據第2次拷貝到 kernel buffer),不過這次是個不同的 kernel buffer,這個 buffer和 socket相關聯。 4、系統調用 write()返回,產生一個上下文切換:從 kernel mode 切換到 user mode(第4次切換了),然後 DMA 從 kernel buffer拷貝數據到協議棧(第4次拷貝了)。 上面4個步驟有4次上下文切換,有4次拷貝,我們發現如果能減少切換次數和拷貝次數將會有效提升性能。在kernel2.0+ 版本中,系統調用 sendfile() 就是用來簡化上面步驟提升性能的。sendfile() 不但能減少切換次數而且還能減少拷貝次數。 再來看一下用 sendfile()來進行網絡傳輸的過程: sendfile(socket,file, len); 硬盤 >> kernel buffer (快速拷貝到kernelsocket buffer) >>協議棧 1、 系統調用sendfile()通過 DMA把硬盤數據拷貝到 kernel buffer,然後數據被 kernel直接拷貝到另外一個與 socket相關的 kernel buffer。這裡沒有 user mode和 kernel mode之間的切換,在 kernel中直接完成了從一個 buffer到另一個 buffer的拷貝。 2、DMA 把數據從 kernelbuffer 直接拷貝給協議棧,沒有切換,也不需要數據從 user mode 拷貝到 kernel mode,因為數據就在 kernel 裡。 步驟減少了,切換減少了,拷貝減少了,自然性能就提升了。這就是為http://write.blog.csdn.net/postedit什麼說在Nginx 配置文件裡打開 sendfile on 選項能提高 web server性能的原因。 tcp_nopush 官方: tcp_nopush Syntax: tcp_nopush on | off Default: off Context: http server location Reference: tcp_nopush This directive permits or forbids the use of thesocket options TCP_NOPUSH on FreeBSD or TCP_CORK on Linux. This option is onlyavailable when using sendfile. Setting this option causes nginx to attempt to sendit’s HTTP response headers in one packet on Linux and FreeBSD 4.x You can read more about the TCP_NOPUSH and TCP_CORKsocket options here. linux 下是tcp_cork,上面的意思就是說,當使用sendfile函數時,tcp_nopush才起作用,它和指令tcp_nodelay是互斥的。tcp_cork是linux下tcp/ip傳輸的一個標准了,這個標准的大概的意思是,一般情況下,在tcp交互的過程中,當應用程序接收到數據包後馬上傳送出去,不等待,而tcp_cork選項是數據包不會馬上傳送出去,等到數據包最大時,一次性的傳輸出去,這樣有助於解決網絡堵塞,已經是默認了。 也就是說tcp_nopush = on 會設置調用tcp_cork方法,這個也是默認的,結果就是數據包不會馬上傳送出去,等到數據包最大時,一次性的傳輸出去,這樣有助於解決網絡堵塞。 以快遞投遞舉例說明一下(以下是我的理解,也許是不正確的),當快遞東西時,快遞員收到一個包裹,馬上投遞,這樣保證了即時性,但是會耗費大量的人力物力,在網絡上表現就是會引起網絡堵塞,而當快遞收到一個包裹,把包裹放到集散地,等一定數量後統一投遞,這樣就是tcp_cork的選項干的事情,這樣的話,會最大化的利用網絡資源,雖然有一點點延遲。 對於nginx配置文件中的tcp_nopush,默認就是tcp_nopush,不需要特別指定,這個選項對於www,ftp等大文件很有幫助 tcp_nodelay TCP_NODELAY和TCP_CORK基本上控制了包的“Nagle化”,Nagle化在這裡的含義是采用Nagle算法把較小的包組裝為更大的幀。 John Nagle是Nagle算法的發明人,後者就是用他的名字來命名的,他在1984年首次用這種方法來嘗試解決福特汽車公司的網絡擁塞問題(欲了解詳情請參看IETF RFC 896)。他解決的問題就是所謂的silly window syndrome,中文稱“愚蠢窗口症候群”,具體含義是,因為普遍終端應用程序每產生一次擊鍵操作就會發送一個包,而典型情況下一個包會擁有一個字節的數據載荷以及40個字節長的包頭,於是產生4000%的過載,很輕易地就能令網絡發生擁塞,。 Nagle化後來成了一種標准並且立即在因特網上得以實現。它現在已經成為缺省配置了,但在我們看來,有些場合下把這一選項關掉也是合乎需要的。 現在讓我們假設某個應用程序發出了一個請求,希望發送小塊數據。我們可以選擇立即發送數據或者等待產生更多的數據然後再一次發送兩種策略。如果我們馬上發送數據,那麼交互性的以及客戶/服務器型的應用程序將極大地受益。如果請求立即發出那麼響應時間也會快一些。以上操作可以通過設置套接字的TCP_NODELAY = on 選項來完成,這樣就禁用了Nagle 算法。 另外一種情況則需要我們等到數據量達到最大時才通過網絡一次發送全部數據,這種數據傳輸方式有益於大量數據的通信性能,典型的應用就是文件服務器。應用 Nagle算法在這種情況下就會產生問題。但是,如果你正在發送大量數據,你可以設置TCP_CORK選項禁用Nagle化,其方式正好同 TCP_NODELAY相反(TCP_CORK和 TCP_NODELAY是互相排斥的)。
Copyright © Linux教程網 All Rights Reserved