Linux下nginx反向代理到后端qps只有原来的三分之一

1,131 views
Skip to first unread message

rong zhongjian

unread,
Feb 3, 2015, 3:04:48 AM2/3/15
to open...@googlegroups.com
在Linux下,我用一个nginx服务器反向代理到另一个nginx服务器(服务静态文件),qps降到只有原来的三分之一。
在Freebsd上,同样方式同样配置再测qps,几乎没有降低。

请问会不会是因为epoll的性能比kqueue的差一些呢?

Yichun Zhang (agentzh)

unread,
Feb 3, 2015, 3:36:34 PM2/3/15
to openresty
Hello!

2015-02-03 0:04 GMT-08:00 rong zhongjian:
> 在Linux下,我用一个nginx服务器反向代理到另一个nginx服务器(服务静态文件),qps降到只有原来的三分之一。
> 在Freebsd上,同样方式同样配置再测qps,几乎没有降低。
>

你是在相似的硬件上测试 Linux 和 FreeBSD 的吗?在满载时,nginx 的 CPU 使用率在 Linux 和 FreeBSD
上分别是怎样的?你具体使用什么工具和选项进行压则的?你得到的绝对的吞吐量指标分别是多少?

代理 qps 没有降低的唯一可能是 page cache 100% 命中。

在 nginx 满载时,需要确保 CPU 接近 100%,否则很可能配置上或测试方法上是有问题的。另外,需要检查你的 nginx
是否在刷错误日志,否则你测的其实是刷错误日志文件的性能。

一般地,应尽量使用火焰图工具进行性能分析,以避免低级错误(犯低级错误是很容易的,我自己也是如此):

http://openresty.org/#Profiling

> 请问会不会是因为epoll的性能比kqueue的差一些呢?
>

显然需要更多的细节信息才能得出有意义的结论 :) 对于你的使用方式来说,epoll 和 kqueue 不太可能是瓶颈,而 socket
和文件相关的系统调用很可能是绝对的瓶颈。

Regards,
-agentzh

rong zhongjian

unread,
Feb 3, 2015, 10:54:32 PM2/3/15
to open...@googlegroups.com

Freebsd下还不知道怎么能获得火焰图,我在Linux压测后获得火焰图如下(没有经过代理的):



经过代理的:


压力测试工具用ab: 分别用命令 ab -c 1000 -n 30000 127.0.0.1:80/ 和 ab -c 1000 -n 30000 127.0.0.1:8080/ 测试,其中80端口的访问会被代理到8080端口上。

使用 ab -c 1000 -n 30000 127.0.0.1:8080/ 时,用 ./sample-bt.pl -p "8080端口那个worker的 pid " -t 5 -u 测试。火焰图为以上第一张,调用 writev 为 16% 左右。

使用 ab -c 1000 -n 30000 127.0.0.1:80/ 时,用 ./sample-bt.pl -p "80端口那个worker的 pid " -t 5 -u 测试。 火焰图为以上第二张, 调用 writev 为 34% 左右。

这么分析的话,应该是在代理的情况下,系统调用耗费了大量cpu导致了qps的损失。

Freebsd还没测试。

多谢春哥指点~ 

Yichun Zhang (agentzh)

unread,
Feb 4, 2015, 3:00:43 PM2/4/15
to openresty
Hello!

2015-02-03 19:54 GMT-08:00 rong zhongjian:
>
> Freebsd下还不知道怎么能获得火焰图,我在Linux压测后获得火焰图如下(没有经过代理的):
>

从火焰图上看,如果你开启 nginx 的 upstream {} 的 HTTP 连接池,很可能可以提高近一倍的性能。具体配置可以参考
nginx 对应的官方文档:

http://nginx.org/en/docs/http/ngx_http_upstream_module.html#keepalive

这样你可以直接省掉 ngx_proxy 模块发起的 connect() 和 close() 这几个系统调用。

Regards,
-agentzh

rong zhongjian

unread,
Feb 4, 2015, 9:40:40 PM2/4/15
to open...@googlegroups.com
谢谢春哥,你帮我们解决了一个瓶颈问题。之前我们以为是 http 协议代理带来了性能的损失,一直想要把 http 协议替换成另外一种协议之类的来提高传输速度。
我按照你说的配置了:

    proxy_buffer_size        32k;
    proxy_buffers            4 32k;
    proxy_busy_buffers_size  32k;
    proxy_buffering          off;

    upstream backend {
        server 127.0.0.1:8080;
        keepalive 32;
    }

    server {
        listen       80;
        server_name  localhost;

        location / {
            proxy_pass http://backend;
            proxy_http_version 1.1;
            proxy_set_header Connection "";
        }


现在火焰图就没有了 connect 和 close 两块:

再用 ab 测: ab -c 1000 -n 10000 127.0.0.1:80/ 得到 (这是代理的) 
Document Path:          /
Document Length:        79487 bytes

Concurrency Level:      1000
Time taken for tests:   0.929 seconds
Complete requests:      10000
Failed requests:        832
   (Connect: 0, Receive: 0, Length: 832, Exceptions: 0)
Non-2xx responses:      832
Total transferred:      731194160 bytes
HTML transferred:       728896560 bytes
Requests per second:    10769.37 [#/sec] (mean)
Time per request:       92.856 [ms] (mean)
Time per request:       0.093 [ms] (mean, across all concurrent requests)
Transfer rate:          768994.54 [Kbytes/sec] received


ab -c 1000 -n 10000 127.0.0.1:8080/ 得到 (这是不经代理的)
Document Path:          /
Document Length:        192 bytes

Concurrency Level:      1000
Time taken for tests:   0.539 seconds
Complete requests:      10000
Failed requests:        9015
   (Connect: 0, Receive: 0, Length: 9015, Exceptions: 0)
Non-2xx responses:      985
Total transferred:      719050550 bytes
HTML transferred:       716764425 bytes
Requests per second:    18559.45 [#/sec] (mean)
Time per request:       53.881 [ms] (mean)
Time per request:       0.054 [ms] (mean, across all concurrent requests)
Transfer rate:          1303240.67 [Kbytes/sec] received

Requests per second 损失了不到一半。比之前好了很多~


On Tuesday, February 3, 2015 at 4:04:48 PM UTC+8, rong zhongjian wrote:

Yichun Zhang (agentzh)

unread,
Feb 5, 2015, 2:05:19 AM2/5/15
to openresty
Hello!

2015-02-04 18:40 GMT-08:00 rong zhongjian:
>
> 谢谢春哥,你帮我们解决了一个瓶颈问题。之前我们以为是 http 协议代理带来了性能的损失,一直想要把 http 协议替换成另外一种协议之类的来提高传输速度。

所以说不进行 profile 就着手优化很容易误入歧途 :)

> 我按照你说的配置了:
>
> proxy_buffer_size 32k;
> proxy_buffers 4 32k;
> proxy_busy_buffers_size 32k;
> proxy_buffering off;

不明白为什么你要禁用 proxy_buffering.

> upstream backend {
> server 127.0.0.1:8080;
> keepalive 32;

你究竟配置了多少个 nginx worker 进程?连接池的大小合理不?

>
> 现在火焰图就没有了 connect 和 close 两块:
>

很好。不过建议提供 SVG 格式的火焰图。你这个 PNG 图片里损失了很多信息,不便于我“看图说话”,呵呵。

[...]
> Failed requests: 832
> (Connect: 0, Receive: 0, Length: 832, Exceptions: 0)
> Non-2xx responses: 832

这些失败的请求是怎么回事?后端服务器的 bug?

> ab -c 1000 -n 10000 127.0.0.1:8080/ 得到 (这是不经代理的)

建议进行 ab 压测时尽量启用 -k 选项,毕竟把 TCP 握手的开销算在内并没什么意义。

另外,我注意到你的 ab、nginx 代理和后端服务器都运行在同一台机器上。这种配置很容易犯一个错误,即让 CPU 时间不够用。必须确保
ab、nginx 代理以及后端服务器都有充足的 CPU 时间,而不至于相互争抢 CPU 资源,影响压测结果。最简单的做法是给 nginx
只配置较少数目的 worker 进程。

次外我不清楚你是否恰当配置了 worker_cpu_affinity 指令,这应当会很有帮助(如果正确配置了了的话)。

值得一提的,从火焰图上看,配置 lingering_close off 对于你这个 benchmark 来说或许也可以提升一些性能。

还有,你貌似并没有回答我先前提的那个问题:“在满载时,nginx 的 CPU 使用率在 Linux 和 FreeBSD 上分别是怎样的?”
如果每个 nginx worker 进程的 CPU 压不满 100%,则可以考虑使用 off-CPU 火焰图再行分析:

https://github.com/openresty/nginx-systemtap-toolkit#sample-bt-off-cpu

Regards,
-agentzh

rong zhongjian

unread,
Feb 6, 2015, 10:23:36 PM2/6/15
to open...@googlegroups.com
> 不明白为什么你要禁用 proxy_buffering. 
因为我们主要提供视频流服务,所以觉得如果启用 proxy_buffering 会导致视频返回会很慢。因为在做 buffering 的那个时间段,没有任何数据返回给浏览器。其实我们也不太确定禁用 proxy_buffering 是否真的有好处 : )

> 你究竟配置了多少个 nginx worker 进程?连接池的大小合理不? 
只配置了一个 nginx worker 进程,因为之前没理解 tcp 的 keep-alive 跟 http 的 keep-alive 的区别,所以就在网上随便找了一个配置来抄的。现在我们考虑将 keep-alive 配置大一些,使得 ( keep-alive 的配置值 x nginx worker 进程数 )达到我们想要的并发数。这样就能保障大部分请求经过代理的时候都
不需要再重新打开 tcp 连接。

> 很好。不过建议提供 SVG 格式的火焰图。你这个 PNG 图片里损失了很多信息,不便于我“看图说话”,呵呵。 
好的,我在附件里提供 : ) 

> 这些失败的请求是怎么回事?后端服务器的 bug? 
accept4() failed (24: Too many open files), 后端服务器采用的是一个原生的 nginx 服务器,使用默认配置,是我们 ulimit 没配置好,不是 bug 。

> 次外我不清楚你是否恰当配置了 worker_cpu_affinity 指令,这应当会很有帮助(如果正确配置了了的话)。
没有配置。现在我们连接池大小设置为 500 ,配置 worker_cpu_affinity 为 01 10,worker 数配置为 2 个, 我们的处理器是 4 核的,并且将 ab , nginx 代理,后端部署在三台不同机器上,配置后我再测试,使用 ab -k ,requests per seconds 几乎是一样的 : ) ,看到这样的结果我们很嗨皮 and relief。3Q.

> 值得一提的,从火焰图上看,配置 lingering_close off 对于你这个 benchmark 来说或许也可以提升一些性能。 
在配置了 lingering_close off 之后,似乎没有多大影响。现在代理的 requests per second 已经很接近不经代理的 requests per second 了。

> 还有,你貌似并没有回答我先前提的那个问题:“在满载时,nginx 的 CPU 使用率在 Linux 和 FreeBSD 上分别是怎样的?” 
> 如果每个 nginx worker 进程的 CPU 压不满 100%,则可以考虑使用 off-CPU 火焰图再行分析: 

忘记回答了,不明白满载是什么意思,以及在 FreeBSD 下如何使用这些工具也不太熟悉所以搁下了你的问题。待我研究一番之后再做回复。

On Tuesday, February 3, 2015 at 4:04:48 PM UTC+8, rong zhongjian wrote:
pu-nopool.svg
pu-pool.svg
Reply all
Reply to author
Forward
0 new messages