Nginx第三方连接限制模块提升服务性能

前段时间项目组在解决一个服务端性能问题的时候有幸了解到了Nginx一个第三方模块nginx-limit-upstream模块,此模块属于个人贡献,拿来玩玩,验证下是否对当前服务性能有很好的改善。下面介绍下模块使用以及在服务上的验证情况。

1. Nginx添加此模块

此模块当前只支持原生的Nginx,对于Openresty好像并没有很好的支持,至少个人在openresty上没有编译成功。

  • 下载源码:git clone https://github.com/cfsego/nginx-limit-upstream.git 到目录nginx-limit-upstream,打开目录可以看到下面文件

      nos@classb-nos0:~/nginx-limit-upstream$ ls
      config  LICENSE  nginx-1.10.1.patch  nginx-1.4.4.patch  nginx-1.8.1.patch  nginx.patch  ngx_http_qos_module.c  README    
    
  • 下载原生Nginx,我这里用的是Nginx-1.8.1版本

  • 在Nginx-1.8.1目录下进行patch,并指定对应patch版本

      nos@classb-nos0:~/nginx-1.8.1$ patch -p0 < /home/nos/nginx-limit-upstream/nginx-1.8.1.patch
    
  • 在nginx目录下执行config,并Add第三方模块

      nos@classb-nos0:~/qiujiansong/nginx-1.8.1$ ./configure --prefix=/home/nos/nginx-1.8.1-i --with-pcre=/home/nos/pcre-8.37 --with-openssl=/home/nos/openssl-1.0.2j --with-zlib=/home/nos/zlib-1.2.8 --add-module=/home/nos/nginx-limit-upstream
    
  • 编译安装即可

      make 
      make install 
    

2. 模块使用及语法简介

  • limit_upstream_zone 为此模块分配一块内存

      syntax:  limit_upstream_zone zone_name size;
      default: -
      context: http
    
  • limit_upstream_conn 连接限制配置

      syntax:  limit_upstream_conn zone=zone_name limit=limit [backlog=length] [timeout=timeout | nodelay] [instant_hook];
      default: -
      context: upstream
    
      * zone 即为上面limit_upstream_zone所定义的zone_name
      * limit 即为所要限制的连接上线
      * backlog 为当连接被占用,请求放入队列等待处理的队列最大长度(允许积压的最大请求数)
      * timeout 队列超时时间,放入队列中的请求当超过timeout时间未被处理直接返回给客户端并返回408
    
  • limit_upstream_log_level 超时失败后打印日志级别配置

      syntax:  limit_upstream_log_level [ error | warn | notice | info ];
      default: limit_upstream_log_level notice;
      context: http, upstream
    

3. 模块验证

在介绍模拟验证效果钱,简单说下我们的服务行为,我们的服务是认证服务,服务业务特点是每个http请求处理很快,当前行为当并发量较大的时候,TPS下降,CPU利用率会降低,且在服务端你会发现大量的TIME_WAIT状态的连接。下面针对限制连接和非限制连接两种情况不同的并发进行性能对比。

测试配置情况:

  • 后端服务,tomcat最大线程数:1024
  • 服务端所在机器:2CPU、32线程
  • 未添加limit限制,nginx中upstream配置如下

      upstream backend_auth {
          server 10.160.133.133:9090;
          keepalive 800;
      }  
    
  • 添加limit限制,nginx中upstream配置如下

      limit_upstream_zone test 200m;
      upstream backend_limit_auth {
          server 10.160.133.133:9090;
          limit_upstream_conn limit=200 zone=test backlog=10000 timeout=3s;
          limit_upstream_log_level error;
          keepalive 800;
      }     
    

    注意 此处upstream配置中使用了keepalive,当使用keepalive时,limit限制推荐值limit=keepalive/worker_processes。

测试结果:

不同并发情况下记录各种性能数据,每轮测试运行5分钟。结果统计如下:

并发数+是否limit TPS Mrt(ms) %CPU ESTABLISHED TIME_WAIT
200并发+no_limit 37316.50 4.63 640 233 237
200并发+add_limit 48023.60 3.63 670 232 263
300并发+no_limit 32113.00 8.22 582 397 331
300并发+add_limit 36238.50 5.96 672 303 178
500并发+no_limit 20839.30 20.71 441 542 433
500并发+add_limit 30414.50 11.46 544 515 222

结果分析: 从结果来看,当不添加连接限制的时候随着并发的增加处于TW状态的连接较多,说明连接未能够很好的被复用,另外随着并发增加CPU使用了及响应时间下降明显,资源利用率较低。对比添加limit限制的结果来看,同样的并发无论在TPS还是CPU以及响应时间方面都优于未使用限制的情况。

模块适用业务类型:

  • 当前测试并发数及时间都有一定的限制,且测试过程中limit限制为200不变,可能测试结果不太理想,大家可以尝试调整下limit数值相信会有很大的性能提升。
  • 根据上面的分析以及简要的测试结论,此模块对于高QPS但是连接数受限制的业务场景较为实用,笔者所测试模块随着连接数增多,大量处于TW状态,但是资源利用率较低,所以限制连接提高资源利用率是很好的方法。

本文来自网易实践者社区,经作者刘成授权发布。