Hello Arthas | 8月更文挑战

223 阅读5分钟

image.png

这是我参与8月更文挑战的第7天,活动详情查看:8月更文挑战

从一个问题开始

当前服务响应情况很慢,它在干什么?是不是哪个线程占用的CPU高?

  1. 机器监控——恰好并没有线程占用cpu的维度
  2. top -Hp pid,找到操作系统里线程占用最多的线程id printf ‘%x\n’ threadId,将查到的十进制数字转为十六进制 jstack pid | grep threadId,终于找到哪个线程占用cpu高了 有了Arthas以后呢? 提示:以下是本篇文章正文内容,下面案例可供参考

Arthas是什么?

Arthas 是Alibaba开源的Java诊断工具。 研发最发愁的就是生产环境发生了问题,但是完全不知道程序的问题在哪里;测试环境又没发生类似问题,看日志也看不出来问题。Arthas就是为了在线排查问题,无需重启;动态跟踪Java代码;实时监控JVM状态,是程序员观察程序的一扇大门,给予程序员实时排查问题的能力。 为什么它能够无需重启实时去排查问题呢?Java自1.5开始增加了instrument包,它提供了两个入口:agentmain和premain。1.6时代又增加了运行期attach的能力。Arthas就是通过这个技术,在前置方法里对字节码进行修改,来增强代码的行为。 那在instrument的加持下,它还能解决什么问题?

执行dashboard命令

image.png

使用thread命令

image.png -b可以查看被锁阻塞的线程 -n 是显示数量,按照cpu使用率排序

image.png

image.png

再来看一个问题

我改了一些代码,为什么部署以后没有执行到?难道是我没 commit?分支搞错了?

  1. 加日志,重新发布上线看日志——通常得改代码,发布,等待部署,查明日志里体现的问题,修复bug重新上线。
  2. 到webapps目录下查找对应的class或者jar包,下载到本地用jad软件打开查看

使用jad

反编译指定已加载类的源码 jad com.facishare.paas.foundation.boot.Injector

还能再给力一点吗?

程序里的静态变量,执行的时候发现似乎不是预期,怎么查呢? getstatic

image.png

还能再给力一点吗? 比如某个接口的请求非常慢,它慢在哪里?

使用trace

用来查看单次调用链路上的耗时

  • trace –n 10 org.apache.commons.lang.StringUtils isBlank

命令 | 10次 | 类名 | 方法 trace *StringUtils isBlank

命令 | 类名通配符| 方法名 trace -E com.ClassA|org.ClassB method1|method2|method3

命令 | 正则| 类名正则匹配 | 方法名的正则匹配 trace技术基于字节码技术,因此不可避免的增加了链路每一个节点的耗时。所以不要在生产一直开着trace,也不要直接把trace跟压测的耗时数据做对比。

image.png 还能再给力一点吗? 用户数据的处理结果不符合预期,那么关键函数入参返回值都是什么呢?

tt

对于一个最基本的使用来说,就是记录下当前方法的每次调用环境现场。 有问题的时候记录下当时方法调用的所有入参和返回值、抛出的异常,那排查问题就可以有的放矢了

image.png

但是很多框架偷偷的将一些环境变量信息塞到了发起调用线程的 ThreadLocal 中,由于调用线程发生了变化,这些 ThreadLocal 线程信息无法通过 Arthas 保存,所以这些信息将会丢失。

tt 命令是将当前环境的对象引用保存起来,但仅仅也只能保存一个引用而已。如果方法内部对入参进行了变更,或者返回的对象经过了后续的处理,那么在 tt 查看的时候将无法看到当时最准确的值。 所以我们主要推荐大家用的是watch命令

-watch

让你能方便的观察到指定方法的调用情况。能观察到的范围为:返回值returnObj,抛出异常throwExp,入参params,ognl表达式里还可以使用对象target,耗时cost

watch -n 1 com.facishare.social.abs.AbstractStandardSocialService batchObject2Feed "{params,returnObj}" '#cost>200' -x 2

命令 | 普通参数 | 类名 | 方法名 | ognl表达式 | 条件,可选 | 还可以继续加普通参数 一般命令都支持-n,表示执行几次,避免匹配到一个热点函数,导致屏幕不断刷屏,停都停不下来 一般能够输出对象信息的命令都支持-x,表示显示对象的层级。

watch还支持-e,表示匹配抛出异常的情况

image.png 还能再给力一点吗? 大家怎么观察应用现在CPU热点在哪里了呢?

使用profiler/火焰图

profiler–使用async-profiler对应用采样,生成火焰图

profiler start -d 300

image.png

image.png

还能再给力一点吗? 在Arthas里使用ognl表达式

ognl基础

官方入门:commons.apache.org/proper/comm… 表达式是按照当前对象进行解析的,有几种使用方式:

  1. 访问属性,比如name或者name.text
  2. 调用方法,比如hashCode()
  3. 数组访问,比如listeners[0]

Arthas这么好用,那我们就用起来吧!

注意! Arthas对类的增强基于字节码技术,增强类的时候也就意味着JIT编译缓存失效了,性能会下降。 对Java自己的类做增强,可能会搞挂JVM,比如toString的增强里里调用了toString。 trace 能方便的帮助你定位和发现因响应时间高所含有的性能问题缺陷,但其每次最好只跟踪某个方法的调用链路,因为同时Trace的越多,性能影响越大。 接口调用太频繁会记录过多的数据变量到内存里,比如tt指令,建议加 -n 参数 限制输出次数。 命令的输出太多,屏幕一直处于刷屏状态,无法终止当前的命令,最终影响服务的性能。 支持正则的命令里, * 通配符的使用不当,范围过大。 使用异步任务时,请勿同时开启过多的后台异步命令,以免对目标JVM性能造成影响。 使用后最好使用stop关闭监听服务的Arthas service,恢复被增强的类。