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

时间:2010-04-06 07:47:43

标签: apache nginx tornado epoll

TornadowebNginx目前是流行的网络服务器,许多基准测试表明,在某些情况下,它们的性能优于Apache。所以我的问题是:

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

2 个答案:

答案 0 :(得分:64)

如果您正在寻找一个套接字服务器,那么几年前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会将回调附加到后端请求,然后处理另一个活动的客户端请求。实际上,这意味着它返回到事件循环(epollkqueueselect)并要求提供要报告的文件描述符。请注意,主事件循环中的系统调用实际上是一个阻塞操作,因为在其中一个文件描述符可以读取或写入之前无需执行任何操作。

这就是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

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

答案 1 :(得分:5)

是和否。虽然他们都使用epoll,但从技术上讲,它们都使用事件循环来处理请求。您可以在wikipedia找到有关事件循环及其使用方式的更多信息。

查看libevent(由gevent使用,通常比龙卷风更快且更稳定)或libev用于实施。