前面我们通过JVM线程分析及内存分析来让大家从服务器资源异常情况下排查代码问题,类似这种的解决方式,更多的是在服务器资源占用已经异常显现,我们就可以按照这种方式去排查和解决。
但实际工作中,可能会出现:接口的TPS很低,但是服务器的各项资源占用率也很低,我们很难通过CPU占用率和内存占用率异常去排查问题。那这里,我们再推荐一种排查工具-Arthas,Arthas 不仅仅能够让我们看到 JVM 的运行状态去定位性能问题,对于很多线上代码异常问题的排查,Arthas 也是手到擒来。
一、Arthas是什么?
Arthas 是阿里提供的一款 Java 开源诊断工具。能够查看应用的线程状态、JVM 信息等;并能够在线对业务问题诊断,比如查看方法调用的出入参、执行过程、抛出的异常、输出方法执行耗时等,极大的提升了线上问题的排查效率。
二、Arthas的使用
1、下载Arthas
我们这里使用命令下载:
wget https://alibaba.github.io/arthas/arthas-boot.jar
Arthas 提供的程序包是以 jar 的形式给出,因此我们可以看出 Arthas 本质也是个 Java 应用。
2、启动
然后使用 java -jar 命令启动,命令如下:
java -jar arthas-boot.jar
输入启动命令后会跳出选项选择要监控的后台 Java 进程,如下代码所示:
[root@JD ~]# java -jar arthas-boot.jar
[INFO] arthas-boot version: 3.3.3
[INFO] Found existing java process, please choose one and input the serial number of the process, eg : 1. Then hit ENTER.
- [1]: 689 cctestplatform.jar
[2]: 31953 unimall.jar
[3]: 14643 sentinel-dashboard-1.7.2.jar
[4]: 20421 org.apache.zookeeper.server.quorum.QuorumPeerMain
[5]: 10694 demo-0.0.1-SNAPSHOT.jar
其中序号表示的就是 Arthas 自动识别的所在服务器的 Java 进程,然后输入要监控的进程的序号并回车,Arthas 便会接着启动,出现 Arthas Logo 之后便可以使用 Arthas 了,如下代码所示:
5
[INFO] arthas home: /root/.arthas/lib/3.4.4/arthas
[INFO] Try to attach process 10694
[INFO] Attach process 10694 success.
[INFO] arthas-client connect 127.0.0.1 3658
wiki https://arthas.aliyun.com/doc
tutorials https://arthas.aliyun.com/doc/arthas-tutorials.html
version 3.4.4
pid 10694
三、Arthas实战演示
1、利用Arthas定位死锁问题
在排查问题前我们先了解下死锁,死锁是指由于两个或者多个线程互相持有对方所需要的资源,导致这些线程处于等待状态,无法前往执行。如果没有外力的作用,那么死锁涉及的各个线程都将永久处于循环等待状态,导致业务无法预期运行,所以我们的代码要避免死锁的情况。
死锁代码示意如下:
//线程Lock1代码示意
while(true){
synchronized("obj1"){
Thread.sleep(3000);//获取obj1后先等一会儿,让Lock2有足够的时间锁住obj2
synchronized("obj2"){
System.out.println("Lock1 lock obj2");
}
}
}
//线程Lock2代码示意
while(true){
synchronized("obj2"){
Thread.sleep(3000); //获取obj2后先等一会儿,让Lock1有足够的时间锁住obj1
synchronized("obj1"){
System.out.println("Lock2 lock obj1");
}
}
}
把以上代码放到服务器中执行,然后我们可以使用 Arthas 的 jvm 命令查看到线程死锁数目为 2,说明程序发生了死锁,如下图所示:
接下来我们输入 thread -b 命令查看当前阻塞其他线程的线程,然后我们可以看到 Lock 1 被阻塞了,访问的资源被 Lock 2 占用,如图所示,根据提示的行数我们便能找到死锁位置,对代码进行优化。
2、使用trace查看方法耗时
写几个不同循环次数的方法,分别代表方法耗时不同,代码如下:
//示例代码,timeCost是个接口
public String timeCost(){
cost1();
cost2();
cost3();
.......
}
private void cost3() {
//进行200万次循环......
}
private void cost2() {
//进行10万次循环......
}
private void cost1() {
//进行10次循环......
}
部署之后我们使用 trace 来查找最耗时的方法,在此过程中需要知道包名、类名,以及方法的名字。上述代码方法所在包名为 com.cctest.arthas_demo.controller,类名为 StressSceneController,所以我们需要输入如下 trace 命令:
trace
com.cctest.arthas_demo.controller.StressSceneController timeCost
输完命令后回车,然后 arthas 程序就进入了等待访问状态。这时候访问接口 /timeCost,我们就可以看到被测程序台在疯狂打印日志,等结束之后,arthas 命令窗口便输出了各方法耗时时间,如图所示:
我们可以看到 timeCost 方法总耗时 258391ms:
-
cost 1 调用耗时 9 ms;
-
cost 2 调用耗时 13909 ms;
-
cost 3 调用耗时 244472 ms。
这里我们就可以看出const2和const3耗时严重,既然已经定位到方法了,那基本上优化的思路也就有了。
3、使用watch命令查看被测方法的入参和返回值
当遇到线上数据问题时,我们一般有两种查找问题的途径:
-
在开发环境中模拟线上数据来复现问题,不过因为环境等各方面的不同,很多情况下模拟数据复现都有难度;
-
在生产日志里查找线索,如果没有相关方法的入参,以及没打印返回值的话,就难以找到有效的信息。
这两种传统查找问题的方式都存在一定的局限性,而使用 Arthas 的 watch 命令可以很方便地根据观察方法入参和出参来判断是否正确定位了代码问题。
比如如下的方法:
@GetMapping("/login")
public String login(@RequestParam(value="userName") String userName, @RequestParam(value="pwd")String pwd){
return "OK";
}
然后我们输入 watch 命令,其中 login 后面指定了需要控制台输出的内容,params[0] 代表第一个参数,如果参数有多个,只要 params 加上下标即可,returnObj 代表返回值,示意代码如下:
watch com.cctest.arthas_demo.controller.StressSceneController login "{params[0],params[1],returnObj}"
输入上述命令后的返回信息如下:
4、使用tt命令定位异常调用
tt 与上面的 watch 的命令有些类似,都可以排查函数的调用情况。但是对于函数调用 n 次中有几次是异常情况,用 watch 就没有那么方便,使用 tt 命令就可以很方便地查看异常的调用及其信息。
tt -t com.cctest.arthas_demo.controller.StressSceneController login
四、通过Web界面操作Arthas
Arthas 提供了客户端访问程序 Arthas Tunnel Server,这样我们便可以操作 Arthas 了。
1、下载
首先,我们需要下载arthas-tunnel-server.jar。
2、部署
把 Arthas Tunnel Server 部署到能和线上服务器通信的目标服务器;
3、启动
确保线上服务器启动了 Arthas,线上启动 Arthas 的操作命令,如下所示:
java -jar arthas-boot.jar --tunnel-server 'ws://目标服务器ip:目标服务器port/ws' --target-ip
4、访问界面
在浏览器中输入 http://目标服务器ip:目标服务器port,就可以访问 WebConsole
5、界面操作与命令行操作有何区别呢?
通过 Web 方式使用 Arthas 与我们上面所说的非 Web 的方式最大的不同:
-
Web 方式可以授权连接之后通过浏览器输入 Arthas 命令;
-
非 Web 方式则是直接 ssh 连接服务器输入命令。
两者比较起来 Web 方式虽然操作麻烦些,不过在权限管控比较严格的情况下提供了使用 Arthas 的可行性。
文章将持续更新,欢迎关注公众号:服务端技术精选。欢迎点赞、关注、转发。