Java线上监控诊断产品Arthas(续集)

前言

在去年,我发表了一片文章,Java线上监控诊断产品Arthas,今年又重新回顾了一下这门技术,发现了以前忽略了很多技术点,这篇文章用来作补充,并且思考了一下这些技术点可以用来哪些场景。

1.auth指令

在 attach 时,可以在命令行指定密码。比如:

java -jar arthas-boot.jar --password admin
  • 可以通过 --username 选项来指定用户,默认值是arthas。
  • 也可以在 arthas.properties 里中配置 username/password。命令行的优先级大于配置文件。
  • 如果只配置username,没有配置password,则会生成随机密码,打印在~/logs/arthas/arthas.log中

本地连接不鉴权
为了方便本地开发和调试,Arthas 默认允许本地连接不进行鉴权。,在arthas.properties文件里有配置:

arthas.localConnectionNonAuth=true

这样,即使设置了密码,本地连接也无需进行认证。
telnet链接鉴权
远程连接后,需要输入auth指令,输入正确密码,这样才能执行arthas的命令。

[arthas@37430]$ auth admin
Authentication result: true

不然会提示:

Error! command not permitted, try to use 'auth' command to authenticates.

2.monitor指令

案例一:最简单的应用,-c参数:统计周期,默认为120秒,我这5秒一次

monitor -c 5 com.example.demo.controller.ArthasController test

输入之后界面这样,没有任何输出:

[arthas@2719]$ monitor -c 5 com.example.demo.controller.ArthasController test
Press Q or Ctrl+C to abort.
Affect(class count: 1 , method count: 1) cost in 220 ms, listenerId: 2

然后我在浏览器疯狂请求这个接口几次,看看输出:

 timestamp                            class                                                  method                                                  total             success            fail              avg-rt(ms)         fail-rate        
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
 2024-08-26 14:54:40                  com.example.demo.controller.ArthasController           test                                                    1                 1                  0                 5.53               0.00%            

 timestamp                            class                                                  method                                                  total             success            fail              avg-rt(ms)         fail-rate        
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
 2024-08-26 14:54:45                  com.example.demo.controller.ArthasController           test                                                    6                 6                  0                 1.91               0.00%            

 timestamp                            class                                                  method                                                  total             success            fail              avg-rt(ms)         fail-rate        
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
 2024-08-26 14:54:47                  com.example.demo.controller.ArthasController           test                                                    9                 9                  0                 0.13               0.00%            

 timestamp                            class                                                  method                                                  total             success            fail              avg-rt(ms)         fail-rate        
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
 2024-08-26 14:54:55                  com.example.demo.controller.ArthasController           test                                                    0                 0                  0                 0.00               0.00%        

案例二:
此指令还支持条件匹配式,我这里举个最简单的例子:
“params[0]<=2”,表示接口的第一个参数必须<=2

monitor -c 5 com.example.demo.controller.ArthasController test "params[0]<=2"

经过测试,我参数传2的时候,可以检测到,当我参数num传3的时候,就检测不到:
接口:http://172.16.72.132:8081/arthast/inputNum?num=3

timestamp                            class                                                  method                                                  total             success            fail              avg-rt(ms)         fail-rate        
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
 2024-08-26 14:59:31                  com.example.demo.controller.ArthasController           test                                                    1                 1                  0                 0.21               0.00%            

 timestamp                            class                                                  method                                                  total             success            fail              avg-rt(ms)         fail-rate        
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
 2024-08-26 14:59:41                  com.example.demo.controller.ArthasController           test                                                    0                 0                  0                 0.00               0.00%          

解读

1.由上面的场景可以看出来,这个指令可以监控一个方法,在一定时间(-c控制)里被请求了多少次,可以用来压测、或者是热点接口监控,可以显示成功和失败率,并且可以显示平均 RT。
2.指令的条件匹配式,还可以帮助我们筛选想要的请求进来统计。

3.classloader指令

查看 classloader 的继承树,urls,类加载信息

  • classloader -l 按类加载实例进行统计

    [arthas@2719]$ classloader -l
     name                                                            loadedCount  hash      parent                                                                                                                                                  
     BootstrapClassLoader                                            4393         null      null                                                                                                                                                    
     com.taobao.arthas.agent.ArthasClassloader@dfd4a07               1702         dfd4a07   jdk.internal.loader.ClassLoaders$PlatformClassLoader@71423665                                                                                           
     jdk.internal.loader.ClassLoaders$AppClassLoader@5c29bfd         47           5c29bfd   jdk.internal.loader.ClassLoaders$PlatformClassLoader@71423665                                                                                           
     jdk.internal.loader.ClassLoaders$PlatformClassLoader@71423665   115          71423665  null                                                                                                                                                    
     org.springframework.boot.loader.LaunchedURLClassLoader@9629756  10082        9629756   jdk.internal.loader.ClassLoaders$AppClassLoader@5c29bfd                                                                                                 
    Affect(row-cnt:5) cost in 11 ms.
    
  • classloader -t 打印所有 ClassLoader 的继承树

    [arthas@2719]$ classloader -t
    +-BootstrapClassLoader                                                                                                                                                                                                                          
    +-jdk.internal.loader.ClassLoaders$PlatformClassLoader@71423665                                                                                                                                                                                 
      +-com.taobao.arthas.agent.ArthasClassloader@dfd4a07                                                                                                                                                                                           
      +-jdk.internal.loader.ClassLoaders$AppClassLoader@5c29bfd                                                                                                                                                                                     
        +-org.springframework.boot.loader.LaunchedURLClassLoader@9629756                                                                                                                                                                            
    Affect(row-cnt:5) cost in 11 ms.
    

注意:上面打印出来的信息,尾部有@9629756 这种编号,这是类加载器的HashCode值,后面我们如果要指定类加载器,参数跟的就是这一串HashCode

  • classloader -c 显示类加载器位置,配合load参数,可以指定用某个类加载器去加载某个类。
[arthas@2719]$ classloader -c 9629756 --load com.example.demo.controller.FileController
load class success.
 class-info        com.example.demo.controller.FileController                                                                                                                                                                                   
 code-source       file:/data/demo-0.0.1-SNAPSHOT.jar!/BOOT-INF/classes!/                                                                                                                                                                       
 name              com.example.demo.controller.FileController                                                                                                                                                                                   
 isInterface       false                                                                                                                                                                                                                        
 isAnnotation      false                                                                                                                                                                                                                        
 isEnum            false                                                                                                                                                                                                                        
 isAnonymousClass  false                                                                                                                                                                                                                        
 isArray           false                                                                                                                                                                                                                        
 isLocalClass      false                                                                                                                                                                                                                        
 isMemberClass     false                                                                                                                                                                                                                        
 isPrimitive       false                                                                                                                                                                                                                        
 isSynthetic       false                                                                                                                                                                                                                        
 simple-name       FileController                                                                                                                                                                                                               
 modifier          public                                                                                                                                                                                                                       
 annotation        org.springframework.stereotype.Controller,org.springframework.web.bind.annotation.RequestMapping                                                                                                                             
 interfaces                                                                                                                                                                                                                                     
 super-class       +-java.lang.Object                                                                                                                                                                                                           
 class-loader      +-org.springframework.boot.loader.LaunchedURLClassLoader@9629756                                                                                                                                                             
                     +-jdk.internal.loader.ClassLoaders$AppClassLoader@5c29bfd                                                                                                                                                                  
                       +-jdk.internal.loader.ClassLoaders$PlatformClassLoader@71423665                                                                                                                                                          
 classLoaderHash   9629756  

场景

可以让指定的 classloader 去 getResources,打印出所有查找到的 resources 的 url。并且还可以指定类类的加载器,对于ResourceNotFoundException比较有用。

4.dump指令

dump 已加载类的 bytecode 到特定目录

场景

将 JVM 中实际运行的 class 的 byte code dump 到指定目录,适用场景批量下载指定包目录的 class 字节码;如需反编译单一类、实时查看类信息,可参考 jad。

  • dump -d /xx dump到指定目录

    [arthas@2719]$ dump -d /data com.example.demo.controller.UserInfoController
     HASHCODE  CLASSLOADER                                                          LOCATION                                                                                                                                                        
     9629756   +-org.springframework.boot.loader.LaunchedURLClassLoader@9629756     /data/org.springframework.boot.loader.LaunchedURLClassLoader-9629756/com/example/demo/controller/UserInfoController.class                                       
                 +-jdk.internal.loader.ClassLoaders$AppClassLoader@5c29bfd                                                                                                                                                                          
                   +-jdk.internal.loader.ClassLoaders$PlatformClassLoader@71423665                                                                                                                                                                  
    Affect(row-cnt:1) cost in 202 ms.
    

    我们看看/data下面的目录文件:

    [root@localhost data]# ll /data/
    总用量 100884
    -rw-r--r--. 1 root root   141899 82 23:45 arthas-boot.jar
    drwxr-xr-x. 2 root root       24 84 01:46 arthas-output
    -rw-r--r--. 1 root root 99038636 826 14:39 demo-0.0.1-SNAPSHOT.jar
    -rw-r--r--. 1 root root      179 82 23:14 Dockerfile
    drwxr-xr-x. 2 root root      227 826 11:04 logs
    -rw-r--r--. 1 root root     4120 83 00:34 math-game.jar
    -rw-------. 1 root root  4097224 826 14:59 nohup.out
    drwxr-xr-x. 3 root root       17 826 15:50 org.springframework.boot.loader.LaunchedURLClassLoader-9629756
    -rw-r--r--. 1 root root      598 84 03:04 Test.class
    -rw-r--r--. 1 root root      446 823 16:17 Test.java
    

    org.springframework.boot.loader.LaunchedURLClassLoader-9629756,这个文件就是我们刚刚dump出来的目录,我们进入目录一直点下去,就能看到最终的class文件:

    [root@localhost controller]# ll
    总用量 4
    -rw-r--r--. 1 root root 2010 826 15:50 UserInfoController.class
    
  • dump --classLoaderClass sun.misc.Launcher$AppClassLoader UserInfoController
    用–classLoaderClass参数+ ClassLoader 的类名来指定类加载器加载,这里ClassLoader 实例必须唯一。classLoaderClass 在 java 8 是 sun.misc.Launcher$AppClassLoader,而 java 11 的 classloader 是 jdk.internal.loader.ClassLoaders$AppClassLoader

5.getstatic指令

场景

想要知道某个类中的某个static修饰的字段的值是多少
示例:
我目前ArthasController 中的sum字段的值类型为Integer,值为6

[arthas@3126]$ getstatic com.example.demo.controller.ArthasController sum
field: sum
@Integer[6]
Affect(row-cnt:1) cost in 14 ms.

6.heapdump指令

场景

导出当前java的堆栈信息。
示例:

[arthas@3126]$ heapdump /data/testDump.hprof
Dumping heap to /data/testDump.hprof ...
Heap dump file created

cd到/data目录后,就可以看到了:

-rw-------. 1 root root 76268636 826 16:32 testDump.hprof

PS:这里的/data目录(本文几乎所有目录),是虚拟机的目录,不是arthas的目录,我们虽然attach上了arthas,控制台变了,但是我们还是可以访问宿主机的目录。默认路径是你arthas-boot.jar文件的目录

7.profiler指令

场景

生成火焰图
示例:
1.开始采样

[arthas@3126]$ profiler start
Profiling started

2.停止,会自动保存

[arthas@3126]$ profiler stop
OK
profiler output file: /data/arthas-output/20240826-170650.html

3.查看
官方说的是用 http://localhost:3658/arthas-output/就能查看,但是我物理机去访问这个地址,ip和端口都没问题,但是就是访问不起,不知道啥情况, 最后只有将文件复制到Windows,然后用浏览器查看。
最后结果就长这样,目前还不知道这个图怎么看,后面学习了再补充上。
在这里插入图片描述

8.sc指令

场景

查看 JVM 已加载的类信息
可选参数-d,就是detail

[arthas@3126]$ sc -d com.example.demo.controller.UserInfoController 
 class-info        com.example.demo.controller.UserInfoController                                                                                                                                                                               
 code-source       file:/data/demo-0.0.1-SNAPSHOT.jar!/BOOT-INF/classes!/                                                                                                                                                                       
 name              com.example.demo.controller.UserInfoController                                                                                                                                                                               
 isInterface       false                                                                                                                                                                                                                        
 isAnnotation      false                                                                                                                                                                                                                        
 isEnum            false                                                                                                                                                                                                                        
 isAnonymousClass  false                                                                                                                                                                                                                        
 isArray           false                                                                                                                                                                                                                        
 isLocalClass      false                                                                                                                                                                                                                        
 isMemberClass     false                                                                                                                                                                                                                        
 isPrimitive       false                                                                                                                                                                                                                        
 isSynthetic       false                                                                                                                                                                                                                        
 simple-name       UserInfoController                                                                                                                                                                                                           
 modifier          public                                                                                                                                                                                                                       
 annotation        org.springframework.web.bind.annotation.RestController,org.springframework.web.bind.annotation.RequestMapping                                                                                                                
 interfaces                                                                                                                                                                                                                                     
 super-class       +-java.lang.Object                                                                                                                                                                                                           
 class-loader      +-org.springframework.boot.loader.LaunchedURLClassLoader@9629756                                                                                                                                                             
                     +-jdk.internal.loader.ClassLoaders$AppClassLoader@5c29bfd                                                                                                                                                                  
                       +-jdk.internal.loader.ClassLoaders$PlatformClassLoader@71423665                                                                                                                                                          
 classLoaderHash   9629756                                                                                                                                                                                                                      

Affect(row-cnt:1) cost in 110 ms.

可选参数-f,需要配合-d一起使用,显示字段信息。

9.trace指令

场景

输出方法内部调用路径,从上往下层级调用输出,并输出方法路径上的每个节点上耗时

[arthas@3126]$ trace com.example.demo.controller.UserInfoController fileUpload
Press Q or Ctrl+C to abort.
Affect(class count: 1 , method count: 1) cost in 1030 ms, listenerId: 1
`---ts=2024-08-26 18:03:41;thread_name=http-nio-8081-exec-8;id=30;is_daemon=true;priority=5;TCCL=org.springframework.boot.web.embedded.tomcat.TomcatEmbeddedWebappClassLoader@2ca6546f
    `---[75.03077ms] com.example.demo.controller.UserInfoController:fileUpload()
        +---[98.91% 74.209617ms ] com.example.demo.service.UserInfoService:list() #36
        `---[0.11% 0.084421ms ] com.example.demo.vo.ResultMsg:success() #37

这个接口的list方法耗时74.209617ms,占比98.91%,而ResultMsg:success()方法耗时0.084421ms,占比0.11%

以上就是对第一篇Java线上监控诊断产品Arthas内容的补充,如果后续有新的体会,出个3.0版本也说不一定,或者在本文继续补充。

  • 23
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值