Arthas协助排查问题干货学习

308 阅读5分钟

本文已参与「新人创作礼」活动,一起开启掘金创作之路。

前言

初识Arthas,是为了排查项目的JVM内存溢出问题,后发现在线上排查问题及性能调优时,也有不错的妙用。 虽有官方文档,在这里做下笔记加深使用印象,我这里只介绍相对实用的操作指令

使用经验:

  • jvm 内存占比及回收状态,适当帮助调整JVM参数---- dashboard
  • 当需要加日志排查问题时,线上一般会考虑 watch 或 trace 指令查看方法的入参和出参协助排查是否业务方问题(敏感日志或方法调用量超大不方面埋点时)
  • 线上主机CPU占比过高问题排查 + 性能调优----火焰图
  • 在不重启应用情况下,手动修改日志打印权限,查看线上执行细节问题 ---- logger
  • 在不重启应用情况下,动态修改线上的代码,并使其生效

安装&启动

  • 安装

    下载包

  • 启动

    java -jar arthas-boot.jar

备注: 需跟微服务进程同一个用户启动,选择需要监控的微服务进程 例如arthas-demo启动使用root用户,则使用root用户启动arthas-boot.jar

image.png

常规操作

常用指令

cls

类似linux的 clear ,清空界面内容

ctrl + c / quit / exit:

退出当前连接,类似 linux的 ctrl + z

ctrl + z / stop

退出arthas操作界面,重回linux界面

tab

补全arthas指令

arthas 进阶

dashboard

主要功能:

看当前活跃线程(ID/GOURP/NAME)cpu 使用占比

查看GC回收次数及jvm内存使用情况

  • ID: Java 级别的线程 ID
  • NAME: 线程名
  • GROUP: 线程组名
  • PRIORITY: 线程优先级, 1~10 之间的数字,越大表示优先级越高
  • STATE: 线程的状态
  • CPU%: 线程的 cpu 使用率。比如采样间隔 1000ms,某个线程的增量 cpu 时间为 100ms,则 cpu 使用率=100/1000=10%
  • DELTA_TIME: 上次采样之后线程运行增量 CPU 时间,数据格式为秒
  • TIME: 线程运行总 CPU 时间,数据格式为分:秒
  • INTERRUPTED: 线程当前的中断位状态
  • DAEMON: 是否是 daemon 线程
  • JVM 内部线程
  • Memory 可查看内存使用状态,Eden区、新生代/老年代 使用内存占比 ,内存回收次数等

image.png

heapdump

功能:jmap中的heap dump功能

例:dump到指定文件:

  • heapdump /opt/hihonor/example.hprof

jvm

功能:查看当前微服务jvm输入参数信息,jvm使用占比,线程总共开启数量,活跃线程数量,类加载数量,是否有死锁线程,jvm最大可以打开的文件描述符数,和当前已打开的描述符数。 个人觉得功能跟dashboard 相似

logger

功能:查看 logback-spring.xml 的日志配置和动态修改日志级别

查看配置

  • logger image.png

修改日志级别

  • logger -c {hashCode} --name {name} --level {level}
  • logger --classLoaderClass {classLoader} --name {name} --level {level}

加载类hash值获取:

  • sc -d className 查看类加载器的hashCode编码(微服务每次启动,hashcode是动态变化的)

      将Mylogger日志级别调成debug ,查看线上更明细日志
      logger --classLoaderClass org.springframework.boot.loader.LaunchedURLClassLoader --name com.example.arthastest.support.Mylogger --level debug
      
      恢复 info 级别
      logger -c 4b9e13df --name com.example.arthastest.support.Mylogger --level info
    

image.png

thread

查看当前最忙的3个线程,并打印出堆栈和CPU占比

  • thread -n 3

笔者demo过于简单,请忽略 image.png

jad

反编译class生成java文件使用,可以验证代码是否成功部署到某个环境 jad一般和mc及retransform搭配使用

  • jad --source-only className
  • jad className image.png

mc

编译java代码使用,如果是编译jad反编译的java代码,切记一定要带 hashcode或类加载器

  • mc -c {hashcode} com.example.arthastest.controller.ArthasController
  • mc --classLoaderClass {ClassLoader} com.example.arthastest.controller.ArthasController

image.png

retransform

重置线上class

动态修改class生效限制

  1. 不允许新增类属性和方法
  2. 方法如果退不出来,即方法内有死循环时,改动不生效(仅限本栈帧的死循环,调用的其他方法不受影响)
  • retransform /opt/myapp/apps/arthas-demo/com/example/arthastest/controller/ArthasController.class

  • retrasform -l 呈现已修改的类信息

  • retransform -d id 还原已修改的类信息,但还要重置retransform才行

       动态修改线上应用字节码文件,并使之生效     
      - jad 命令反编译,然后可以用其它编译器,比如 vim 来修改源码
      - mc 命令来内存编译修改过的代码
      - 用 retransform 命令加载新的字节码
      第一和第二步,可以通过本地上传class文件实现
    

动态修改流程参照截图:

1. jad命令线上生成java代码,一定要携带 --source-only 参数
jad --source-only com.example.arthastest.controller.ArthasController > /opt/myapp/ArthasController.java
2. 第一步修改java源码完成后,重新编译,此时切记带上加载类参数(第一步生成的java代码已有该行,可复制)
mc --classLoaderClass org.springframework.boot.loader.LaunchedURLClassLoader /opt/myapp/ArthasController.java 
3. 重置字节码,使其生效
retransform /opt/myapp/apps/arthas-demo/com/example/arthastest/controller/ArthasController.class

image.png

stack/trace/watch/

三者都和方法调用链相关,放在一起。 watch 命令我个人很喜欢使用,查看线上方法是否生效,是否正常被调用

  • stack :方法是否被执行,被哪个方法执行,打印方法执行的堆栈信息
  • trace :追踪方法调用链,统计整个方法调用链的性能开销 以上指令两者调用相似 stack/trace {className} {methodName}

trace image.png stack image.png

  • watch :查看方法被调用时的入参、出参,是否抛出异常

  • watch {className} {methodName} {params,returnObj} -x 2

    一般我会搭配管道 grep 使用

     入参出参都在 result 参数内,排序 params->target->returnObj ,一般target用不到,
     已过滤。 ognl 条件表达式我很少用,有兴趣的同学可以研究下,可以过滤出我们想要的结果
    

image.png

profiler

生成火焰图,性能调优神器,不用过多介绍了

  • profiler start --开始
  • profiler stop -- 结束,结束后会生成该期间内统计的各方法性能时长火焰图

以上是我个人觉得需要掌握的常用指令,如还有其他实操常用指令,欢迎留言。