一、估算系统的性能最大吞吐量
1、首页获取商品列表
模拟APP首页产生10KB的数据。
2、在https://start.spring.io/生成一个springboot项目
添加:ItemVO.java
package com.example.demo;
public class ItemVO {
private int id;
private String name;
private String city;
private int price;
private int number;
private String picture;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getCity() {
return city;
}
public void setCity(String city) {
this.city = city;
}
public int getPrice() {
return price;
}
public void setPrice(int price) {
this.price = price;
}
public int getNumber() {
return number;
}
public void setNumber(int number) {
this.number = number;
}
public String getPicture() {
return picture;
}
public void setPicture(String picture) {
this.picture = picture;
}
}
添加:ItemController.java
package com.example.demo;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.ArrayList;
import java.util.List;
@RestController
public class ItemController {
@RequestMapping("/home")
public List<ItemVO> home() throws InterruptedException {
byte[] bytes1 = new byte[1024*5];
//模拟业务操作,睡5毫秒
Thread.sleep(5);
byte[] bytes2 = new byte[1024*5];
//模拟业务操作,睡5毫秒
Thread.sleep(5);
List<ItemVO> lists = getItems();
return lists;
}
private List<ItemVO>getItems() {
List<ItemVO> lists = new ArrayList<>();
for(int i=0; i<10; i++) {
ItemVO item = new ItemVO();
item.setId(i+1000);
item.setName("商品"+i);
item.setCity("上海");
item.setNumber(i);
item.setPrice(i);
item.setPicture("http://www.picture.com");
lists.add(item);
}
return lists;
}
}
外部配置文件:application.properties
server.port=8080
3、上传文件到服务器,并启动
java -jar -Xms200m -Xmx200m -Dspring.config.location=/appserver/application.properties demo-0.0.1-SNAPSHOT.jar &
4、访问地址http://IP地址:8080/home
5、第一步:估算QPS理论值
先看单次请求多少毫秒
假设是200毫秒
QPS = 1000 / 200 = 5
所以压测的时候,在5左右上下浮动,是对的,和这个值偏离太多就要找原因。
1条线程,QPS = 5
10条线程,QPS = 50
100条线程,QPS = 500
200条线程,QPS = 1000
二、采用jmeter压测,验证系统吞吐量最大理论值
1、jmeter
jmeter是基于Java的压力测试工具。用于对软件做压力测试,它最初被设计用于Web应用测试,但后来扩展到其他测试领域。
https://jmeter.apache.org/
2、运行
windows下运行jmeter.bat
3、操作
1)设置语言
Options - Choose Language - Chinese
2)设置名称:demo测试
3)添加线程组
demo测试 - 右键 - 添加 - 线程(用户) - 线程组
线程数:200
Ramp-Up时间(秒):1
循环次数:500(假设我们要10万并发)
4)添加结果报告
线程组 - 右键 - 添加 - 监听器 - 查看结果树
线程组 - 右键 - 添加 - 监听器 - 汇总报告
线程组 - 右键 - 添加 - 监听器 - 聚合报告
5)添加HTTP请求
线程组 - 右键 - 添加 - 取样器 - HTTP请求
协议:http,服务器名称或IP:192.168.3.203,端口号:8080
HTTP请求:GET,路径:/home
去掉跟随重定向、使用KeepAlive
三、第一次压测(验证单条线程的最大QPS)
1、改tomcat配置文件
只配1条线程:
server.port=8080
server.tomcat.threads.max=1
2、内存给512M
年轻代=170M(Eden=136M,survivor0=17M,survivor1=17M)
老年代=341M
体验下效果
3、重新打包,名称为demo-0.0.1-SNAPSHOT-1.jar
java -jar -Xms512m -Xmx512m -Dspring.config.location=/appserver/application.properties demo-0.0.1-SNAPSHOT.jar &
4、jmeter点击启动
5、报告
1)汇总报告
吞吐量是86,远远大于预计的5,这是为啥
2)查看结果树
勾选仅错误日志,查看错误
四、分别测试
1条线程:吞吐量80
10条线程:吞吐量95
错误Connection timed out: connect
错误Connection refused: connect
100条线程:吞吐量85
错误Connection timed out: connect
错误Connection refused: connect
200条线程:吞吐量86
错误Connection timed out: connect
错误Connection refused: connect
错误Read timed out
五、tomcat线程
tomcat用的是nio模式,如果最大线程设置为10,则exec线程有10个
1924 root 20 0 2587756 281976 13540 S 0.0 15.0 0:00.22 http-nio-8080-e
1925 root 20 0 2587756 281976 13540 S 0.0 15.0 0:00.00 http-nio-8080-e
1926 root 20 0 2587756 281976 13540 S 0.0 15.0 0:00.00 http-nio-8080-e
1927 root 20 0 2587756 281976 13540 S 0.0 15.0 0:00.00 http-nio-8080-e
1928 root 20 0 2587756 281976 13540 S 0.0 15.0 0:00.00 http-nio-8080-e
1929 root 20 0 2587756 281976 13540 S 0.0 15.0 0:00.00 http-nio-8080-e
1930 root 20 0 2587756 281976 13540 S 0.0 15.0 0:00.00 http-nio-8080-e
1931 root 20 0 2587756 281976 13540 S 0.0 15.0 0:00.00 http-nio-8080-e
1932 root 20 0 2587756 281976 13540 S 0.0 15.0 0:00.00 http-nio-8080-e
1933 root 20 0 2587756 281976 13540 S 0.0 15.0 0:00.00 http-nio-8080-e
1934 root 20 0 2587756 281976 13540 S 0.0 15.0 0:00.01 http-nio-8080-P
1935 root 20 0 2587756 281976 13540 S 0.0 15.0 0:00.01 http-nio-8080-A
六、jmeter界面说明
1、变量定义
双击测试项目名称
全局变量(用户定义的变量):User Defined Variables
局部变量(用户参数):User Parameters
线程组上 - 右键 - Add
2、http请求头
HTTP Header Manager
线程组上 - 右键 - Add
3、需要动态生成的变量
BeanShell Sampler
线程组上 - 右键 - Add
shell脚本中,jdk自带的类,直接import就能使用
外部.java文件和jar需要指定或配置后才能使用
4、http请求
HTTP Request
线程组上 - 右键 - Add
5、结果查看
View Results Tree
Summary Report
Aggregate Report
线程组上 - 右键 - Add
6、执行日志
点击右上角的三角感叹号符号
7、Json提取器
提取上一个Sampler返回json串的某个返回字段
8、跨线程组传参数
前一个线程组存入全局属性:${__setProperty(xxx, ${xxx})}
后一个线程组获取属性:${__P(xxx)}
9、响应断言
在Http Request下加响应断言,这样只对http请求这个sampler有效,如果加在线程组下面,则对每个脚本执行都会有断言
10、固定定时器
在Http Request下加固定定时器,控制线程等待多少毫秒执行一次
11、jmeter内置对象
(1)vars对象
定义变量
vars.put(String key, String value)
vars.get(String key)
(2)ctx对象
import org.apache.jmeter.samplers.SampleResult;
// 获取取样器结果
SampleResult result = ctx.getPreviousResult();
// 获取请求头
String RequestHeaders = result.getRequestHeaders();
// 获取响应头
String ResponseHeaders = result.getResponseHeaders();
// 获取响应码
String responseCode = result.getResponseCode();
// 获取响应数据
String responseData = result.getResponseDataAsString();
(3)prev对象
该内置对象可以直接使用SampleResult类中的方法
// 获取请求头
String RequestHeaders = prev.getRequestHeaders();
// 获取响应头
String ResponseHeaders = prev.getResponseHeaders();
// 获取响应码
String responseCode = prev.getResponseCode();
// 获取响应数据
String responseData = prev.getResponseDataAsString();
12、jmeter清除open recent(最近打开)
搜索regedit,打开“注册表编辑器”,按照以下路径:
计算机\HKEY_CURRENT_USER\Software\JavaSoft\Prefs\org\apache\jmeter\gui\action
删除recent_file_0到recent_file_5这六个记录
13、jmeter线程组单个执行和顺序执行
(1)线程组分类
setUp Thread Group:在普通线程组执行之前执行
Thread Group:普通线程组
tearDown Thread Group:在普通线程组执行之后执行
(2)jmeter会按照添加顺序依次执行所有的setUp Thread Group(不可跳过)
(3)tearDown Thread Group测试下来也会执行(不可跳过)
(4)线程单个执行和多个顺序执行,只针对于Thread Group普通线程组
所以如果你案例里只有三个线程组:
setUp Thread Group
Thread Group
tearDown Thread Group
不论怎么设置都会执行,因为只有一个普通线程组
(5)配置参数
Run Thread Groups consecutively (i.e. one at time):
控制线程组是并行执行还是顺序执行
说明:
当存在多个线程组(Thread Group),jmeter默认是同时执行的,也就是说是并行的
如果勾选了TestPlan(测试计划)中的Run Thread Groups consecutively(独立运行每个组件组),让线程组执行结束后再执行下一个线程组,就可以简单的控制线程组的执行顺序
Run tearDown Thread Groups after shutdown of main threads:
控制如果主线程Thread Groups意外终止,是否会执行tearDown线程,勾选才执行tearDown,不勾选不执行
(6)结论
jmeter如果设置多个线程组(Thread Group),只能设置并行执行还是顺序执行,不能其中某一个单个执行!
14、找到了一个方法,可以将线程组状态设置为Disable,这样就不会执行这个线程组了