下载并启动jemeter
下载好jemeter5并解压之后,可以先打开jemeter目录下的bin\jmeter.properties文件设置语言:在#language=en下面新加一行添加:language=zh_CN 设置显示中文。然后直接运行jemeter.bat可以直接在windows端打开压测工具。
jemeter压测配置
jemeter压测主要需要以下配置:
- 线程组:启动多个并发的线程发送接口请求,用来测试服务端压力,可以配置线程数,循环次数等等。
- Http请求:线程组发送http请求,需要指定服务器名称或ip,端口号和压测路径。并且打开keepAlive来忽略因为长连接因素造成的误差。(tips:服务器名称可以通过driver/etc/hosts文件来指定,指定的格式为 云服务器ip地址 服务器名称)这样在访问的时候就可以直接输入服务器名称,而不用去记ip。
- 查看结果树:http请求发送之后,查看http返回的结果。
- 聚合报告:记录了线程组进行压测的结果的各项指标。包括tps和qps。
开始压测
jemeter内先保存压测的信息,然后点击绿色运行按钮进行压测。然后可以查看结果树和聚合报告:
聚合报告内各个标签意义:
- average:平均响应时间
- median:中位数的响应时间
- 90% line:有百分之90的请求是在这个结果的时间之内返回的,95% line, 99% line类似。
- min:最短的返回时间
- max:最长的返回时间
- throughput(tps):每秒处理事务数,每秒收发包的数量:比如在10秒内成功处理500个并发请求,那么tps就是50。
聚合报告中:比较重要的是95%线和tps。
准备压测:
1.ps -ef | grep java 查看java的进程编号,我这里是21079.
2.使用pstree 21079,查看有多少个线程数量
3.top -H 查看服务器的各项实时指标:
%cpus : us为用户占用的, sy为系统占用的,一般观察us
load average:代表的收发的压力
4.打开jemeter,设置线程数,这里我设置的线程数为100个,每个线程循环请求10次,共1000次请求,100个线程在10秒内启动。
5.结果,us最高达到了38.8%,没有出错的线程,还不够,再加!
设置线程数500个。一边运行一边查看聚合报告,这次qps最高能达到250多。查看top -H发现mysql的cpu占用非常高。因为我测试的接口压力基本都来自数据库。还是不太够,可以直接加多一些,看看出错的原因在哪里。
6.这次我设置线程数为5000,循环100次。这次顶不住了。。。
查看 pstree -p 21079 | wc -l ------>59
最高才能走59个并发。所以肯定是有问题的,下面是优化。
初步优化
打开项目的springboot内嵌的tomcat的配置文件。
查看可能与并发多线程相关的参数:
server.tomcat.accept-count : 默认是100。这个参数是当tomcat的线程被全部占满之后最大的等待队列的大小。即当等待队列达到100个的时候,再进来的请求线程会被拒绝掉。
server.tomcat.min-spare-threads :默认是10。这个是tomcat应对突发的流量入口的时候的默认启动的线程数,可以理解为最小线程数。
server.tomcat.max-connections: 默认10000,可接受的最大连接数。
server.tomcat.max-threads:默认200。tomcat最大支持的工作线程数。
这样的配置下:连接超过10000之后会出现拒绝连接的情况。请求的线程数超过200+100(等待队列+最大线程数)之后拒绝处理(刚才启动了5000个线程,大量的线程会失败)。
所以我们第一步的优化就是修改tomcat的并发相关的配置。不做这个配置任何其他优化都收效甚微。
打开挂载的springboot配置文件application.properties
修改上面四个当中的三个配置:
server.tomcat.accept-count=800
server.tomcat.max-threads=500
server.tomcat.min-spare-threads=100
主要将最小线程数和最大线程数调高,并把等待队列大小扩容。
但是:
1.最大线程数不能无限大,太大的话会花费巨大的时间在cpu调度,一般4核8g的服务器会设置为1000以下,这里我是4g的就设置为500。
2.等待队列长度也不能过大,等待队列相当于线程的缓冲池,太大会很耗内存,出入队操作也耗费cpu
设置好之后,重启项目 ./deploy.sh &
将并发数调到一个合理的范围:大概200-500之间,循环次数50次。
发现延时300ms左右,tps200左右。无错误。
还有比较重要的keepalive方面的参数,springboot并没有对外开放,需要自己写WebServerFactoryCustomize <ConfigurableWebServerFactory>
的实现类来配置:
//当spring容器内没有TomcatEmbeddedServletContainerFactory这个bean的时候,会把bean加载进来。
@Component
public class WebServerConfiguration implements WebServerFactoryCustomizer<ConfigurableWebServerFactory> {
@Override
public void customize(ConfigurableWebServerFactory factory) {
//使用对应工厂类提供的接口定制化我们的tomcat connector
((TomcatServletWebServerFactory)factory).addConnectorCustomizers(new TomcatConnectorCustomizer() {
@Override
public void customize(Connector connector) {
Http11NioProtocol protocol = (Http11NioProtocol) connector.getProtocolHandler();
//定制化keepAliveTimeOut,30秒,30秒内没有请求,服务端才会断开keepalive连接
protocol.setKeepAliveTimeout(30000);
//当客户端发送超过10000个请求,则自动断开keepalive连接
protocol.setMaxKeepAliveRequests(10000);
}
});
}
}
到此为止,tomcat的参数优化基本完成,tps仍然不高,后续优化。