QPS 100K压测报告

1、现状说明

线上服务器QPS最高只能达到40K,架构中各层服务(Nginx、Tomcat、Dobbu、Redis/Mysql)的服务器负载都很低,横向扩展Nginx、Tomcat服务器,QPS不提升,增加压力,QPS和服务器负载还会下降。

无法知道架构的瓶颈在哪一层,各层服务的瓶颈值是多少,导致无法根据用户量来预估服务器的数量。

2、测试目标

  • 测试出各层服务的瓶颈值
  • 测试出当前架构能达到的QPS
  • QPS达到100K时,是否需要扩展或调整架构,怎么调整

3、测试计划

阶段测试项目目标
单压Nginx增加压力,QPS成线性增长,单台Nginx QPS能达到200K以上
单压Tomcat(空)掌握Tomcat的QPS和服务器负载情况
Nginx + Tomcat(空)增加压力和Tomcat,QPS成线性增长,QPS能达到100K以上
Nginx + 带业务Tomcat掌握业务的QPS和服务器负载情况,增加压力和Tomcat,QPS成线性增长,QPS能达到100K
Nginx + 带业务Tomcat + Dubbo掌握Dubbo的负载情况
Nginx + 带业务Tomcat + Dubbo + Redis掌握Redis的负载情况,以及整体QPS达到100K的情况

4、术语说明

测试中,经常会遇到一些术语,这些术语可能在不同的场景会出现概念偏差,为了保持统一,在本次测试中,对这些术语和公式进行说明。

带宽: 单位一般用 MbpsMbit/s,用来描述数据传输速度。常用在描述光纤和网线上。

吞吐量: 单位一般用 MBMByte,用来描述数据量。常用在描述网卡上。MbpsMB 是可以计算转换的,1000Mbps = 125 MB(8倍的关系)。

QPS: 每秒的响应请求数,该值代表了系统的吞吐能力。

TPS: 每秒处理的事务数。该值代表了系统的性能。

并发数: 系统同时处理的 Request 数,在真实场景中,该值一般等同于并发用户数,因为在同一时刻点,一般一个用户只发送一个Request。

响应时间:平均响应时间。

公式:

QPS或TPS = 并发数 / 响应时间

并发数 = QPS * 响应时间

根据上面的公式,假设一个用户一次请求的响应时间是0.010秒,那么,在1秒内,该用户只能发送100次请求。要想提高1秒内的请求数,只能从两个因素来考虑,要么降低响应时间,要么增加用户数。

同理,对我们的架构来讲,要想提高压测的QPS,要么优化接口的响应时间,要么提供压力的并发用户数。

接口响应时间的优化是下一步工作,并不在这次压测计划范畴,所以,我们只能通过提高压力的并发用户数来提高QPS。

5、服务器配置说明

由于测试都是基于阿里云的ECS进行的,所以配置说明以阿里云提供的信息为标准。

服务器名称规格CPU内存处理器主频内网带宽内网收发包
Nginx通用网络增强型 sn2ne4162.5GHz1.5Gbps50万PPS
Tomcat通用型 g54162.5GHz1.5Gbps50万PPS
压力机通用型 g54162.5GHz1.5Gbps50万PPS
Redis

6、测试过程

由于服务器配置和操作成本原因,整个测试过程都是基于 abTsung 两个压测软件进行的。等全部过程结束后,可以用 Loadrunner 进行一次验证。

6.1、第一阶段

目标:增加压力,QPS成线性增长,单台Nginx QPS能达到200K以上。

压测命令:

ab -c200 -n100000 -k http://nginx01/
压测说明压力机数量QPS响应时间(毫秒)CPU内网进峰值内网出峰值说明
1台空Nginx1140K1.43%很低很低正常压力
1台空Nginx2140K 140K1.4 1.43%很低很低正常压力

结论:

通过压测,说明QPS等于100K的压力,对 Nginx 服务来说,没有任何压力。

6.2、第二阶段

目标:掌握单台Tomcat的QPS和服务器负载情况。

压测命令:

ab -c200 -n60000 -k http://tomcat01:8810/
压测说明压力机数量QPS响应时间(毫秒)CPU内网进峰值内网出峰值说明
1台空Tomcat150K3.680%很低很低正常压力
1台空Tomcat225K 26K3.6 3.685%很低很低正常压力

结论:

通过压测,说明当前配置的服务器,单台TomcatQPS为50K,CPU已经达到了80%,增加压力,并不能明显提高QPS。

备注: 该步骤的Tomcat没有部署任何服务,是一个空的Tomcat。

6.3、第三阶段

目标:增加压力和Tomcat,QPS成线性增长,QPS能达到100K以上。

压测命令:

ab -c240 -n100000 -k http://nginx01/
压测说明压力机数量QPS响应时间(毫秒)CPU内网进峰值内网出峰值说明
1台Nginx + 1台Tomcat150K4.2Nginx:5% Tomcat:80%很低很低正常压力
1台Nginx + 2台Tomcat160K4Nginx:10% Tomcat:12%很低很低压力不够
1台Nginx + 2台Tomcat248K 48K4.9 4.9Nginx:16% Tomcat:75%很低很低QPS = 96k
1台Nginx + 2台Tomcat336K 36K 36K6.5 6.5 6.5Nginx:16% Tomcat:85%很低很低QPS = 10.8
1台Nginx + 3台Tomcat340K 40K 41K6 5.8 5.8Nginx:16% Tomcat:76%很低很低QPS = 12.1
1台Nginx + 4台Tomcat433K 35K 33K 33K7 7 6.8 7.3Nginx:20% Tomcat:80%很低很低QPS = 13.4
1台Nginx + 4台Tomcat524K 24K 23K 21K 22K6 21 5.8Nginx:24% Tomcat:86%很低很低QPS = 11.4

说明:

通过压测,说明当前配置的服务器,Nginx代理Tomcat后的QPS,与单压Tomcat的QPS差不多。而且,持续增加压力,不增加Tomcat,响应时间会增加,QPS并没有明显提升。

通过增加压力和Tomcat,QPS能接近线性增长,也能达到100K。

备注:ab 多台压力机进行压测时,是通过人工手动触发的,存在一定误差。后面将会采用Tsung的集群方式压测。

6.4、第四阶段

目标:掌握业务的QPS和服务器负载情况,增加压力和Tomcat,QPS成线性增长,QPS能达到100K。

压测接口:

# 登录接口
/api/per/login?userName=xxx&password=xxxx&checkCode=xxxx

由于登录接口必须要用Dubbo服务,为了减少Dubbo服务的影响,在每台Tomcat的本地服务器上,都部署了一套Dubbo服务。

压测结果:

查看压测报告中的QPS时,请以 Throughput graps 中的 Requests 为准。

压测说明压力机数量QPS响应时间(毫秒)CPU内网进峰值内网出峰值说明
1台Tomcat19K21.6Tomcat:50%78Mbps76Mbps正常压力
1台Nginx + 1台Tomcat19K21Nginx:7% Tomcat:37%30Mbps35Mbps正常压力
1台Nginx + 2台Tomcat318.5K21Nginx:20% Tomcat:64%133Mbps134Mbps压测报告
1台Nginx + 3台Tomcat327K24Nginx:21% Tomcat:85%330Mbps369Mbps压测报告
1台Nginx + 4台Tomcat336K24Nginx:28% Tomcat:85%459Mbps472Mbps压测报告
1台Nginx + 6台Tomcat350K14Nginx:40% Tomcat:85%684Mbps702Mbps压测报告
1台Nginx + 8台Tomcat352K14.5Nginx:40% Tomcat:72%698Mbps710Mbps压测报告
1台Nginx + 8台Tomcat570K7.5Nginx:46% Tomcat:65%941Mbps963Mbps压测报告
1台Nginx + 8台Tomcat571K10.11Nginx:46% Tomcat:65%941Mbps963Mbps此处增加了压力数,查看压测报告
2台Nginx + 8台Tomcat7100K12.47Nginx:40% Tomcat:78%698Mbps710Mbps压测报告

说明:

  1. 在QPS小于50K时,增加Tomcat数量,QPS能成线性增长;
  2. 在QPS大于50K时,压力不够,增加压力机后,QPS能提升。但是,当QPS达到70K,Nginx内网进出带宽之和已经超出1500Mbps,继续增加压力,QPS几乎不能提升,说明Nginx层的带宽已经达到极限;
  3. 扩展Nginx,增加压力,QPS能达到100K,每台Nginx的内网带宽也下降了。

6.5、第五阶段

目标:掌握Dubbo的负载情况。

压测接口:

# 登录接口
/api/per/login?userName=xxx&password=xxxx&checkCode=xxxx

压测结果:

压测说明压力机数量QPS响应时间(毫秒)CPU内网进峰值内网出峰值说明
1台Nginx + 5台Tomcat + 1台Dubbo129K10.8Tomcat:40% Dubbo:85%nginx:383Mbpsnginx:393Mbps压测报告
1台Nginx + 8台Tomcat + 4台Dubbo570K7.5Nginx:46% Tomcat:65%941Mbps963Mbps压测报告
1台Nginx + 8台Tomcat + 4台Dubbo571K10.11Nginx:46% Tomcat:65%941Mbps963Mbps此处增加了压力数,查看压测报告
2台Nginx + 8台Tomcat + 4台Dubbo7100K12.47Nginx:40% Tomcat:78%698Mbps710Mbps压测报告

说明:

  1. 单台Dubbo服务的QPS能达到29K,扩展Dubbo服务,QPS能增长;
  2. 4台Dubbo服务能撑起QPS等于100K的目标,这时Dubbo服务器的CPU负载已经超过80%,QPS在增加的话,需要扩展Dubbo服务。

6.5、第六阶段

目标:掌握Redis读操作的负载情况,以及整体QPS达到100K的情况。

压测接口:

# 登录接口
/api/per/login?userName=xxx&password=xxxx&checkCode=xxxx

注意:该接口会对Redis执行3次读操作。

压测结果:

压测说明压力机数量QPS响应时间(毫秒)CPU内网进峰值内网出峰值说明
2台Nginx + 8台Tomcat + 4台Dubbo + 1个Redis实例120K10Redis: 100% 其它服务无压力压测报告
2台Nginx + 8台Tomcat + 4台Dubbo + 1个Redis实例219K20Redis: 100% 其它服务无压力此处增加了压力数,查看压测报告
2台Nginx + 8台Tomcat + 4台Dubbo + 1个Redis实例224K16Redis: 100% 其它服务无压力此处将Redis进程绑定了指定的CPU,查看压测报告
2台Nginx + 8台Tomcat + 4台Dubbo + 2个Redis实例247K7Redis: 100% 其它服务无压力此处将Redis进程绑定了指定的CPU,查看压测报告
2台Nginx + 8台Tomcat + 4台Dubbo + 3个Redis实例266K5.7Redis: 96% Dubbo: 70% Tomcat: 56%此处将Redis进程绑定了指定的CPU,查看压测报告
2台Nginx + 8台Tomcat + 6台Dubbo + 5个Redis实例292K10Redis: 80% Dubbo: 80% Tomcat: 70%450Mbps468Mbps此处将Redis进程绑定了指定的CPU,5台Redis实例分布在2台服务器上,查看压测报告
2台Nginx + 8台Tomcat + 6台Dubbo + 5个Redis实例292K14Redis: 80% Dubbo: 80% Tomcat: 70%450Mbps468Mbps此处增加了压力数,5台Redis实例分布在2台服务器上,查看压测报告

说明:

  1. Redis实例进程不绑定CPU时,单实例Redis的登录接口QPS等于20K,当绑定CPU后,QPS等于24K;
  2. 2台Redis实例QPS等于47K,近似线型增长;
  3. 3台Redis实例QPS等于66K,理论值应该等于72K,折损9%,相当于近似线型增长;
  4. 5台Redis实例QPS等于92K,理论值应该等于120K,增加压力,并不能提升QPS,此时,Dubbo服务出现排队情况,已经达到瓶颈,Nginx网络流量接近千兆,而Tomcat和Redis服务没有达到瓶颈;
  5. 再增加一台Dubbo服务,整体QPS应该能达到100K,此项压测省略。

说明:

1、在压测时,并发用户数直接从400调整到1000时, Dubbo服务出现过中途连接Redis超时的问题,多几十秒后,又恢复,说明并发量瞬间值较大时,Dubbo服务可能会出现瓶颈;

2、在压测时,出现一种现象,同样的服务配置和压力,只是因为重新选择了服务器,导致压测结果有一定误差,例如:2个Redis实例(部署在同一台服务器)曾经在不同的服务器上测登录接口,QPS有一定的差异,分别为26K,27K,29K(理论值应该为28K),这个可能跟云服务器的宿主机资源抢占有关;

3、Redis实例绑定CPU时,一定要绑定到没有被用到的CPU上;

4、在压测时,曾出现最后启动的Redis实例,CPUS始终无法压到98%,换台服务器重新压测,就可以。这个也可能跟云服务器的宿主机资源抢占有关。

6.6、第七阶段

目标:掌握Redis写操作的负载情况。

压测接口:

# 写接口(String类型)
/api/per/writeStr?key=MYSTR&value=SUCCESS

/api/per/writeHash?key=MYHASH&field=fffff&value=vvvvvv

压测结果:

压测说明压力机数量QPS响应时间(毫秒)CPU内网进峰值内网出峰值说明
2台Nginx + 8台Tomcat + 6台Dubbo + 1个Redis实例263K5.8Redis: 100% 其它服务无压力第一个接口,压测报告
2台Nginx + 8台Tomcat + 6台Dubbo + 1个Redis实例274K4.5Redis: 100% 其它服务无压力第一个接口,增加压力数压测报告
2台Nginx + 8台Tomcat + 6台Dubbo + 1个Redis实例263K5.2Redis: 100% 其它服务无压力第二个接口,压测报告

说明:单Redis实例写操作,String类型的QPS等于74K,Hash类型的QPS等于63K。

6.7、第八阶段

目标:掌握阿里云Redis性能。

压测接口:

主要有注册、登录、简单的数据写入接口

压测结果:

压测说明Redis版本说明
标准版2.8与自搭建单节点的性能相似
读写分离版2.8与自搭建单节点的性能相似
集群版2.88个节点,登录QPS能达到98000,注册能达到30000

说明:

  1. 阿里云Redis的标准版和读写分离版,与我们自己搭建的Redis性能没有太大区别;
  2. 阿里云Redis的集群版能满足我们的要求;
  3. 自搭建codis与阿里云Redis集群版性能差不多,但是维护成本较高。

7、总结

根据目前的压测情况,可以得出以下初步结论。

负载均衡

  • 这个需要服务商的负载均衡带宽限制来决定,建议采用N + 1的方式。

Nginx

  • Nginx服务在保持长连接的情况下,基本上没有什么压力;
  • 当并发用户数大于60K(这个跟系统的TCP的端口号范围配置有关),需要扩展Nginx;
  • 当Nginx的网络带宽峰值达到极限时,需要扩展Nginx,这个值需要根据所有业务接口的返回数据量大小来评估,根据登录接口压测的情况来看,QPS超过50K时,就需要扩展Nginx。

Tomcat

  • 从登录接口来看,单台Tomcat的QPS为9K+,不同的业务接口,该值会不同,但不会超过50K;
  • 横向扩展Tomcat,QPS能达到线性增长;
  • 从登录接口来看,当Tomcat等于8台时,QPS能达到100K。

Dubbo

  • 从登录接口来看,单台Dubbo的QPS为29K,不同的业务接口,该值会不同;
  • 横向扩展Dubbo,QPS能近似线性增长;
  • 从登录接口来看,当Dubbo等于4台时,QPS能达到100K。

Redis

  • 从登录接口来看,单实例Redis的QPS为24K,不同的业务接口,该值会不同;
  • 横向扩展Redis,QPS能近似线性增长;
  • 从登录接口来看,当Dubbo等于7台,Tomcat等于8台,Nginx等于2台,Redis实例等于5时,整体QPS能达到100K。

整个服务QPS达到100K的各服务部署数量规划表:


服务
建议数量说明
Nginx3主要瓶颈在网络带宽,当QPS达100K时,2台Nginx的平均带宽接近千兆
Tomcat10虽然用8台Tomcat,压测结果能达到100K,这个可能与服务器性能多少有点影响
Dubbo8受业务逻辑影响很大
Redis2+每台上部署多个实例 单实例写操作QPS无法达到目标,读可以,需要重新设计Redis的集群部署方式

8、建议

  • 由于部分接口的请求内容和返回内容的字符太多,当并发上来时,瞬间占用的带宽较大,对业务服务器层的网络带宽和负载均衡的网络带宽压力较大,很容易导致网络阻塞。后期需要优化请求和返回的内容;
  • 大部分接口的响应时间都能达到要求,个别接口的响应时间较长,这个跟业务(多次读写Redis操作)有关。需要优化代码或拆分逻辑;
  • 负载均衡层和服务层达到线性增长后,最终瓶颈会落到读写层(数据库),这时需要选择分库或分布式数据库。