测试说我写的1个接口后TPS不达标,只有200多。 而一直性能不佳的下单接口竟然都有300多,那显然是我接口出问题了。
后用arthas排查后定位到耗时代码,比较简单,这里做个记录。
本地安装arthas
就完全参考的文档安装部署https://arthas.aliyun.com/doc/quick-start.html
,文档写的很好,也不需要去搜别人的博客来学习使用。 支持本地windows安装的,真是很棒。
安装好后cmd黑窗口java -jar math-game.jar
启动即可,然后输入1个数字选择具体某个jvm进程。
定位耗时代码
主要用到trace
这个命令。 一步步trace到耗时的方法,定位到是这行:
ValidUtils.validateDTO(driverQRCodeDTO);
ValidUtils
是我写的1个工具类,用来手动校验Validation,没想到就这块拉胯了。
代码如下:
import javax.validation.ConstraintViolation;
import javax.validation.Validation;
import javax.validation.Validator;
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
注释掉这行代码后压测,线程组如下:
结果ok(开发环境上压着玩的,服务器性能一般,不过1k够了):
得出结论:
- 能自己本地用jmeter压测不要自己写多线程模拟并发,不准!
- 压本地环境TPS比压开发环境低,原因未知,arthas看了耗时在数据库。
- 如开头所猜想,既然其他接口好的,事实证明也确实果然是这个接口的问题,而不是开发环境的网关服务或磁盘哪里耗时了。
- 就算开发环境的服务器性能很差,数据库插入的压测都有2000,说明这次压测不达标不是数据库压力。