nginx AIO機制與sendfile機制

nginx AIO機制與sendfile機制

從0.8.11版本開始, nginx 開始支持Linux native aio,如何在nginx里配置使用這套機制是本文介紹的重點。在下面的示例配置中,幾個重要相關選項的具體含義如下: aio:

Syntax: aio on | off | sendfile
Default: off

在linux下aio可以設置為on或off(在freebsd還可以設置為sendfile),但需要2.6.22及以后版本的內核,原因在前面文章已經提到過,nginx使用的eventfd有這個 要求 。

directio:

Syntax: directio size | off
Default: off

directio選項可以設置為off或一個大小值,表示當文件大小大于等于這個值時啟用directio。

sendfile:

Syntax: sendfile on | off
Default: off

是否啟用sendfile()。

[root@www nginx-1.2.0]# uname -a
Linux www.t1.com 2.6.38.8 #2 SMP Wed Nov 2 07:52:53 CST 2011 x86_64 x86_64 x86_64 GNU/Linux
[root@www nginx-1.2.0]# cat /etc/issue
CentOS Linux release 6.0 (Final)
Kernel \r on an \m

[root@www nginx-1.2.0]# ./configure --with-file-aio
[root@www nginx-1.2.0]# make
[root@www nginx-1.2.0]# make install
[root@www nginx-1.2.0]# cat /usr/local/nginx/conf/nginx.conf
...
http {
...
server {
...
location / {
aio on;
directio 512k;
sendfile on;
output_buffers 1 128k;
...

要使aio生效需把directio設置為打開狀況,并且如果aio生效,那么將自動不使用sendfile(),這在linux下這是顯然的,要么利用aio讀到緩存區,要么利用sendfile()直接發送出去,兩者不可兼用,而對于freebsd系統下aio和sendfile并用的情況,我并不了解,所以也就不妄加評論;

可以看到directio是針對每個請求的文件大小而決定是否開啟directio的,因此對于上面的整個示例配置,也就會針對每個請求的不同而不同: 如果某處請求的文件大于等于512k,那么將啟用directio,從而aio生效,進而sendfile不生效; 如果某處請求的文件小于512k,那么將禁用directio,從而aio也就不生效,轉而使用sendfile(),即sendfile生效;

這種設計貌似剛好把linux下aio和sendfile兩種機制的優點很好的結合起來使用。對于大文件采用aio,節省cpu,而對于小文件,采用sendfile,減少拷貝;并且對于大文件aio采用directio,避免擠占文件系統緩存,讓文件系統緩存更多的小文件。 從理論上來看,這種配置比較適合系統內存有限、小文件請求比較多、間隔有幾個大文件請求的Web環境;如果內存足夠大,那么應該充分利用文件系統緩存,而directio使得aio無法使用緩存是衡量最終是否需要采用aio的一個需要仔細考慮的因素;網上有人總結說nginx+aio很好,也有人說其很差,其實根據特定的系統環境和應用場景來做配置調節,才能達到性能的最優,nginx提供的 AIO 只是一套工具,沒有固定的好與差之分,就看你能否恰當的用好它,但據nginx官網論壇來看,在linux系統的大部分場景下,目前因使用aio功能附加的限制而帶來的實際效果估計并不太理想:

nginx supports file AIO only in 0.8.11+, but the file AIO is functional
on FreeBSD only. On Linux AIO is supported by nginx only on kerenl
2.6.22+ (although, CentOS 5.5 has backported the required AIO features).
Anyway, on Linux AIO works only if file offset and size are aligned
to a disk block size (usually 512 bytes) and this data can not be cached
in OS VM cache (Linux AIO requires DIRECTIO that bypass OS VM cache).
I believe a cause of so strange AIO implementaion is that AIO in Linux
was developed mainly for databases by Oracle and IBM.

示例:

location /video/ {
sendfile on;
sendfile_max_chunk 256k; 
aio threads;
directio 512k;
output_buffers 1 128k;
}

啟用aio時會自動啟用directio,小于directio定義的大小的文件則采用sendfile進行發送,超過或等于directio定義的大小的文件,將采用aio線程池進行發送,也就是說aio和directio適合大文件下載.因為大文件不適合進入操作系統的buffers/cache,這樣會浪費內存,而且Linux AIO(異步磁盤IO)也要求使用directio的形式.

sendfilemaxchunk可以減少阻塞調用sendfile()所花費的最長時間.因為Nginx不會嘗試一次將整個文件發送出去,而是每次發送大小為256KB的塊數據.

注意,Nginx從1.7.11開始為AIO引入了線程池支持,能夠使用多線程讀取和發送文件,以免工人進程被阻塞.要啟用多線程支持,configure時需要顯式加入–with-threads選項.

sendfile機制:

在apache,nginx,lighttpd等web服務器當中,都有一項sendfile相關的配置,在一些網上的資料都有談到sendfile會提升文件傳輸性能,那sendfile到底是什么呢?它的原理又是如何呢?

在傳統的文件傳輸里面(read/write方式),在實現上其實是比較復雜的,需要經過多次上下文的切換,我們看一下如下兩行代碼: Java代碼 收藏代碼

read(file, tmp_buf, len);      
       write(socket, tmp_buf, len);      


    以上兩行代碼是傳統的read/write方式進行文件到socket的傳輸。

當需要對一個文件進行傳輸的時候,其具體流程細節如下: 1、調用read函數,文件數據被copy到內核緩沖區 2、read函數返回,文件數據從內核緩沖區copy到用戶緩沖區 3、write函數調用,將文件數據從用戶緩沖區copy到內核與socket相關的緩沖區。 4、數據從socket緩沖區copy到相關協議引擎。

以上細節是傳統read/write方式進行網絡文件傳輸的方式,我們可以看到,在這個過程當中,文件數據實際上是經過了四次copy操作:

硬盤—>內核buf—>用戶buf—>socket相關緩沖區—>協議引擎

而sendfile系統調用則提供了一種減少以上多次copy,提升文件傳輸性能的方法。Sendfile系統調用是在2.1版本內核時引進的: Java代碼 收藏代碼

sendfile(socket, file, len);

運行流程如下: 1、sendfile系統調用,文件數據被copy至內核緩沖區 2、再從內核緩沖區copy至內核中socket相關的緩沖區 3、最后再socket相關的緩沖區copy到協議引擎

相較傳統read/write方式,2.1版本內核引進的sendfile已經減少了內核緩沖區到user緩沖區,再由user緩沖區到socket相關緩沖區的文件copy,而在內核版本2.4之后,文件描述符結果被改變,sendfile實現了更簡單的方式,系統調用方式仍然一樣,細節與2.1版本的不同之處在于,當文件數據被復制到內核緩沖區時,不再將所有數據copy到socket相關的緩沖區,而是僅僅將記錄數據位置和長度相關的數據保存到socket相關的緩存,而實際數據將由DMA模塊直接發送到協議引擎,再次減少了一次copy操作。

原創文章,作者:YOUNG,如若轉載,請注明出處:http://www.www58058.com/54790

(19)
YOUNGYOUNG
上一篇 2016-10-26
下一篇 2016-10-27

相關推薦

  • Linux Basic–磁盤分區

    附件: 磁盤管理相關方法.pdf

    Linux干貨 2016-11-21
  • heartbeartv2實現lamp高可用-week17

    3、基于heartbeat v2 crm實現HA LAMP組合;要求,部署wordpress,用于編輯的文章中的任何數據在節點切換后都能正常訪問; 拓撲: 環境: CentOS6.6NFS: 172.16.0.34 輸出mysql數據目錄ntp: 172.16.0.31 時間服務器node1: 172.16.0.32 heartbeart+httpd+php…

    Linux干貨 2017-05-23
  • shell腳本小練習..

    剛剛接觸vim和shell腳本,用幾個小腳本練練手。 1、編寫腳本/root/bin/systeminfo.sh,顯示當前主機系統信息,包括主機名,IPv4地址,操作系統版本,內核版本,CPU型號,內存大小,硬盤大小。 2、編寫腳本/root/bin/backup.sh,可實現每日將/etc/目錄備份到/root/etcYYYY-mm-dd中。 3、編寫腳本…

    2017-04-13
  • Linux操作系統發展史

    內容摘要:Linux操作系統的誕生,Linux 的發展,Linux的特性決定其迅猛發展,Linux的應用領域與發展前景 關鍵詞:Linux的發展  前景   1.  Linux操作系統的誕生 在1981年到1991年十年間,微軟公司的MS-DOS系統一直主宰操作系統的市場,其價格十分昂貴,另一個操作系統UNIX的經銷商為了高利潤…

    Linux干貨 2016-10-14
  • 用NFS搭建wordpress讓兩臺httpd服務同時服務

    一、博客實踐作業: (1) nfs server導出/data/application/web,在目錄中提供wordpress;  (2) nfs client掛載nfs server導出的文件系統至/var/www/html; (3) 客戶端(lamp)部署wordpress,并讓其正常訪問;要確保能正常發文章,上傳圖片; (4) 客戶端2(la…

    2017-06-07
  • N22-第2周作業

    1、Linux上的文件管理類命令都有哪些,其常用的使用方法及其相關示例演示 cd、pwd、ls、alias、cat、more、less、tail、cut、wc、touch、mv、cp、rm pwd:用戶當前所在目錄 [xuc@localhost ~]$ pwd /home/xuc cd:切換目錄  cd  [/PATH…

    Linux干貨 2016-08-22
欧美性久久久久