本文主要记录使用arthas工具来排查线上系统接口性能问题,如果你也刚好刷到这篇文章,希望对你有所帮助。
事情起因是接手了一个项目,已经部署在现场了,结果访问页面提示超时,这里先通过F12打开浏览器开发者工具,确定了是接口getMeterList
接口响应超时,接着我去看了应用日志,并没有发现报错,还在运行中。紧接着我又去看了该接口内部实现,里面调用了多个方法查询,不确定具体是哪个方法执行有问题。由此我这里想借助arthas
工具去帮助分析一些接口调用时长。下面主要记录如何去做。
首先去官网下载地址获取arthas工具压缩包,这里我下载的是arthas-packaging-3.6.7-bin.zip
,然后将其上传到应用部署的服务器(目录不限定),再将其解压出来,如下图所示:
解压后我们可以先尝试运行一下:
java -jar arthas-boot.jar
运行后它会自动检测到当前服务器上正在运行的Java应用进程,如下所示:
[root@localhost arthas-packaging-3.6.7-bin]# java -jar arthas-boot.jar
[INFO] JAVA_HOME: /usr/local/java/jdk1.8.0_152/jre
[INFO] arthas-boot version: 3.6.7
[INFO] Found existing java process, please choose one and input the serial number of the process, eg : 1. Then hit ENTER.
- [1]: 3750 /home/app.jar
这里显示有一个app.jar在运行,输入1回车即可进入arthas的控制台窗口,通过输入相应的命令来达到不同的排查效果,具体命令可以参考官网的doc文档,写的很详细。我这边选择的是trace
命令,它能展示方法内部调用路径,并输出方法路径上的每个节点上耗时。
我使用的开发工具是idea,可以借助里面的插件工具arthas idea
来快速生成arthas工具命令,这样就避免用手敲出错了。我们首先在入口方法上右键,然后选择Arthas Command,然后选择Trace,这样就获取到了该方法的trace命令,如下图所示:
接着我们将获取到的命令行粘贴到前面打开的arthas的控制台里,执行一下,这时候我们再去页面点击一下,控制台就开始执行检测了,会输出方法内部的调用路径和耗时信息,如下图所示:
红色部分是该方法总的执行时间,有13秒多,然后面列出了方法内部其他方法的调用时长,可以看到主要时间都是被这个getMeterPageList方法占用了,接下来我们重复上述方法,再去监测一下该方法内部耗时情况,最终定位到方法realtimeQuery,耗时高达12秒多,这是一个查询方法,我们先看一下它的执行计划,如下图所示:
这里可以看到子查询和主查询都是全表扫描,当前表里的数据60w,已经慢成这样了,这里我先尝试添加了tagname和time字段的联合索引,来看一下执行计划:
感觉效果并不理想,该应用使用的数据库是MySQL8,这里通过窗口函数ROW_NUMBER() 或 RANK() 函数来重写查询
,如下所示:
SELECT tag_name, VALUE, TIME
FROM (
SELECT
tag_name,
VALUE,
TIME,
ROW_NUMBER() OVER(PARTITION BY tag_name ORDER BY TIME DESC) AS rn
FROM tag_value
WHERE tag_name IN ('1', '2')
) AS subquery
WHERE subquery.rn = 1;
ROW_NUMBER() 为每个 tag_name 分组内的记录分配一个唯一的序号,按照 TIME 降序排列。外层查询然后选择每个分组中序号为1的记录,即每个 tag_name 的最新记录。让我们再来看一下执行计划:
现在看上去还不错,那么接下来再用arthas去监测一下接口性能,发现该方法查询已经降到了130ms,问题得到解决。
好了 这篇文章到这里也就结束了,主要记录了如何用arthas来排查接口性能问题以及如何去优化SQL,希望对你也有所帮助。