运维攻坚之jmeter压力测试报错

背景 某客户实施DAP,在上线前需要对DAP进行压力测试,有专门的压力测试环境,并且要求并发能够达到1000,团队使用jmeter作为压测工具,整个系统架构很简单浏览器->Nginx->Tomcat,在压测的时候碰到以下问题

  • 对DAP流程提交接口进行压测,压测不通过
  • 部署一个仅仅返回请求参数,没有任何业务逻辑,压测不通过
  • 绕过Nginx,直接对Tomcat进行压测,压测通过
  • 直接对Nginx进行压测,压测Nginx welcome页面,压测不通过
并且对Nginx进行了大量的调优,能调的参数基本都试过,压测不通过,总结下来就是,只要经过Nginx,压测就不通过,看来问题出现在Nginx上
环境信息
  • Nginx:16CPU 64G内存
  • Nginx配置,这里只列几个比较重要的参数
worker_processes 16; worker_connections 1000; keepalive_timeout 60;

这些参数都调整过,对结果影响不大,当然如果调的太极端,比如worker_processes设置为1,肯定是会报错的。
  • Tomcat:16CPU 64G内存
这个配置Nginx跑1000并发完全是足够的
排查 先看下两个测试结果对比
  • 压测tomcat简单接口,并发1000,循环50次,总共50000次请求
【运维攻坚之jmeter压力测试报错】运维攻坚之jmeter压力测试报错
文章图片

压测结果
运维攻坚之jmeter压力测试报错
文章图片

所有请求没有出现Error
  • 压测Nginx welcome页面,并发1000,循环50次,总共50000次请求
运维攻坚之jmeter压力测试报错
文章图片

有百分之0.31%的错误率,虽然不高,但这个错误率是一直有的,而且如果说Nginx的压测不如Tomcat,相信这个结果大家都接受不了,Nginx是负载均衡产品中公认最强的产品,一个是负载均衡,一个是应用服务器,负载均衡最重要的就是并发能力,应用服务器最重要的是业务能力,如果Tomcat在并发能力上超过Nginx,可能会颠覆很多人的认知。所以这其中肯定是有问题的。
Nginx压测请求的错误主要集中在以下几点
  • java.net.ConnectionException: Connection refused: connect
  • java.net.SocketException: Connection reset
  • java.net.SocketException: Unexpected end of file from server
  • org.apache.http.NoHttpResponseException: failed to respond
基本上是网络错误,为了排除网络错误,做了两个测试
本地运行
我自己电脑(MAC)开nginx和tomcat,用jmeter进行压测,结果更不理想,也是1000并发
运维攻坚之jmeter压力测试报错
文章图片

虽然有这么高的错误率,但是不管是nginx还是tomcat,并没有报错,这能说明什么问题呢,说明很可能是内核层面就报错了,也就是请求根本就没进来
Linux主机运行
Jmeter支持在LInux下运行,也支持命令行模式,因此可以考虑在内网服务器找一台同网段主机作为压测机器,步骤如下
  • 将jmeter安装包上传到Linux压测机并解压
  • 在本地配好测试计划,保存为jmx文件,并将jmx文件上传至Linux压测机
  • 执行以下命令以命令行模式开启压测
apache-jmeter-5.4.1/bin/jmeter.sh -n -t plan.jmx -l plan.jtl

运维攻坚之jmeter压力测试报错
文章图片

  • 将结果文件plan.jtl下载到本地,在汇总报告中点击Browser打开文件
运维攻坚之jmeter压力测试报错
文章图片

错误率为0,结合本地运行的结果,可以猜测跟压测机的环境有关。
压测机
本次使用的压测机是一台windows 7主机,如果是压测机的原因,那么为什么压tomcat就没问题,压nginx就有问题,两次压测到底区别在哪,我们可以用wireshark进行抓包,看两次压测在网络包上有什么不同
  • Nginx压测抓包,发现有大量RST的包,并且持续快速出现
运维攻坚之jmeter压力测试报错
文章图片

RST是连接关闭时会发送的数据包
  • Tomcat压测抓包也有RST的包,但是速度明显较慢,而且数量不多
也就是说,Nginx压测不断在创建连接和关闭连接,tomact创建连接和关闭连接动作并没有那么频繁,我们可以在windows上用以下命令查看连接情况
netstat -a | find /i /c "TIME_WAIT"

该命令可以统计当前系统处于TIME_WAIT状态的连接数,TIME_WAIT表示连接处于即将关闭的状态,这时候连接所占用的端口依然无法释放,无法进行再次分配,如果短时间内产生大量的TIME_WAIT连接,容易导致端口号耗尽以至于无法创建新的连接,服务无法响应
  • Tomcat压测 TIME_WAIT连接数情况
运维攻坚之jmeter压力测试报错
文章图片

TIME_WAIT表示等待关闭的连接数,可以看到缓慢增长,并且达到两千左右停止增长
  • Nginx压测TIME_WAIT连接数情况
运维攻坚之jmeter压力测试报错
文章图片

可以看到快速增长,并且总数可以达到2w以上,最多可以达到4w,所以两次压测的区别就是TIME_WAIT的数量, 那为什么会产生这种结果,以下是我的个人猜测
nginx采用的是epoll非阻塞模型,tomcat采用的是线程模型,一个请求一个线程,属于阻塞模型,所以nginx可以段时间内"吃掉"大量的连接,tomcat需要排队进入,这样就造成了以上现象,nginx短时间创建大量连接,tomcat则是缓慢增加连接
结论 windows作为压测机进行高并发压测并不合适,因为会在短时间内产生大量连接,windows作为工作PC,在这方面处理能力不如Linux,加上网络波动等因素,容易造成错误,造成压测结果失真,虽然可以通过优化部分参数降低错误率,但解决不了根本问题,建议通过同网段Linux主机作为压测机,测试计划可以在windows进行配置,结果分析也可以在windows中完成,但执行测试任务建议在Linux主机上进行。

    推荐阅读