3
回答
apache 和 nginx 压力测试结果
模拟1000个用户,设置10秒

apache

Transactions:                3725 hits
Availability:              100.00 %
Elapsed time:                9.26 secs
Data transferred:           32.39 MB
Response time:                1.21 secs
Transaction rate:          402.27 trans/sec
Throughput:                3.50 MB/sec
Concurrency:              488.71
Successful transactions:        3725
Failed transactions:               0
Longest transaction:            7.71
Shortest transaction:            0.00

nginx

Transactions:                10152 hits
Availability:              100.00 %
Elapsed time:                9.54 secs
Data transferred:           545.65 MB
Response time:                0.31secs
Transaction rate:         1064.15trans/sec
Throughput:               57.20 MB/sec
Concurrency:             329.25
Successful transactions:        10152
Failed transactions:               0
Longest transaction:            8.04

Shortest transaction:            0.00

以上测试在内网测试,debian安装apache ,centos安装nginx ,测试页面是一个php

phpinfo();。内容只是打印详细信息。

举报
kdybdsx
发帖于4年前 3回/974阅
共有3个答案 最后回答: 4年前
引自: http://tengine.taobao.org/book/chapter_02.html

为什么nginx可以采用异步非阻塞的方式来处理呢,或者异步非阻塞到底是怎么回事呢?我们先回到原点,看看一个请求的完整过程。首先,请求过来,要建立连接,然后再接收数据,接收数据后,再发送数据。具体到系统底层,就是读写事件,而当读写事件没有准备好时,必然不可操作,如果不用非阻塞的方式来调用,那就得阻塞调用了,事件没有准备好,那就只能等了,等事件准备好了,你再继续吧。阻塞调用会进入内核等待,cpu就会让出去给别人用了,对单线程的worker来说,显然不合适,当网络事件越多时,大家都在等待呢,cpu空闲下来没人用,cpu利用率自然上不去了,更别谈高并发了。好吧,你说加进程数,这跟apache的线程模型有什么区别,注意,别增加无谓的上下文切换 ?所以,在nginx里面,最忌讳阻塞的系统调用了。不要阻塞,那就非阻塞喽。非阻塞就是,事件没有准备好,马上返回EAGAIN,告诉你,事件还没准备好呢,你慌什么,过会再来吧。好吧,你过一会,再来检查一下事件,直到事件准备好了为止,在这期间,你就可以先去做其它事情,然后再来看看事件好了没。虽然不阻塞了,但你得不时地过来检查一下事件的状态,你可以做更多的事情了,但带来的开销也是不小的。所以,才会有了异步非阻塞的事件处理机制,具体到系统调用就是像select/poll/epoll/kqueue这样的系统调用。它们提供了一种机制,让你可以同时监控多个事件,调用他们是阻塞的,但可以设置超时时间,在超时时间之内,如果有事件准备好了,就返回。这种机制正好解决了我们上面的两个问题,拿epoll为例(在后面的例子中,我们多以epoll为例子,以代表这一类函数),当事件没准备好时,放到epoll里面,事件准备好了,我们就去读写,当读写返回EAGAIN时,我们将它再次加入到epoll里面。这样,只要有事件准备好了,我们就去处理它,只有当所有事件都没准备好时,才在epoll里面等着。这样,我们就可以并发处理大量的并发了,当然,这里的并发请求,是指未处理完的请求,线程只有一个,所以同时能处理的请求当然只有一个了,只是在请求间进行不断地切换而已,切换也是因为异步事件未准备好,而主动让出的。这里的切换是没有任何代价,你可以理解为循环处理多个准备好的事件,事实上就是这样的。与多线程相比,这种事件处理方式是有很大的优势的,不需要创建线程,每个请求占用的内存也很少,没有上下文切换,事件处理非常的轻量级。并发数再多也不会导致无谓的资源浪费(上下文切换)。更多的并发数,只是会占用更多的内存而已。 我之前有对连接数进行过测试, 在24G内存的机器上,处理的并发请求数达到过200万。现在的网络服务器基本都采用这种方式,这也是nginx性能高效的主要原因。


我的理解是,在等待IO设备(存在阻塞)完成工作时,Nginx的单线程worker进程中用epoll轮询(异步非阻塞)能够容纳大量的空闲连接。如果一个进程或者一个线程对应一个请求,系统在大量线程间切换会消耗大量CPU资源。而Nginx绑定worker进程到CPU核心,能够充分利用CPU,减少上下文切换带来的系统开销。
顶部