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.178linux.com/54790

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

相关推荐

  • 22期第四周课程练习

    1、复制/etc/skel目录为/home/tuser1,要求/home/tuser1及其内部文件的属组和其它用户均没有任何访问权限。 [root@localhost tuser1]# cp   -r    /etc/skel/   /ho…

    Linux干货 2016-09-08
  • 关于大型网站技术演进的思考(十五)–网站静态化处理—前后端分离—中(7)

    原文出处: 夏天的森林    上篇里我讲到了一种前后端分离方案,这套方案放到服务端开发人员面前比放在web前端开发人员面前或许得到的掌声会更多,我想很多资深前端工程师看到这样的技术方案可能会有种说不出来的矛盾心情,当我的工作逐渐走向越来越专业化的前端开发后,我就时常被这套前后端分离方案所困惑,最近我终于明白了这个困惑的本源在哪里…

    Linux干货 2015-03-11
  • 第二天作业

    1、echo 查闪烁,下划,颜色    echo -e "\033[31;5;1m*******\033[0m\n \033[32;5;1m*****\033[0m\n  \033[33;5;1m***\033[0m\n   \033[34;5;1m*\033[0m" 2、scr…

    Linux干货 2016-07-26
  • Linux系统启动流程初识

    centos系统启动流程 本篇仅仅讲解centos5和6 centos7并不适用 Linux系统的组成部分:内核+根文件系统 内核功能: 进程管理 内存管理 网络管理 驱动程序 文件系统 安全功能 有以下目录结构的文件系统可以被识别为根文件系统,但根文件系统本身不存在 rootfs:/bin/ /sbin /etc/ /sys/…

    Linux干货 2016-09-11
  • 文本处理工具

    分页查看文件内容 less和more命令介绍 分页查看文件内容:less和more less:一页一页地查看文件或STDIN输出   # less FILE less的快捷键:     Ctrl+u:向上翻半屏     Ctrl+d:向下翻…

    Linux干货 2016-08-07
  • 软连接与硬连接

    硬链接定义 新建的文件是已经存在的文件的一个别名,当原文件删除时,新建的文件仍然可以使用. 硬链接(hard link) ln   UNIX文件系统提供了一种将不同文件链接至同一个文件的机制,称这种机制为链接。它可以使得单个程序对同一文件使用不同的名字。这样的好处是文件系统只存在一个文件的副本。系统简单地通过在目录中建立一个新的登记项来实现这种连接。该登记项…

    Linux干货 2017-07-22