背景
使用中开发了一个flask项目,为了提升并发能力,使用tornado托管,然后使用nginx来做反向代理并直接处理静态文件的分发。
测试过程
服务器环境是 Windows Server 2008 R2, 8C, 16G。
编码环境 python3
压测使用Tsung
直接访问项目首页html,存在加载多个js,css等文件。
1 、直接对flask压测,并发用户500
效果如下:
Name | highest 10sec mean | lowest 10sec mean | Highest Rate | Mean Rate | Mean | Count |
---|---|---|---|---|---|---|
connect | 32.96 msec | 31.69 msec | 27 / sec | 2.55 / sec | 31.96 msec | 1700 |
page | 9mn 12sec | 3.52 sec | 15.9 / sec | 1.84 / sec | 49.87 sec | 1201 |
request | 9mn 12sec | 3.52 sec | 15.9 / sec | 1.84 / sec | 49.87 sec | 1201 |
session | 9mn 42sec | 9mn 9sec | 0.333333333333333 / sec | 0.22 / sec | 9mn 9sec | 1 |
Code | Highest Rate | Mean Rate | Total number |
---|---|---|---|
200 | 16 / sec | 1.39 / sec | 935 |
500 | 5.9 / sec | 0.39 / sec | 225 |
可以看出效果是比较差的,其实还没压测完就报了个内存错误,程序挂了。
2、使用tornado部署,并发用户500
部署代码如下:
#coding=utf-8
#!/usr/bin/python
from tornado.wsgi import WSGIContainer
from tornado.httpserver import HTTPServer
from tornado.ioloop import IOLoop
from manage import app
http_server = HTTPServer(WSGIContainer(app))
http_server.listen(5000) #flask默认的端口
IOLoop.instance().start()
再压测一次,还是500的并发,效果如下:
Name | highest 10sec mean | lowest 10sec mean | Highest Rate | Mean Rate | Mean | Count |
---|---|---|---|---|---|---|
connect | 0.10 sec | 32.68 msec | 47.1 / sec | 39.27 / sec | 37.35 msec | 23522 |
page | 1.69 sec | 1.28 sec | 83.8 / sec | 78.40 / sec | 1.47 sec | 46806 |
request | 1.69 sec | 1.28 sec | 83.8 / sec | 78.40 / sec | 1.47 sec | 46806 |
session | 3mn 5sec | 6.43 sec | 10.9 / sec | 0.64 / sec | 13.00 sec | 386 |
Code | Highest Rate | Mean Rate | Total number |
---|---|---|---|
200 | 42.4 / sec | 39.21 / sec | 23515 |
效果妥妥的,连500的错误都没了。
3、使用tornado部署,1000并发
效果如下:
Name | highest 10sec mean | lowest 10sec mean | Highest Rate | Mean Rate | Mean | Count |
---|---|---|---|---|---|---|
connect | 0.84 sec | 32.01 msec | 51.7 / sec | 45.14 / sec | 0.24 sec | 27105 |
page | 16.66 sec | 2.39 sec | 50.5 / sec | 44.43 / sec | 10.45 sec | 26616 |
request | 16.66 sec | 2.39 sec | 50.5 / sec | 44.43 / sec | 10.45 sec | 26616 |
Code | Highest Rate | Mean Rate | Total number |
---|---|---|---|
200 | 42.9 / sec | 38.79 / sec | 23330 |
效果和500也差不多,并发稳定在40/sec。
4、nginx反向代理处理静态文件(首页的JS,CSS等),tornado部署,并发用户1000
nginx主要配置如下:
worker_processes auto; #进程数,auto设置与CPU个数一致
error_log logs/error.log;
pid logs/nginx.pid;
worker_rlimit_nofile 1024; #最大打开文件数,不超过系统最大打开文件数(ulimit -n)
events {
#use epoll; #使用epoll事件模型,windows中无法使用
worker_connections 1024; #一个work进程并发处理的最大连接数,不能超过worker_rlimit_nofile
}
http {
include mime.types;
default_type text/plain;
server_tokens off; #关闭nginx版本提示
fastcgi_intercept_errors on;
server_names_hash_bucket_size 128;
client_header_buffer_size 4k;
large_client_header_buffers 4 32k;
#日志格式
log_format main '[$time_local] $remote_addr - $remote_user "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for" '
'$upstream_addr '
'ups_resp_time: $upstream_response_time '
'request_time: $request_time';
sendfile on; #开启高效文件传输模式
keepalive_timeout 10; #长连接超时时间
tcp_nodelay on;
tcp_nopush on;
client_body_buffer_size 512k; #缓冲区代理缓冲用户端请求的最大字节数
client_max_body_size 10m; #允许客户端请求的最大单文件字节数
#http_proxy
proxy_connect_timeout 60; #代理连接超时时间
proxy_read_timeout 130; #代理接收超时时间
proxy_send_timeout 60; #代理发送超时时间
proxy_buffer_size 16k; #从后端服务器读取用户头信息的缓冲区大小
proxy_buffers 4 64k; #proxy_buffers缓冲区,nginx针对单个连接缓存来自后端的响应
proxy_busy_buffers_size 128k; #高负荷下缓冲大小
proxy_temp_file_write_size 128k; #当proxy_buffers满时,将部分保存到临时文件,这个值设置文件大小
#gzip
gzip on; #开启gzip压缩输出,减少网络传输
gzip_min_length 1k; #设置允许压缩的页面最小字节数,建议设置成大于等于1K
gzip_buffers 4 16k; #设置系统获取几个单位的缓存用于存储gzip的压缩结果数据流
gzip_http_version 1.1; #用于识别http协议的版本
gzip_comp_level 4; #压缩比,1-9
gzip_types test/html text-javascript text/plain application/x-javascript text/css application/xml application/json;
gzip_vary on; #在响应头加个Vary:Accept-Encoding
server {
listen 80;
server_name localhost;
#请求返回给后台服务器
location / {
proxy_set_header Host $Host;
proxy_set_header WebHost $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Accept-Encoding '';
proxy_set_header Cookie $http_cookie;
proxy_redirect off;
proxy_http_version 1.1;
proxy_next_upstream error timeout http_404 http_500 http_502 http_503;
proxy_pass http://127.0.0.1:5000;
}
#返回本地静态资源
location ^~ /static {
root C:/app;
expires 30d;
}
}
}
效果如下:
Name | highest 10sec mean | lowest 10sec mean | Highest Rate | Mean Rate | Mean | Count |
---|---|---|---|---|---|---|
connect | 0.16 sec | 31.85 msec | 1348.4 / sec | 428.96 / sec | 93.65 msec | 255991 |
page | 6.25 sec | 0.46 sec | 1346.9 / sec | 426.19 / sec | 1.30 sec | 254250 |
request | 6.25 sec | 0.46 sec | 1346.9 / sec | 426.19 / sec | 1.30 sec | 254250 |
session | 8mn 49sec | 40.80 sec | 8 / sec | 0.88 / sec | 1mn 55sec | 469 |
Code | Highest Rate | Mean Rate | Total number |
---|---|---|---|
200 | 63.5 / sec | 38.39 / sec | 22791 |
500 | 133 / sec | 11.27 / sec | 6193 |
504 | 18.5 / sec | 12.58 / sec | 7020 |
第一个表上看,并发是增加了,但是其实500,和504的错误也增加了,但看200的并发也就不超过40/sec,感觉好像完全没有性能的提升,反而下降了。看nginx的error报错,也是说upstream timeout。于是考虑增加nginx中upstream中服务器台数。
5、开4个tornado部署的flask项目,使用nginx反向代理,并处理静态文件,并发用户1000
通过分别开4个tornado监听8001,8002,8003,8004端口,当做4台应用服务器
nginx配置中增加如下配置:
upstream frontends{
server 127.0.0.1:8001;
server 127.0.0.1:8002;
server 127.0.0.1:8003;
server 127.0.0.1:8004;
}
#请求返回给后台服务器
location / {
proxy_set_header Host $Host;
proxy_set_header WebHost $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Accept-Encoding '';
proxy_set_header Cookie $http_cookie;
proxy_redirect off;
proxy_http_version 1.1;
proxy_next_upstream error timeout http_404 http_500 http_502 http_503;
#proxy_pass http://127.0.0.1:5000;
proxy_pass http://frontends;
}
最终效果如下:
Name | highest 10sec mean | lowest 10sec mean | Highest Rate | Mean Rate | Mean | Count |
---|---|---|---|---|---|---|
connect | 0.67 sec | 32.84 msec | 1431.8 / sec | 359.78 / sec | 0.12 sec | 215438 |
page | 12.50 sec | 0.43 sec | 1425.3 / sec | 356.32 / sec | 1.49 sec | 213317 |
request | 12.50 sec | 0.43 sec | 1425.3 / sec | 356.32 / sec | 1.49 sec | 213317 |
session | 8mn 17sec | 32.67 sec | 19.9 / sec | 0.82 / sec | 1mn 32sec | 436 |
Code | Highest Rate | Mean Rate | Total number |
---|---|---|---|
200 | 118.5 / sec | 64.11 / sec | 38643 |
500 | 73.2 / sec | 10.50 / sec | 5817 |
502 | 0.5 / sec | 0.03 / sec | 15 |
504 | 0.5 / sec | 0.02 / sec | 7 |
效果有了一定的提升,200Code的并发可以到64/sec了,按理应该达到4倍。nginx的error.log还是提示有upstream的timeout。在测试过程中,服务器本身cpu内存没有到达瓶颈,仅有冲高,但也没达到一半。
问题
按理并发效果应该远比这个要好,根据网上评测应该可以有个小1000吧。
nginx中超时时间也设置为60了,不加nginx就全部是200,没有50x的错误,为啥加了反而不行了。。。
求各位大神指点,谢谢
一直没有人答复,那我自己说下后续吧
觉得这个问题应该还是Nginx的配置超时问题,于是在upstream配置里进行如下设置:
也就是告诉Nginx,无论尝试多少次,都继续尝试。效果如下:
可以看出,在400并发的时候,全部都是200,500的时候就不行了。这里部署4个flask实例也是在同一台服务器上,应该也有一些性能瓶颈。所以目前得出的结论是,单台服务器使用Nginx+torando部署flask基本上并发到400-500就差不多了。在实际商用中,Nginx的配置还是不要配这么极端,两个都是0就等于没有灾备迁移功能了。
当前测试的是网站的首页,涉及后台html的渲染,数据库查询等,那么如果只返回一个"hello world"的情况效果如何呢:
可以看出tornado框架还是很稳定的,基本上不会直接给502之类的错误,顶多要多等待一会。单台并发稳定在200左右。加了Nginx之后,由于全部都部署在一台服务器上,并发最高可以到500多,1000的压力下就会有502错误了。
期间还有一些windows服务器瓶颈问题,可以参考下http://keejo.coding.me/Window...