说明:最近刚学会Arthas,就对自己开发的接口试了下。发现了几个接口RT较长,就相应做了优化。本文介绍使用Arthas优化接口的思路。
Arthas使用
Arthas使用可参考博主的这篇文章:Arthas使用及常用命令,也可参考官网提供的文档。
排查接口
首先,找到需要操作的项目。大多数情况,公司服务器不会只部署一个项目,往往是其他分支、其他项目的程序都在一起运行,在这个情况下运行Arthas,就会出现大量相同名称的进程,让我们不知道哪个是我们需要的操作的项目。如下:
这时我们可以通过下面的命令找到我们需要的PID:
- Linux:ps -ef | grep ‘关键字’
- Windows:netstat -ano | findstr 端口号
我们可以根据项目配置的端口号,或者如果是分布式项目,可通过配置的注册中心地址(可在项目配置文件中找到,端口号一般会和其他项目错开)来锁定这一组服务,如下:
这里第2列是PID,但需要注意,ps命令
也会生成一个进程,所以如果你的项目有5个模块,那么查出来就是 2 × 5 + 1 = 11
行,每个项目占两个进程,一个是项目,一个是查询的命令,最后一个是总的查询命令进程。仔细看会发现,第1行第2列的PID(如上图的2465)是第2行第3列的值,下面的进程都是这样的,它们是成组出现的。
而我们进入Arthas窗口,输入的PID则是成组出现的下面这个,如上图的2467、2517、2644……,输入对应的PID,就可以对对应的项目进行排查;
分析
进入Arthas后,使用trace
命令追踪接口,命令后面跟 全类名 方法 查看链路耗时(总耗时 499ms);
在最下面调用了Service层的代码,继续追踪Service实现类中的对应的方法,如果使用远程调用(如Dubbo、Feign实现,实现类不在该服务中,则需要退出找到实现类对应的服务模块,再继续排查,不然会提示找不到该类)如下:
总耗时578ms(与前面499ms不符,可能是网络波动),找到了其中一个方法,耗时占比最高,该方法的代码如下(已脱敏):
/**
* 学生关联教室,通过给学生赋classRoom值实现
*/
private void updateData(String classRoom, List<String> ids) {
int index = 1;
if (CollectionUtils.isNotEmpty(dataPaths)) {
for (String s : ids) {
User user = new User();
user.setClassRoom(id);
user.setId(s);
user.setIndex(index);
index++;
userMapper.updateById(User);
}
}
}
很明显,这里循环操作数据库了。可以考虑改为批量操作,只访问一次数据库,缩减处理时长;
优化
关于Mybatis批量更新对象数据,参考以下这篇文章,如果是MyBatis-Plus则有与之对应的方法;
修改完之后,再使用trace
命令测试,查看成果,如下:
耗时203ms,缩短了一半,美滋滋;
总结
本文介绍了使用Arthas优化接口的实际使用,耗时长的方法很好定位,重点是如何找到自己要排查的项目、接口。