Arthas(阿尔萨斯)定位线上问题

编程入门 行业动态 更新时间:2024-10-10 13:13:05

Arthas(<a href=https://www.elefans.com/category/jswz/34/1755944.html style=阿尔萨斯)定位线上问题"/>

Arthas(阿尔萨斯)定位线上问题

Arthas 阿尔萨斯使用

  • 参考
  • 实际使用案例
    • 线上安装与挂载
    • 火焰图
    • 查找类、查看类详细信息与反编译代码
    • 查看类中的所有field值
    • thread的各种操作
    • 查看入参、返回值、异常
    • 线上修改代码:jad/mc/redefine/retransform
    • 性能监控
    • dump
    • 找到异常线程并查看堆栈
    • Mbean
  • 案例总结
    • trace查看耗时进行调优
    • Arthas底层实现
    • WeakHashMap死循环引起CPU跑满
    • JDK函数调用查询与后台脚本打印数据
    • ognl表达式筛选并观察输入输出
    • 查看某个Spring引用的具体实现
    • tt获取Spring容器内的bean
    • list出现环导致死循环引发的CPU负载过高
    • 奇怪日志来源定位

参考

官方文档:/
用户案例:=label%3Auser-case
一图流:
IDE插件官方文档:
一篇很好的总结:=app&app_version=4.13.0&code=app_1562916241&uLinkId=usr1mkqgl919blen

JVM工具专栏:
.html

实际使用案例

基础命令:.html#id2

线上安装与挂载

wget .jar
jps -ml
ps -ef | grep java
java -jar arthas-boot.jar {pid}

火焰图

参考

火焰图基本科普与讲解: .html
定位不同问题的不同类型火焰图 + 安装使用教程:< >
本机可以随意安装火焰图生成工具。用于线上环境时,需要看线上环境用的火焰图生成工具是什么,生成图示之后传到本机进行分析即可。

profiler start
# 一段时间(>30s)后
profiler stop
exit
wget -O /usr/local/bin/toshelper  && chmod +x /usr/local/bin/toshelper
toshelper /tmp/XXX.svg

查找类、查看类详细信息与反编译代码

参考

# 可以找到需要的类全路径
# -d 输出当前类的详细信息:所加载的原始文件来源、类的声明、
# 加载的ClassLoader(可以看出是哪个组件加载的)等详细信息。
sc -d *DispatcharServlet      # 查看某个方法的信息,如果存在的话 ,不加方法的话查看所有方法
sm org.springframework.web.servlet.DispatcherServlet getHandler # 直接反编译出java 源代码,包含类加载器等额外信息
jad package.XXXService.method 




sc -d查看详细类的详细信息

查看类中的所有field值

sc -d -f class

thread的各种操作

=app&app_version=4.13.0&code=app_1562916241&uLinkId=usr1mkqgl919blen
4.2节
查看topn的线程 + 具体线程堆栈 + 查看blocking线程、死锁线程 + 查看线程池等实例。

.html

// 查看所有线程信息
thread
// 查看前N线程
thread -n 3// 查看具体线程
thread id
// 找出当前阻塞其他线程的线程
thread -b
// 查看指定状态的线程
thread --state WAITING

查看入参、返回值、异常

.html
支持复杂的设定

# 同时监控入参,返回值,及异常。如果有异常,直接打印出来
watch package.testMethod "{params, returnObj, throwExp}" -e -x 2  

几个watch结合ognl的实例

# 观察CommonTest的test方法
# 输出 入参、返回结果、抛出的异常 —— 输出的内容可以动态调整
# 后面跟着的是 条件表达式,表示耗时超过10ms才输出
# -n 表示只执行一次,-x表示 入参和返回结果的展开层次为5层
watch *.CommonTest test "{params,returnObj,throwExp}" '#cost>10' -x 5 -n 1# 耗时大于10ms并且第一个参数等于1才输出
watch *.CommonTest test "{params,returnObj,throwExp}" '#cost>10 && params[0]==1' -x 5 -n 1# 第一个参数大于1 并且第二个参数等于hello才输出
watch *.CommonTest test "{params,returnObj,throwExp}" 'params[0]>1 && params[1]=="hello"' -x 5 -n 1
# 第一个参数小于5或者第二个参数等于"world"就输出
watch *.CommonTest test "{params,returnObj,throwExp}" 'params[0]<5 || params[1]=="wolrd"' -x 5 -n 1
# 第一个参数的name字段等于world时才输出。
# 由于在方法执行过程中参数的name属性可能发生改变,因此加上-b才能观察到真正的入参
watch -b *.CommonTest test "{params,returnObj,throwExp}" 'params[0].name=="wolrd"' -x 5 -n 1# 由于同时指定了-s和-b,所以方法被调用一次,就会输出2次结果(两个场景分开输出),分别是方法被调用前,和返回之后
# 注意,这里如果-n只设置成1,那么只会输出-b对应的输出,-s对应的输出由于没有次数了就无法输出了
watch *.CommonTest test '{params,returnObj,throwExp}' -x 5 -n 2 -s -b

线上修改代码:jad/mc/redefine/retransform

整体而言,还是使用Spring提供的hot swap更为合适。

Arthas:
jad命令:.html
mc命令:.html
redefine命令:.html
retransform:.html

# 先反编译出class源码
jad --source-only com.example.demo.arthas.user.UserController > /tmp/UserController.java  # 然后使用外部工具编辑内容
vim /tmp/UserController.java# 查找加载UserController的ClassLoader
sc -d *UserController | grep classLoaderHash#output : classLoaderHash   1be6f5c3# 再编译成class,只需指明目录即可# 有时候mc命令不一定成功,尤其是很复杂的类有着各种注入各种依赖。
mc -c 1be6f5c3 /tmp/UserController.java -d /tmp # 最后,重新载入定义的类
redefine /tmp/com/example/demo/arthas/user/UserController.class
retransform /tmp/Test.class

更好的做法:
直接在IDE上完成class的编辑,然后去生产环境中将代码拷贝进去,运行redefine命令即可。

注意:

  1. redefine的class不能修改、添加、删除类的field和method,包括方法参数、方法名称及返回值
  2. 如果mc失败,可以在本地开发环境编译好class文件,上传到目标系统,使用redefine热加载class
  3. 目前redefine 和watch/trace/jad/tt等命令冲突,
  4. redefine后的原来的类不能恢复,redefine有可能失败

retransform直接替换jvm里已经加载的class方法。好处是可以恢复。
上传 .class 文件到服务器的技巧

性能监控

monitor:方法执行结果监控,统计重要信息。.html

$ monitor -c 5 demo.MathGame primeFactors
Press Ctrl+C to abort.
Affect(class-cnt:1 , method-cnt:1) cost in 94 ms.timestamp            class          method        total  success  fail  avg-rt(ms)  fail-rate
-----------------------------------------------------------------------------------------------2018-12-03 19:06:38  demo.MathGame  primeFactors  5      1        4     1.15        80.00%timestamp            class          method        total  success  fail  avg-rt(ms)  fail-rate
-----------------------------------------------------------------------------------------------2018-12-03 19:06:43  demo.MathGame  primeFactors  5      3        2     42.29       40.00%timestamp            class          method        total  success  fail  avg-rt(ms)  fail-rate
-----------------------------------------------------------------------------------------------2018-12-03 19:06:48  demo.MathGame  primeFactors  5      3        2     67.92       40.00%timestamp            class          method        total  success  fail  avg-rt(ms)  fail-rate
-----------------------------------------------------------------------------------------------2018-12-03 19:06:53  demo.MathGame  primeFactors  5      2        3     0.25        60.00%timestamp            class          method        total  success  fail  avg-rt(ms)  fail-rate
-----------------------------------------------------------------------------------------------2018-12-03 19:06:58  demo.MathGame  primeFactors  1      1        0     0.45        0.00%timestamp            class          method        total  success  fail  avg-rt(ms)  fail-rate
-----------------------------------------------------------------------------------------------2018-12-03 19:07:03  demo.MathGame  primeFactors  2      2        0     3182.72     0.00%

tt:时空隧道,记录了过程中的快照,方便Arthas内部线程重新发起一次调用。.html

// 留下快照
$ tt -lINDEX   TIMESTAMP            COST(ms)  IS-RET  IS-EXP   OBJECT         CLASS                          METHOD
-------------------------------------------------------------------------------------------------------------------------------------1000    2018-12-04 11:15:38  1.096236  false   true     0x4b67cf4d     MathGame                       primeFactors1001    2018-12-04 11:15:39  0.191848  false   true     0x4b67cf4d     MathGame                       primeFactors1002    2018-12-04 11:15:40  0.069523  false   true     0x4b67cf4d     MathGame                       primeFactors1003    2018-12-04 11:15:41  0.186073  false   true     0x4b67cf4d     MathGame                       primeFactors1004    2018-12-04 11:15:42  17.76437  true    false    0x4b67cf4d     MathGame                       primeFactors91005    2018-12-04 11:15:43  0.4776    false   true     0x4b67cf4d     MathGame                       primeFactors
Affect(row-cnt:6) cost in 4 ms.
// 详细信息查询
$ tt -i 1003INDEX            1003GMT-CREATE       2018-12-04 11:15:41COST(ms)         0.186073OBJECT           0x4b67cf4dCLASS            demo.MathGameMETHOD           primeFactorsIS-RETURN        falseIS-EXCEPTION     truePARAMETERS[0]    @Integer[-564322413]THROW-EXCEPTION  java.lang.IllegalArgumentException: number is: -564322413, need >= 2at demo.MathGame.primeFactors(MathGame.java:46)at demo.MathGame.run(MathGame.java:24)at demo.MathGame.main(MathGame.java:16)Affect(row-cnt:1) cost in 11 ms.

发起执行

[arthas@10718]$ tt -t demo.MathGame run -n 5
Press Q or Ctrl+C to abort.
Affect(class count: 1 , method count: 1) cost in 56 ms, listenerId: 1INDEX      TIMESTAMP                   COST(ms)     IS-RET     IS-EXP      OBJECT              CLASS                                     METHOD
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------1000       2021-01-08 21:54:17         0.901091     true       false       0x7699a589          MathGame                                  run
[arthas@10718]$ tt -w '@demo.MathGame@random.nextInt(100)'  -x 1 -i 1000
@Integer[46]

trace:单纯时间统计.html

# 输出方法内部调用路径,并输出方法路径上的每个节点上耗时,根据耗时进行过滤
trace demo.MathGame run '#cost > 10' 

dump

dump:dump 已加载类的 bytecode 到特定目录. .html
heapdump:dump java heap, 类似jmap命令的heap dump功能。.html

heapdump --live /tmp/jvm.hprof# 之后使用tos回传
wget -O /usr/local/bin/toshelper  && chmod +x /usr/local/bin/toshelper
toshelper /opt/tiger/multi-tenant-custom-entity/multi-tenant-custom-entity-cos-web/arthas-output/20210720-102201.svg

找到异常线程并查看堆栈

thread命令参看文章前半截

方法一:
# 查找进程
top
# 查看进程线程
top -Hp 进程号
#或者也可以采用下面2种ps命令来查看繁忙的线程信息
ps -mp pid -o THREAD,tid,time
ps -Lfp pid 
# 16进制线程号
printf "%x\n" 目标线程号 
# jstack查看线程堆栈,jstack会打印出所有线程堆栈
jstack 进程号 | grep 线程ID方法二:
# show busy threads的方法:直接打印出异常线程堆栈
wget --no-check-certificate .x/bin/show-busy-java-threads
chmod +x show-busy-java-threads./show-busy-java-threads方法三:
# Arthas方法,查找cpu占用量最高的线程
thread -n 10
# 查看堆栈
thread pid方法四:
# jstack 、top的文件也可以使用这个网站来分析
.jsp

Mbean

命令介绍:.html
什么是Mbean与jmx:


一种JVM运行时的监控框架。

案例总结

=1&q=label%3Auser-case

trace查看耗时进行调优


使用trace查看调用链路,从中分析耗时严重的函数。

Arthas底层实现

ByteKit解读:

WeakHashMap死循环引起CPU跑满

thread + sc的应用
1,异常线程堆栈章节查到线程并且发现是weakHashMap的get方法出了问题
2,sc -d 从code-source中查看jar包,发现这个jar包里用到的是线程不安全版本的weakHashMap,遂破案。

JDK函数调用查询与后台脚本打印数据

案例:System.gc查找

stack:.html

实时观察版本:

# Arthas默认关闭了对JDK类的自带类的增强,需要通过options命令打开。
options unsafe true 
# stack命令:输出当前方法被调用的调用路径,实时观察谁调用了java.lang.System#gc,等待触发
# 实际上是不带每一步调用时间信息的trace版本
stack java.lang.System gc

后台打印版本

# 编辑脚本
cat system_gc.as# 脚本内容
options unsafe true
# 务必注意这里的-n,表示这个命令只执行一次,然后退出。如果不指定,Arthas 2.0会一直卡在那里,永远不退出,Arthas 3.0默认执行100次才会退出。在写批处理脚本的时候,请务必加上-n参数。
stack java.lang.System gc -n 1# 后台执行脚本1
./as.sh -b -f system_gc.as 59863 > system_gc.out 2>&1 &
# 后台执行脚本2,这种方式能够避免session因为连接超时中断的同时导致该脚本中断
nohup ./as.sh -b -f system_gc.as 59863 > system_gc.out 2>&1 &
# 后代执行脚本3,使用screen避免脚本中断
sudo yum install -b current screen
screen
./as.sh -b -f system_gc.as 59863 > system_gc.out 2>&1
# 即便网络断掉也没有问题。过一段时间之后,要查看之前的结果。如果连接断掉了,只需要输入以下命令
screen -r#过段时间观察即可
cat system_gc.out

ognl表达式筛选并观察输入输出

ognl表达式:
一些例子:

# 打印线上某个容器的size
ognl '@xxxmon.redis.collections.UniqConcurrentSet@INSTANCE.dataIsNullSet.size()
# 在内部类某个方法中查看外部类容器大小
# 
watch sun.httpserver.ServerImpl$ServerTimerTask1 run -f "target.this$0.allConnections.size()

查看某个Spring引用的具体实现

日志打满问题解决:

# -d显示详细信息
sc -d *LarkService*
# 查看具体实现类
getstatic -c 73ad2d6 ioty.channel.nio.NioEventLoop logger 'getClass().getName()'
getstatic -c 73ad2d6 ioty.channel.nio.NioEventLoop logger 'logger'
getstatic -c 73ad2d6 ioty.channel.nio.NioEventLoop logger 'logger.getClass().getProtectionDomain().getCodeSource().getLocation()'
field: logger
# 查询其基类的积累的logger实现
getstatic -c 73ad2d6 ioty.channel.nio.NioEventLoop logger 'logger.parent.parent.parent.parent.parent'
field: logger

tt获取Spring容器内的bean


时空隧道中能抓取到bean的调用
实际上用的就是idea插件生成的ognl语句。

list出现环导致死循环引发的CPU负载过高

thread
thread pid# 查看方法调用情况
tt -t com.googlemon.collect.HashBiMap seekByKey -n 100# SpringMVC应用,所有请求都会被RequestMappingHandlerAdapter拦截,我们通过tt命令,监听invokeHandlerMethod的执行,然后在页面随便点点,就会得到以下内容
[arthas@384]$ tt -t org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter invokeHandlerMethod -n 10
Press Q or Ctrl+C to abort.
Affect(class-cnt:1 , method-cnt:1) cost in 622 ms.INDEX	COST(ms)  	OBJECT    	CLASS             METHOD                                             
------------------------------------------------------------------------------------1000 	481.203383	0x481eb705	RequestMappingHandlerAdapter    invokeHandlerMethod                                1001 	3.432024  	0x481eb705	RequestMappingHandlerAdapter	invokeHandlerMethod                               
...
# tt 命令会记录方法调用时的所有入参和返回值、抛出的异常、对象本身等数据。通过 -i 参数后边跟着对应的 INDEX 编号查看这条记录的详细信息。再通过-w参数,指定一个OGNL表达式,查找相关对象
# Arthas会把当前执行的对象放到target变量中,通过target.getApplicationContext()就得到了SpringContext对象,这里同上一节内容
# OGNL写一个函数,来实现链表的环路检测,在OGNL里写一段环路检测代码里是不太容易的,一个bucket不太可能有50个以上的节点,所以就通过遍历次数是否大于50来判断是否有环路。
tt -i 1000 -w 'target.getApplicationContext().getBean("oaInfoManager").userCache.entrySet().{delegate}.{^ #loopCnt = 0,#foundCycle = :[ #this == null ? false : #loopCnt > 50 ? true : (#loopCnt = #loopCnt + 1, #foundCycle(#this.nextInKToVBucket))], #foundCycle(#this)}.get(0)' -x 2

奇怪日志来源定位


实际上是通过重写StringBuilder代码来定位某个奇怪日志的stack
使用到的技术:
redefine

更多推荐

Arthas(阿尔萨斯)定位线上问题

本文发布于:2024-02-07 09:51:03,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1755268.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:阿尔萨斯   线上   Arthas

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!