'epoll'是Tornadoweb(或Nginx)如此之快的重要原因吗?

Mic*_*ine 23 apache epoll nginx tornado

TornadowebNginx目前是流行的Web服务器,许多基准测试表明它们在某些情况下比Apache具有更好的性能.所以我的问题是:

'epoll'是使它们如此之快的最重要原因吗?如果我想编写一个好的套接字服务器,我还能从中学到什么?

Emi*_*ler 66

如果您正在寻找一个套接字服务器,那么几年前Dan Kegel的C10k文章就是一个很好的起点:

http://www.kegel.com/c10k.html

我还发现Beej的网络编程指南非常方便:

http://beej.us/guide/bgnet/

最后,如果你需要一个很好的参考,那就是W. Richard Stevens等人的UNIX网络编程.人:

http://www.amazon.com/Unix-Network-Programming-Sockets-Networking/dp/0131411551/ref=dp_ob_title_bk

无论如何,要回答你的问题,Apache和Nginx之间的主要区别在于Apache每个客户端使用一个线程阻塞I/O,而Nginx是单线程的非阻塞I/O. Apache的工作池确实减少了启动和去除进程的开销,但它仍然使CPU在为多个客户端提供服务时在多个线程之间切换.另一方面,Nginx处理一个线程中的所有请求.当一个请求需要发出网络请求(例如,发送到后端)时,Nginx会将回调附加到后端请求,然后处理另一个活动的客户端请求.在实践中,这意味着它返回到事件循环(epoll,kqueueselect)并要求有报告内容的文件描述符.请注意,主事件循环中的系统调用实际上是一个阻塞操作,因为在其中一个文件描述符准备好进行读取或写入之前无需执行任何操作.

因此,这是Nginx和Tornado在为许多同时客户端提供服务方面有效的主要原因:只有一个进程(因此节省了RAM)和只有一个线程(因此从上下文切换中节省了CPU).至于epoll,它只是一个更有效的选择版本.如果有N个打开的文件描述符(套接字),它可以让你选择那些准备好在O(1)而不是O(N)时间内读取的文件.事实上,如果用--with-select_module选项编译它,Nginx可以使用select而不是epoll ,我敢打赌它仍然比Apache更有效.我不熟悉Apache内部,但快速grep显示它确实使用select和epoll - 可能是在服务器正在侦听多个端口/接口时,或者它是否同时为单个客户端发出后端请求.

顺便说一句,我开始尝试编写一个基本的套接字服务器,并想弄清楚Nginx如何如此高效.通过阅读Nginx源代码并阅读上面链接的那些指南/书籍后,我发现编写Nginx模块而不是我自己的服务器会更容易.因此诞生了现在半传奇的Emiller的Nginx模块开发指南:

http://www.evanmiller.org/nginx-modules-guide.html

(警告:指南是针对Nginx 0.5-0.6而且API可能已经改变了.)如果你正在做任何关于HTTP的事情,我会说给Nginx一个机会,因为它解决了处理愚蠢客户的所有毛茸茸的细节.例如,我为了好玩而编写的小型套接字服务器对所有客户端都很有用 - 除了Safari,我从来没有弄明白为什么.即使对于其他协议,Nginx可能是正确的方法; 事件很好地从协议中抽象出来,这就是为什么它可以代理HTTP以及IMAP.Nginx代码库组织得非常好,写得很好,有一个例外值得一提.在涉及手动协议解析器时,我不会遵循它的主导; 相反,使用解析器生成器.我在这里写了一些关于在Nginx中使用解析器生成器(Ragel)的东西:

http://www.evanmiller.org/nginx-modules-guide-advanced.html#parsing

所有这些可能都是你想要的更多信息,但希望你能找到一些有用的信息.


Phi*_*ham 5

是的,不是.虽然他们都使用epoll,但从技术上讲,它们都使用事件循环来处理请求.您可以在维基百科中找到有关事件循环及其使用方式的更多信息.

查看libevent(由gevent使用,通常比龙卷风更快更稳定)或libev实现.