首页 > 编程学习 > 2021-04-03--Arthas

2021-04-03--Arthas

发布时间:2022/5/14 15:35:12

Arthas工具介绍以及常用方法

目录

文章目录

从一个问题开始

Arthas是什么?

执行dashboard命令

使用thread命令

再来看一个问题

使用jad

还能再给力一点吗?

getstatic

还能再给力一点吗?

使用trace

还能再给力一点吗?

tt

watch

还能再给力一点吗?

使用profiler/火焰图

​还能再给力一点吗?

ognl基础

一般成员变量和函数调用

​获取SpringContext的通用办法

Arthas都有哪些命令?

太复杂了,我怎么才能快速上手?

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

注意!

  •  

 


从一个问题开始

  • 当前服务响应情况很慢,它在干什么?是不是哪个线程占用的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命令

使用thread命令

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

 

再来看一个问题

  • 我改了一些代码,为什么部署以后没有执行到?难道是我没 commit?分支搞错了?
  • 1. 加日志,重新发布上线看日志——通常得改代码,发布,等待部署,查明日志里体现的问题,修复bug重新上线。
  • 2. 到webapps目录下查找对应的class或者jar包,下载到本地用jad软件打开查看

使用jad

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

还能再给力一点吗?

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

getstatic

还能再给力一点吗?

  • 比如某个接口的请求非常慢,它慢在哪里?

使用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跟压测的耗时数据做对比。

还能再给力一点吗?

  • 用户数据的处理结果不符合预期,那么关键函数入参返回值都是什么呢?

tt

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

  • 但是很多框架偷偷的将一些环境变量信息塞到了发起调用线程的 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,表示匹配抛出异常的情况

 

还能再给力一点吗?

  • 大家怎么观察应用现在CPU热点在哪里了呢?

使用profiler/火焰图

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

参数名称

参数说明

action

要执行的操作,如start stop

actionArg

属性名模式

[i:]

采样间隔(单位:ns)(默认值:10'000'000,即10 ms

[f:]

将输出转储到指定路径

[d:]

运行评测指定秒

[e:]

要跟踪哪个事件(cpu, alloc, lock, cache-misses等),默认是cpu

还能再给力一点吗?

  • 在Arthas里使用ognl表达式

ognl基础

  • 官方入门:https://commons.apache.org/proper/commons-ognl/language-guide.html
  • 表达式是按照当前对象进行解析的,有几种使用方式:
    1. 访问属性,比如name或者name.text
    2. 调用方法,比如hashCode()
    3. 数组访问,比如listeners[0]
  • 支持变量,比如#var,#this
  • 点号右可以用括号包含起来,表示一起被调用headline.parent.(ensureLoaded(), name)= (headline.parent.ensureLoaded(), headline.parent.name),返回值以最右一个为准。这与C语言的逗号表达式一致
  • 数组: { null,“Untitled” } 字典:#{ “foo” : “foo value”, “bar” : “bar value” }或者#@java.util.LinkedHashMap@{ "foo" : "foo value", "bar" : "bar value" }

一般成员变量和函数调用

  • 先找到类加载器的hash值:sc -d com.facishare.paas.foundation.boot.Injector
  • 再访问某个成员变量:ognl -c 60e52a73 "@com.facishare.paas.foundation.boot.Injector@inner.id"
  • 其实我们已经拿到了ApplicationContext,已经可以获取bean并访问其字段了,比如ognl -c 54e871fe '@com.facishare.paas.foundation.boot.Injector@inner.getBean("serviceFacade")'.getVersion("74114")

获取SpringContext的通用办法

  • watch -x 3 -n 1 org.springframework.web.servlet.DispatcherServlet doDispatch '#springContext=@org.springframework.web.context.support.WebApplicationContextUtils@getWebApplicationContext(params[0].getServletContext()),#springContext.getBean("okHttpSupport").getString("http://www.baidu.com")'

Arthas都有哪些命令?

  • help——查看命令帮助信息
  • cat——打印文件内容,和linux里的cat命令类似
  • echo–打印参数,和linux里的echo命令类似
  • grep——匹配查找,和linux里的grep命令类似
  • base64——base64编码转换,和linux里的base64命令类似
  • tee——复制标准输入到标准输出和指定的文件,和linux里的tee命令类似
  • pwd——返回当前的工作目录,和linux命令类似
  • cls——清空当前屏幕区域
  • session——查看当前会话的信息
  • reset——重置增强类,将被 Arthas 增强过的类全部还原,Arthas 服务端关闭时会重置所有增强过的类
  • version——输出当前目标 Java 进程所加载的 Arthas 版本号
  • history——打印命令历史
  • quit——退出当前 Arthas 客户端,其他 Arthas 客户端不受影响
  • stop——关闭 Arthas 服务端,所有 Arthas 客户端全部退出
  • keymap——Arthas快捷键列表及自定义快捷键
  • dashboard——当前系统的实时数据面板
  • thread——查看当前 JVM 的线程堆栈信息
  • jvm——查看当前 JVM 的信息
  • sysprop——查看和修改JVM的系统属性
  • sysenv——查看JVM的环境变量
  • vmoption——查看和修改JVM里诊断相关的option
  • perfcounter——查看当前 JVM 的Perf Counter信息
  • logger——查看和修改logger
  • getstatic——查看类的静态属性
  • ognl——执行ognl表达式
  • mbean——查看 Mbean 的信息
  • heapdump——dump java heap, 类似jmap命令的heap dump功能
  • sc——查看JVM已加载的类信息
  • sm——查看已加载类的方法信息
  • jad——反编译指定已加载类的源码
  • mc——内存编译器,内存编译.java文件为.class文件
  • retransform——加载外部的.class文件,retransform到JVM里
  • redefine——加载外部的.class文件,redefine到JVM里
  • dump——dump 已加载类的 byte code 到特定目录
  • classloader——查看classloader的继承树,urls,类加载信息,使用classloader去getResource
  • monitor——方法执行监控
  • watch——方法执行数据观测
  • trace——方法内部调用路径,并输出方法路径上的每个节点上耗时
  • stack——输出当前方法被调用的调用路径
  • tt——方法执行数据的时空隧道,记录下指定方法每次调用的入参和返回信息,并能对这些不同的时间下调用进行观测

太复杂了,我怎么才能快速上手?

  • Arthas idea plugin

 

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

 

注意!

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

 

 

 

 


Copyright © 2010-2022 ngui.cc 版权所有 |关于我们| 联系方式| 豫B2-20100000