[FreeBSD kqueque]NGINX引入线程池 性能提升9倍,及为何非瞬间就处理完的业务交由apache2与PHP结合的理论及实践集合。
背景:本文作者主要是讲linux下的nginx处理高效是依赖内核驱动事件处理,但是一个一个的事件处理都是建立在一个消息处理队列循环,而这个一个个的循环的一个(一个事件循环)是得一个一个的处理,而OS系统的瓶颈是磁盘IO,而作者认为linux提供的相关磁盘IO异步操作不如FreeBSD的稳健,没有纳入Linux内核而FreeBSD对这块有优势,再就是nginx从应用层上加入了线程池,避免了这个循环被卡住,这两条的解决,真正提升了应用的效率,总之,Nginx对瞬间就处理完的事件上目前还是不错的,而非瞬间就处理完的操作则目前linux和在上面安装低版本的没有线程池支持的nginx来讲,性能并没有得到最大发挥,而这个新版本的nginx(加入了线程池)如果在FreeBSD上,则性能会最优,最后,作者所说的对于不是一瞬间就处理完的业务理论和实践上的确存在,也就是为何对于一些PHP耗时的处理,大多数是安装在apache上,而不是nginx,这也是有这个原因在里面的,很多人一说nginx牛了,就全用nginx,也是没有认真思考,为何大公司都是nginx和apache2同时使用的根源。
step1:
作者显然是有FreeBSD的立场如下:
要命的是,操作系统可能永远没有这个功能。第一次尝试是 2010 年 linux 中引入 fincore() 系统调用方法,没有成功。接着做了一系列尝试,例如引入新的带有 RWF_NONBLOCK 标记的 preadv2() 系统调用方法。所有的这些补丁前景依旧不明朗。比较悲剧的是,因为 持续的口水战 ,导致这些补丁一直没有被内核接受。
另一个原因是,FreeBSD用户根本不会关心这个。因为 FreeBSD 已经有一个非常高效的异步文件读取接口,完全可以不用线程池。
step2:
发文件这块是nginx的软肋,于是用了aio threads来补充:
Nginx从1.7.11开始为AIO(Asynchronous I/O)引入了线程池支持,能够使用多线程读取和发送文件,不会阻塞工人进程.
http://nginx.org/en/docs/http/ngx_http_core_module.html#aio
location /video/ {
sendfile on;
aio threads;
}
要启用多线程支持,configure时需要显式加入--with-threads选项.
step3:php发文件也交给了nginx,提高了效率减轻了sapi的等待时间,也就减少了nginx事件消息处理队列循环等待时间:
比如对于一些需要经过PHP认证身份的附件,可以通过X-Accel-Redirect告诉Nginx文件的路径,让Nginx利用它的线程池读取文件并发送给浏览器,免得阻塞PHP进程.
<?php
auth(); //用户身份认证
header('Content-type: application/octet-stream');
header('Content-Disposition: attachment; filename="'.basename($filePath).'"');
//PHP通过X-Accel-Redirect告诉Nginx文件的路径,Nginx读取文件并发送给浏览器.
header("X-Accel-Redirect: $filePath");
//对比下面直接通过PHP输出文件
//readfile($filePath); //或者echo file_get_contents($filePath);
step4:有人因老外的这篇文章写了评论,http://xiaorui.cc/2015/06/25/%E5%AF%B9%E4%BA%8Enginx%E7%BA%BF%E7%A8%8B%E6%B1%A0thread-pool%E6%8F%90%E9%AB%98%E6%80%A7%E8%83%BD%E7%9A%84%E7%96%91%E6%83%91/
step4涉及到FreeBSD的kqueque,功能角度来盾kqueue比epoll灵活得多。在写kqueue的时候,内核帮你考虑好了不少东西。但是从效率来看,从我作的压力测试来看epoll比kqueue强。估计是学院派自由派的一个哲学问题:
http://jarit.iteye.com/blog/935283
使用 kqueue 在 FreeBSD 上开发高性能应用服务器:
http://blog.csdn.net/xnn2s/article/details/6047038
____________________________________________________________________________
问题
一般情况下,nginx 是一个事件处理器,一个从内核获取连接事件并告诉系统如何处理的控制器。实际上,在操作系统做读写数据调度的时候,nginx是协同系统工作的,所以nginx能越快响应越好。
nginx处理的事件可以是 超时通知、socket可读写的通知 或 错误通知。nginx 接收到这些消息后,会逐一进行处理。但是所有处理过程都是在一个简单的线程循环中完成的。nginx 从消息队列中取出一条event后执行,例如 读写socket的event。在大多数情况下这很快,Nginx瞬间就处理完了。
如果有耗时长的操作发生怎么办?整个消息处理的循环都必须等待这个耗时长的操作完成,才能继续处理其他消息。所以,我们说的“阻塞操作”其实意思是长时间占用消息循环的操作。操作系统可能被各种各样的原因阻塞,或者等待资源的访问,例如硬盘、互斥锁、数据库同步操作等。
例如,当nginx 想要读取没有缓存在内存中的文件时,则要从磁盘读取。但磁盘是比较缓慢的,即使是其他后续的事件不需要访问磁盘,他们也得等待本次事件的访问磁盘结束。结果就是延迟增加和系统资源没有被充分利用。
有些操作系统提供了异步读写文件接口,在nginx中可以使用这些接口(http://nginx.org/en/docs/http/ngx_http_core_module.html?&&&_ga=1.197764335.1343221768.1436170723#aio)。例如FreeBSD就是一个较好的例子,但不幸的是,linux提供的一系列异步读文件接口有不少缺陷。其中一个问题是:文件访问和缓冲需要队列,但是Nginx已经很好解决了。但是还有一个更严重的问题:使用异步接口需要对文件描述符设置O_DIRECT标识,这意味着任何对这个文件的访问会跳过缓存直接访问磁盘上的文件。在大多数情况下,这不是访问文件的最佳方法。
..............
英文原文:Thread Pools in NGINX Boost Performance 9x!
中文翻译:http://www.infoq.com/cn/articles/thread-pools-boost-performance-9x?utm_campaign=infoq_content&utm_source=infoq&utm_medium=feed&utm_term=global
step1:
作者显然是有FreeBSD的立场如下:
要命的是,操作系统可能永远没有这个功能。第一次尝试是 2010 年 linux 中引入 fincore() 系统调用方法,没有成功。接着做了一系列尝试,例如引入新的带有 RWF_NONBLOCK 标记的 preadv2() 系统调用方法。所有的这些补丁前景依旧不明朗。比较悲剧的是,因为 持续的口水战 ,导致这些补丁一直没有被内核接受。
另一个原因是,FreeBSD用户根本不会关心这个。因为 FreeBSD 已经有一个非常高效的异步文件读取接口,完全可以不用线程池。
step2:
发文件这块是nginx的软肋,于是用了aio threads来补充:
Nginx从1.7.11开始为AIO(Asynchronous I/O)引入了线程池支持,能够使用多线程读取和发送文件,不会阻塞工人进程.
http://nginx.org/en/docs/http/ngx_http_core_module.html#aio
location /video/ {
sendfile on;
aio threads;
}
要启用多线程支持,configure时需要显式加入--with-threads选项.
step3:php发文件也交给了nginx,提高了效率减轻了sapi的等待时间,也就减少了nginx事件消息处理队列循环等待时间:
比如对于一些需要经过PHP认证身份的附件,可以通过X-Accel-Redirect告诉Nginx文件的路径,让Nginx利用它的线程池读取文件并发送给浏览器,免得阻塞PHP进程.
<?php
auth(); //用户身份认证
header('Content-type: application/octet-stream');
header('Content-Disposition: attachment; filename="'.basename($filePath).'"');
//PHP通过X-Accel-Redirect告诉Nginx文件的路径,Nginx读取文件并发送给浏览器.
header("X-Accel-Redirect: $filePath");
//对比下面直接通过PHP输出文件
//readfile($filePath); //或者echo file_get_contents($filePath);
step4:有人因老外的这篇文章写了评论,http://xiaorui.cc/2015/06/25/%E5%AF%B9%E4%BA%8Enginx%E7%BA%BF%E7%A8%8B%E6%B1%A0thread-pool%E6%8F%90%E9%AB%98%E6%80%A7%E8%83%BD%E7%9A%84%E7%96%91%E6%83%91/
step4涉及到FreeBSD的kqueque,功能角度来盾kqueue比epoll灵活得多。在写kqueue的时候,内核帮你考虑好了不少东西。但是从效率来看,从我作的压力测试来看epoll比kqueue强。估计是学院派自由派的一个哲学问题:
http://jarit.iteye.com/blog/935283
使用 kqueue 在 FreeBSD 上开发高性能应用服务器:
http://blog.csdn.net/xnn2s/article/details/6047038
____________________________________________________________________________
问题
一般情况下,nginx 是一个事件处理器,一个从内核获取连接事件并告诉系统如何处理的控制器。实际上,在操作系统做读写数据调度的时候,nginx是协同系统工作的,所以nginx能越快响应越好。
nginx处理的事件可以是 超时通知、socket可读写的通知 或 错误通知。nginx 接收到这些消息后,会逐一进行处理。但是所有处理过程都是在一个简单的线程循环中完成的。nginx 从消息队列中取出一条event后执行,例如 读写socket的event。在大多数情况下这很快,Nginx瞬间就处理完了。
如果有耗时长的操作发生怎么办?整个消息处理的循环都必须等待这个耗时长的操作完成,才能继续处理其他消息。所以,我们说的“阻塞操作”其实意思是长时间占用消息循环的操作。操作系统可能被各种各样的原因阻塞,或者等待资源的访问,例如硬盘、互斥锁、数据库同步操作等。
例如,当nginx 想要读取没有缓存在内存中的文件时,则要从磁盘读取。但磁盘是比较缓慢的,即使是其他后续的事件不需要访问磁盘,他们也得等待本次事件的访问磁盘结束。结果就是延迟增加和系统资源没有被充分利用。
有些操作系统提供了异步读写文件接口,在nginx中可以使用这些接口(http://nginx.org/en/docs/http/ngx_http_core_module.html?&&&_ga=1.197764335.1343221768.1436170723#aio)。例如FreeBSD就是一个较好的例子,但不幸的是,linux提供的一系列异步读文件接口有不少缺陷。其中一个问题是:文件访问和缓冲需要队列,但是Nginx已经很好解决了。但是还有一个更严重的问题:使用异步接口需要对文件描述符设置O_DIRECT标识,这意味着任何对这个文件的访问会跳过缓存直接访问磁盘上的文件。在大多数情况下,这不是访问文件的最佳方法。
..............
英文原文:Thread Pools in NGINX Boost Performance 9x!
中文翻译:http://www.infoq.com/cn/articles/thread-pools-boost-performance-9x?utm_campaign=infoq_content&utm_source=infoq&utm_medium=feed&utm_term=global
作者:jackxiang@向东博客 专注WEB应用 构架之美 --- 构架之美,在于尽态极妍 | 应用之美,在于药到病除
地址:https://jackxiang.com/post/8433/
版权所有。转载时必须以链接形式注明作者和原始出处及本声明!
最后编辑: jackxiang 编辑于2016-1-8 16:58
评论列表