测试说我写的1个接口压测后TPS不达标,只有200多。 而另外个一直性能不佳的下单接口竟然都有300多,那显然是我接口出问题了。
后用Arthas排查后定位到耗时代码,比较简单,这里做个记录。
本地安装arthas
就完全参考的文档安装部署https://arthas.aliyun.com/doc/quick-start.html,文档写的很好,也不需要去搜别人的博客来学习使用。
支持本地windows安装的,真是很棒。
按照文档来,安装好后cmd黑窗口java -jar arthas-boot.jar启动即可,然后输入1个数字选择具体某个jvm进程,我选择的是本地启动的服务。
定位耗时代码
主要用到trace这个命令。
一步步trace到耗时的方法,定位到是这行:
ValidUtils.validateDTO(driverQRCodeDTO);
ValidUtils是我写的1个工具类,想用来手动做Java Bean Validation的,真没想到就这块代码拉胯了(之前以为是哪块数据库操作或调的1个rpc接口耗时出现瓶颈)。
代码如下:
public static <T> void validateDTO( T dtoClass) {
// 取得一个Validator实例
Validator validator = Validation.buildDefaultValidatorFactory().getValidator();
// 调用Validator#validate方法对这个bean进行校验
// 所有的
// ConstraintViolation的泛型类型要设定为被校验bean的类型
Set<ConstraintViolation<T>> errors = validator.validate(dtoClass);
// 这里遍历errors这个set,打印出各个错误的信息
errors.forEach(error -> {
//TODO
});
if (errors.size() > 0) {
// 可以取出所有的校验失败信息,拼接起来之后返回给调用方
final String errMessages = errors.stream()
.map(ConstraintViolation::getMessage)
.collect(Collectors.joining(", "));
throw new BusinessException(BusinessCode.PARAM_ERROR.getCode(), BusinessCode.PARAM_ERROR.getMsg());
}
}
继续用trace命令(想再度验证下):
trace com.xxx.xxx.enterprise.utils.ValidUtils validateDTO '#cost > 50' -n 100
结果如下。 果然如同我的猜想,是获取validator这个方法有性能问题。
压测OK
注释掉这行代码后再次压测(用的jmeter),线程组如下:
结果ok(虽然是开发环境上压着玩的,服务器性能一般,但1k也够了):
得出结论:
- 能自己本地用jmeter压测不要自己写多线程模拟并发,真的不准!
- 压本地环境TPS比压开发环境低(TPS 5,600),原因未知,arthas看了耗时在数据库。
- 如开头所猜想,既然其他接口好的,事实证明也确实果然是这个接口的问题,而不是开发环境的网关服务或磁盘哪里耗时了。
- 就算开发环境的服务器性能很差,但数据库插入的压测 TPS 都能有2000,说明这次压测不达标大概率就不是数据库压力了。