如今tornadoweb和nginx事相当流行的web服务器,很多指标都显示在大多数情况下,他们比apache的性能要好很多。既然如此,我就有以下问题:
Epoll模型是导致他们如此快速的根本原因吗?如果我想写一个好的socket服务器,我能够从中学到什么东西呢?
如果你想写一个socket服务器,建议先看看dan kegel几年前写的c10k文章
http://www.kegel.com/c10k.html
我也认为beej的《网络编程指导》也是一本非常方便实用的书籍
http://beej.us/guide/bgnet/
如果,你需要更多的参考,W. Richard stevens写的《unix网络编程也是一本很好的书籍。
总之,要回答那个问题,apache和nginx最大的不同是,apache使用了每个请求一个线程的阻塞I/O模型,nginx使用了单线程的非阻塞I/O模型。Apache的工作池的确是缩减了一些启动内容并销毁了一些进程,但是在处理多请求的时候他仍然让CPU在不同的线程间跳来跳去。Nginx却把所有的请求都放在一个线程里面。当有一个请求想要发送网络请求的时候,nginx向后端求求附加一个回调,然后再一个新的活跃客户端请求上工作。事实上,这意味着他返回到时间循环(epoll,kqueue,或者是select)然后后请求文件描述符,并告知有些事情要报告。注意,系统调用在主要时间循环里面实际上是一个阻塞操作,因为直到文件描述符可以读写之前是无事可做的。
所以,nginx和ternado如此高效同时服务多个客户端请求的主要原因是:只有一个进程(因此也就剩内存)只有一个线程(因为也就减少了CUP在不同的上下文里面交换)。至于epool,他只是select的另一个更加高级的版本。如果有N个打开的文件描述符(sockets),他就会让你从中选择一个按0(1)的时间复杂度而不是0(N)的时间复杂度进行读操作。事实上,如果你在编译的时候使用了—with-select_module参数,你就可以使用select模型,我敢打赌,那笔apche更加的高效。我对apache的内核不是很熟悉,但是一个快速的grep操作可以告诉我们apache的确是使用了select和epoll模型—可能当服务器在监听多端口/接口的时候,或者他确实有多个为一个客户端请求准备了多了后端请求。
偶尔,我照着这个开始编写一个基本的socket服务器,想要搞清楚为什么nginx是如此的高效。在熟读了nginx的源代码然后又看完了上面的链接中的那些书籍之后,我发现,写一个nginx的模块要比写自己的服务器简单的多。因此也就诞生了一个nginx模块开发指南
http://www.evanmiller.org/nginx-modules-guide.html
(注意,这本指导是针对nginx0.5-0.6编写的,现在有些api已经变化了)如果你做一些与http关的事情,我说你的确应该支持一下nginx因为他把那些愚蠢客户端的请求处理的是如此之好。例如,我自己业余写的一个socket服务器在大多数客户端下都很好出了safari浏览器,我到现在都没搞清楚这是怎么回事。即使在其他的协议下,nginx也能适应,nginx的事物处理能力已经完全对协议层透明,这就是为什么他技能代理http,也能代理imap.ngingx的核心代码组织的相当好,写的也相当优秀,唯一的缺陷是几乎没有什么注释。我不会在被nginx牵着鼻子走,当他和一个协议解释器纠缠不清的时候。相反,使用一个解释生成器。我写了一些关于在nginx中使用解释生成器的东西在下面这给对方:
http://www.evanmiller.org/nginx-modules-guide-advanced.html#parsing
这可能比你想要的信息要多,不过我还是希望你能找到一些对你有用的东西
Epoll模型是导致他们如此快速的根本原因吗?如果我想写一个好的socket服务器,我能够从中学到什么东西呢?
如果你想写一个socket服务器,建议先看看dan kegel几年前写的c10k文章
http://www.kegel.com/c10k.html
我也认为beej的《网络编程指导》也是一本非常方便实用的书籍
http://beej.us/guide/bgnet/
如果,你需要更多的参考,W. Richard stevens写的《unix网络编程也是一本很好的书籍。
总之,要回答那个问题,apache和nginx最大的不同是,apache使用了每个请求一个线程的阻塞I/O模型,nginx使用了单线程的非阻塞I/O模型。Apache的工作池的确是缩减了一些启动内容并销毁了一些进程,但是在处理多请求的时候他仍然让CPU在不同的线程间跳来跳去。Nginx却把所有的请求都放在一个线程里面。当有一个请求想要发送网络请求的时候,nginx向后端求求附加一个回调,然后再一个新的活跃客户端请求上工作。事实上,这意味着他返回到时间循环(epoll,kqueue,或者是select)然后后请求文件描述符,并告知有些事情要报告。注意,系统调用在主要时间循环里面实际上是一个阻塞操作,因为直到文件描述符可以读写之前是无事可做的。
所以,nginx和ternado如此高效同时服务多个客户端请求的主要原因是:只有一个进程(因此也就剩内存)只有一个线程(因为也就减少了CUP在不同的上下文里面交换)。至于epool,他只是select的另一个更加高级的版本。如果有N个打开的文件描述符(sockets),他就会让你从中选择一个按0(1)的时间复杂度而不是0(N)的时间复杂度进行读操作。事实上,如果你在编译的时候使用了—with-select_module参数,你就可以使用select模型,我敢打赌,那笔apche更加的高效。我对apache的内核不是很熟悉,但是一个快速的grep操作可以告诉我们apache的确是使用了select和epoll模型—可能当服务器在监听多端口/接口的时候,或者他确实有多个为一个客户端请求准备了多了后端请求。
偶尔,我照着这个开始编写一个基本的socket服务器,想要搞清楚为什么nginx是如此的高效。在熟读了nginx的源代码然后又看完了上面的链接中的那些书籍之后,我发现,写一个nginx的模块要比写自己的服务器简单的多。因此也就诞生了一个nginx模块开发指南
http://www.evanmiller.org/nginx-modules-guide.html
(注意,这本指导是针对nginx0.5-0.6编写的,现在有些api已经变化了)如果你做一些与http关的事情,我说你的确应该支持一下nginx因为他把那些愚蠢客户端的请求处理的是如此之好。例如,我自己业余写的一个socket服务器在大多数客户端下都很好出了safari浏览器,我到现在都没搞清楚这是怎么回事。即使在其他的协议下,nginx也能适应,nginx的事物处理能力已经完全对协议层透明,这就是为什么他技能代理http,也能代理imap.ngingx的核心代码组织的相当好,写的也相当优秀,唯一的缺陷是几乎没有什么注释。我不会在被nginx牵着鼻子走,当他和一个协议解释器纠缠不清的时候。相反,使用一个解释生成器。我写了一些关于在nginx中使用解释生成器的东西在下面这给对方:
http://www.evanmiller.org/nginx-modules-guide-advanced.html#parsing
这可能比你想要的信息要多,不过我还是希望你能找到一些对你有用的东西
作者:jackxiang@向东博客 专注WEB应用 构架之美 --- 构架之美,在于尽态极妍 | 应用之美,在于药到病除
地址:https://jackxiang.com/post/5526/
版权所有。转载时必须以链接形式注明作者和原始出处及本声明!
最后编辑: jackxiang 编辑于2015-7-20 10:30
评论列表