一次线上问题的综合排查排查,两个相同的系统的某个模块,数据量更少的系统查询更慢。
先说下总体思路:java
这样看起来arthas真的很强大,它不只仅能处理上述问题,还能....mysql
Arthas 是Alibaba开源的Java诊断工具,采用命令行交互模式,提供了丰富的功能,是排查jvm相关问题的利器。
在逛github时,发现了这款利器,深刻了解以后,简直惊为天人。下面先列举一下它能作的一些事情:git
进入当前系统的实时数据面板,按 ctrl+c 退出。这个面板会实时刷新,其中包括线程信息、内存信息、gc信息、还有一些运行时的数据。
另外,当运行在Ali-tomcat时,会显示当前tomcat的实时信息,如HTTP请求的qps, rt, 错误数, 线程池信息等等。github
经过thread命令能够查看当前jvm进程的线程详情。能够查看线程的cpu使用时间占比,经过指定各类参数能够找出最忙的几个线程,以及阻塞其余线程的线程。具体如何使用这里很少作介绍,你们能够去看arthas的官方文档。正则表达式
当前最忙的前N个线程并打印堆栈 thread -i 5000 thread -i 5000
经过jvm命令直接输出当前jvm的各类信息。算法
经过getstatic命令能够方便的查看类的静态属性。sql
getstatic demo.MahtGame random
执行ognl表达式,可执行任意代码express
Ognl @demo.MathGame@random
动态修改日志级别apache
更详细的介绍:https://github.com/alibaba/arthas/issues/11vim
将已加载类的字节码dump到本地磁盘上。
有时咱们常常会不肯定线上或者测试环境的包是不是咱们修改过的,这时候就能够经过jad反编译来看下。
反编译指定已加载类的源码,jad demo.MathGame
将 JVM 中全部的classloader的信息统计出来,并能够展现继承树,urls等。
该命令能够加载外部的.class文件,而后覆盖 jvm已加载的类。注意,这个命令不必定都能覆盖成功,若是添加了新的field,就不会加载成功。
关于redefine,arthas的github上有个很是经典的userCase:
https://github.com/alibaba/arthas/issues/263
动态更新代码,不用重启jvm
参数名称 | 参数说明 |
---|---|
class-pattern | 类名表达式匹配 |
method-pattern | 方法名表达式匹配 |
express | 观察表达式 |
condition-express | 条件表达式 |
[b] | 在方法调用以前观察 |
[e] | 在方法异常以后观察 |
[s] | 在方法返回以后观察 |
[f] | 在方法结束以后(正常返回和异常返回)观察 |
[E] | 开启正则表达式匹配,默认为通配符匹配 |
[x:] | 指定输出结果的属性遍历深度,默认为 1 |
[n:] | 只执行n次,默认会不断输出,除非用户按下cltr+c |
# 观察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
在填写条件表达式时要注意一点,条件表达式中的params默认都是获取的方法执行完后的参数信息,好比入参a的属性name方法执行前是"hello",在方法执行后变成了"world",那么条件表达式传入'params[0].name="hello"'将不会输出,只有填入'params[0].name="hello"'才能够匹配上。这点对于后面的trace、stack命令也是同样的。
查看方法输入参数/返回值/异常信息,watch demo.MathGame primeFactors "{params,returnObj}" -x 2
monitor命令能够监控方法的执行状况。好比调用成功次数,失败次数,失败率、平均执行时间等等。默认120秒输出一次,也就是说,当咱们输入monitor命令以后,每120秒就会输出一次统计结果。
经过-c参数能够修改输出频率,支持通配符和正则表达式。
monitor -c 5 demo.MathGame primeFactors
方法内部调用路径,并输出方法路径上的每一个节点上耗时,tt命令会记录每次方法调用的各类信息。它和watch有些类似可是它能记录下各个时间点的调用信息,以后随时查看,甚至replay此次调用。
trace demo.MathGame run
timetunnel,记录下指定方法每次调用的入参和返回信息,并能对这些不一样的时间下调用进行观测,同时可回放该方法调用
tt -t demo.MathGame primeFactors
直接重放请求参数
1.使用tt –t 类名次 方法名次 2.tt –play -i 1000
另外介绍几个我常常用的工具,jmap,jstat,jstack,dump这些基本的就不介绍了。
TProfiler是一个能够在生产环境长期使用的性能分析工具.它同时支持剖析和采样两种方式,记录方法执行的时间和次数,生成方法热点 对象建立热点 线程状态分析等数据,为查找系统性能瓶颈提供数据支持.
TProfiler在JVM启动时把时间采集程序注入到字节码中,整个过程无需修改应用源码.运行时会把数据写到日志文件,通常状况下每小时输出的日志小于50M.
参考:https://blog.csdn.net/u013332124/article/details/84888074#11_redefine_157