一、压测数据准备
1.1 注册5000个用户
在leyou-user中增加测试方法,用来注册5000个用户。
import com.leyou.user.LyUserApplication;
import com.leyou.user.mapper.UserMapper;
import com.leyou.user.pojo.User;
import com.leyou.utils.CodecUtils;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
import java.util.Date;
/**
* @Author: 98050
* @Time: 2018-11-14 23:31
* @Feature:
*/
@RunWith(SpringRunner.class)
@SpringBootTest(classes = LyUserApplication.class)
public class UserTest {
@Autowired
private UserMapper userMapper;
/**
* 注册5000个用户
*/
@Test
public void addUser(){
User user = new User();
for (int i = 1; i < 5000; i ++){
user.setId(null);
user.setCreated(new Date());
user.setPhone("1883482"+String.format("%04d",i));
user.setUsername("username"+i);
user.setPassword("abcdefg"+i);
String encodePassword = CodecUtils.passwordBcryptEncode(user.getUsername().trim(),user.getPassword().trim());
user.setPassword(encodePassword);
this.userMapper.insertSelective(user);
}
}
}
1.2 获取5000用户的登录Token
在授权中心leyou-authentication里添加测试方法,获取5000用户的Token并写入文件中。获取token前,设置永不过期
import com.leyou.auth.LyAuthApplication;
import com.leyou.auth.service.AuthService;
import com.leyou.user.pojo.User;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
import java.io.*;
/**
* @Author: 98050
* @Time: 2018-11-15 00:00
* @Feature: 获取5000用户的Token,写入文件中
*/
@RunWith(SpringRunner.class)
@SpringBootTest(classes = LyAuthApplication.class)
public class TokenTest {
@Autowired
private AuthService authService;
@Test
public void getTokenCSV(){
try {
File csv = new File("G://Token.csv");//CSV文件
BufferedWriter bw = new BufferedWriter(new FileWriter(csv, true));
for (int i =0; i < 5000; i++) {
//新增一行数据
String token = this.authService.authentication("username"+i,"abcdefg"+i);
bw.write("username"+i+","+token);
bw.newLine();
}
bw.close();
} catch (FileNotFoundException e) {
//捕获File对象生成时的异常
e.printStackTrace();
} catch (IOException e) {
//捕获BufferedWriter对象关闭时的异常
e.printStackTrace();
}
}
}
二、测试
2.1 秒杀商品准备
2.2 可以用来秒杀的库存
2.3 Jmeter压测
2.2.1 设置读取csv文件
模拟不同用户
2.2.2 测试
50个用户,循环请求10次,看一下结果:
发现问题,stock多减了好多。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。
2.2.3 修改配置
在进行测试时,由于秒杀服务通过Feign Client来调用订单服务下订单,有可能出现超时的情况,这里面需要在秒杀微服务中配置一下Ribbon和Hystix。
ribbon:
ConnectTimeout: 400 # 连接超时时间(ms)
ReadTimeout: 2000 # 通信超时时间(ms)
OkToRetryOnAllOperations: true # 是否对所有操作重试
MaxAutoRetriesNextServer: 1 # 同一服务不同实例的重试次数
MaxAutoRetries: 1 # 同一实例的重试次数
hystrix:
command:
default:
execution:
isolation:
thread:
timeoutInMillisecond: 10000 # 熔断超时时长:10000ms
2.2.4 错误分析
为什么会造成多余的订单呢?因为数据不一致造成的,当一次请求到达订单微服务,检查库存充足,然后开始下订单,结果由于高并发,这次操作中还没有修改数据库中的库存,结果第二个请求就来了,造成多余的订单生成。