Nginx+tornado部署flask项目,性能提升测试

背景

使用中开发了一个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的错误,为啥加了反而不行了。。。

求各位大神指点,谢谢

阅读 7.1k
1 个回答

一直没有人答复,那我自己说下后续吧

觉得这个问题应该还是Nginx的配置超时问题,于是在upstream配置里进行如下设置:

upstream frontends{
            server 127.0.0.1:8001 max_fails=0 fail_timeout=0;
            server 127.0.0.1:8002 max_fails=0 fail_timeout=0;
            server 127.0.0.1:8003 max_fails=0 fail_timeout=0;
            server 127.0.0.1:8004 max_fails=0 fail_timeout=0;
        }

也就是告诉Nginx,无论尝试多少次,都继续尝试。效果如下:

  • 开4个tornado部署的flask项目,使用nginx反向代理,并处理静态文件,并发用户500
Name highest 10sec mean lowest 10sec mean Highest Rate Mean Rate Mean Count
connect 38.87 msec 30.69 msec 542.9 / sec 419.26 / sec 33.78 msec 121351
page 2.89 sec 0.91 sec 541.7 / sec 417.67 / sec 1.12 sec 120871
request 2.89 sec 0.91 sec 541.7 / sec 417.67 / sec 1.12 sec 120871
Code Highest Rate Mean Rate Total number
200 152 / sec 129.27 / sec 38414
502 414.6 / sec 332.77 / sec 83513
  • 开4个tornado部署的flask项目,使用nginx反向代理,并处理静态文件,并发用户400
Name highest 10sec mean lowest 10sec mean Highest Rate Mean Rate Mean Count
connect 39.83 msec 30.62 msec 146.2 / sec 134.01 / sec 31.44 msec 40059
page 3.21 sec 0.82 sec 140.2 / sec 132.91 / sec 2.76 sec 39663
request 3.21 sec 0.82 sec 140.2 / sec 132.91 / sec 2.76 sec 39663
Code Highest Rate Mean Rate Total number
200 140.2 / sec 132.92 / sec 40008

可以看出,在400并发的时候,全部都是200,500的时候就不行了。这里部署4个flask实例也是在同一台服务器上,应该也有一些性能瓶颈。所以目前得出的结论是,单台服务器使用Nginx+torando部署flask基本上并发到400-500就差不多了。在实际商用中,Nginx的配置还是不要配这么极端,两个都是0就等于没有灾备迁移功能了。

当前测试的是网站的首页,涉及后台html的渲染,数据库查询等,那么如果只返回一个"hello world"的情况效果如何呢:

  • tornado,压力500
Name highest 10sec mean lowest 10sec mean Highest Rate Mean Rate Mean Count
connect 35.79 msec 31.99 msec 244.1 / sec 186.23 / sec 33.65 msec 57079
page 0.31 sec 35.55 msec 473.8 / sec 371.59 / sec 0.21 sec 113773
request 0.31 sec 35.55 msec 473.8 / sec 371.59 / sec 0.21 sec 113773
session 3mn 54sec 7.53 sec 12 / sec 1.65 / sec 45.25 sec 496
Code Highest Rate Mean Rate Total number
200 238.7 / sec 186.42 / sec 57217
  • torando,压力1000
Name highest 10sec mean lowest 10sec mean Highest Rate Mean Rate Mean Count
connect 75.67 msec 31.79 msec 242.1 / sec 212.01 / sec 36.55 msec 63374
page 0.33 sec 78.45 msec 475.3 / sec 423.27 / sec 0.22 sec 126300
request 0.33 sec 78.45 msec 475.3 / sec 423.27 / sec 0.22 sec 126300
session 3mn 19sec 8.58 sec 10.8 / sec 3.23 / sec 22.62 sec 968
Code Highest Rate Mean Rate Total number
200 237.7 / sec 212.27 / sec 63859
  • torando, 压力2000
Name highest 10sec mean lowest 10sec mean Highest Rate Mean Rate Mean Count
connect 47.39 msec 31.65 msec 242.8 / sec 216.52 / sec 33.66 msec 64568
page 0.33 sec 0.25 sec 485.5 / sec 432.49 / sec 0.28 sec 128814
request 0.33 sec 0.25 sec 485.5 / sec 432.49 / sec 0.28 sec 128814
session 1mn 58sec 7.16 sec 12.5 / sec 6.30 / sec 12.45 sec 1891
Code Highest Rate Mean Rate Total number
200 242.8 / sec 216.43 / sec 65019
  • Nginx+torando,压力500
Name highest 10sec mean lowest 10sec mean Highest Rate Mean Rate Mean Count
connect 0.18 sec 86.24 msec 2052.1 / sec 693.82 / sec 0.14 sec 208786
page 0.52 sec 0.24 sec 2060.7 / sec 693.34 / sec 0.45 sec 208606
request 0.52 sec 0.24 sec 2060.7 / sec 693.34 / sec 0.45 sec 208606
Code Highest Rate Mean Rate Total number
200 2056.6 / sec 693.67 / sec 208703
  • Nginx+torando,压力1000
Name highest 10sec mean lowest 10sec mean Highest Rate Mean Rate Mean Count
connect 0.20 sec 31.95 msec 2558.2 / sec 586.12 / sec 0.10 sec 179102
page 0.88 sec 0.11 sec 2579.6 / sec 584.35 / sec 0.60 sec 178521
request 0.88 sec 0.11 sec 2579.6 / sec 584.35 / sec 0.60 sec 178521
Code Highest Rate Mean Rate Total number
200 2478.2 / sec 538.17 / sec 164669
502 181.2 / sec 53.53 / sec 13917
  • 结论

可以看出tornado框架还是很稳定的,基本上不会直接给502之类的错误,顶多要多等待一会。单台并发稳定在200左右。加了Nginx之后,由于全部都部署在一台服务器上,并发最高可以到500多,1000的压力下就会有502错误了。

期间还有一些windows服务器瓶颈问题,可以参考下http://keejo.coding.me/Window...

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题