【java线上监控】Arthas由菜鸟到菜鸡
Arthas 是一款线上监控诊断产品,通过全局视角实时查看应用 load、内存、gc、线程的状态信息,并能在不修改应用代码的情况下,对业务问题进行诊断,包括查看方法调用的出入参、异常,监测方法执行耗时,类加载信息等,大大提升线上问题排查效率。官方文档SkyWalking 是什么?FROM分布式系统的应用程序性能监视工具,专为微服务、云原生架构和基于容器(Docker、K8s、Mesos)架构而设计
目录
5.2 Alibaba Cloud Toolkit 热部署组件(一键 retransform)
1 arthas介绍
1.1 简介
Arthas 是一款线上监控诊断产品,通过全局视角实时查看应用 load、内存、gc、线程的状态信息,并能在不修改应用代码的情况下,对业务问题进行诊断,包括查看方法调用的出入参、异常,监测方法执行耗时,类加载信息等,大大提升线上问题排查效率。
1.2 背景
通常,本地开发环境无法访问生产环境。如果在生产环境中遇到问题,则无法使用 IDE 远程调试。更糟糕的是,在生产环境中调试是不可接受的,因为它会暂停所有线程,导致服务暂停。
开发人员可以尝试在测试环境或者预发环境中复现生产环境中的问题。但是,某些问题无法在不同的环境中轻松复现,甚至在重新启动后就消失了。
如果您正在考虑在代码中添加一些日志以帮助解决问题,您将必须经历以下阶段:测试、预发,然后生产。这种方法效率低下,更糟糕的是,该问题可能无法解决,因为一旦 JVM 重新启动,它可能无法复现,如上文所述。
Arthas 旨在解决这些问题。开发人员可以在线解决生产问题。无需 JVM 重启,无需代码更改。 Arthas 作为观察者永远不会暂停正在运行的线程。
1.3 Arthas(阿尔萨斯)能为你做什么?
Arthas
是 Alibaba 开源的 Java 诊断工具,深受开发者喜爱。
当你遇到以下类似问题而束手无策时,Arthas
可以帮助你解决:
-
这个类从哪个 jar 包加载的?为什么会报各种类相关的 Exception?
-
我改的代码为什么没有执行到?难道是我没 commit?分支搞错了?
-
遇到问题无法在线上 debug,难道只能通过加日志再重新发布吗?
-
线上遇到某个用户的数据处理有问题,但线上同样无法 debug,线下无法重现!
-
是否有一个全局视角来查看系统的运行状况?
-
有什么办法可以监控到 JVM 的实时运行状态?
-
怎么快速定位应用的热点,生成火焰图?
-
怎样直接从 JVM 内查找某个类的实例?
Arthas
支持 JDK 6+,支持 Linux/Mac/Windows,采用命令行交互模式,同时提供丰富的 Tab
自动补全功能,进一步方便进行问题的定位和诊断。
2 window环境搭建
2.1 下载和启动
#下载jar包 curl -O https://arthas.aliyun.com/arthas-boot.jar # 启动 d: cd temp java -jar arthas-boot.jar
2.1 启动后:选择需要监控的服务
输入2:回车 D:\Temp> java -jar arthas-boot.jar [INFO] JAVA_HOME: D:\Java\jdk-17 [INFO] arthas-boot version: 3.6.7 [INFO] Found existing java process, please choose one and input the serial number of the process, eg : 1. Then hit ENTER.
-
[1]: 13344 org.jetbrains.jps.cmdline.Launcher [2]: 11652 com.bridge.MybatisMybatisPlusApp
[3] 14212
[4]: 4700 org.jetbrains.idea.maven.server.RemoteMavenServer36 2
3 快速入门
3.1 打开浏览器
3.2 开启trace请求
trace -E 类全路径 方法名 -n 5 --skipJDKMethod false '1==1'
-
如入需要监控的方法名
trace -E com.bridge.controler.UserController getUsers -n 5 --skipJDKMethod false '1==1'
回车后效果
Affect(class count: 2 , method count: 2) cost in 70 ms, listenerId: 2 [arthas@11652]$ trace -E com.bridge.controler.UserController getUsers -n 5 --skipJDKMethod false '1==1' Press Q or Ctrl+C to abort.
-
亲的页面请求后效果如下
[arthas@11652]$ trace -E com.bridge.controler.UserController getUsers -n 5 --skipJDKMethod false '1==1' Press Q or Ctrl+C to abort. Affect(class count: 2 , method count: 2) cost in 64 ms, listenerId: 3 `---ts=2023-04-09 21:37:54;thread_name=http-nio-8080-exec-5;id=58;is_daemon=true;priority=5;TCCL=org.springframework.boot.web.embedded.tomcat.TomcatEmbeddedWebappClassLoader@186dcec2 `---[23.6803ms] com.bridge.controler.UserController$$EnhancerBySpringCGLIB$$ea91532e:getUsers() `---[98.58% 23.3448ms ] org.springframework.cglib.proxy.MethodInterceptor:intercept() `---[97.18% 22.6864ms ] com.bridge.controler.UserController:getUsers() `---[99.79% 22.6391ms ] com.bridge.service.IUserService:getAll() #38
3.3 查看 dashboard
输入dashboard,按回车/enter
,会展示当前进程的信息,按ctrl+c
可以中断执行。
$ dashboard ID NAME GROUP PRIORI STATE %CPU TIME INTERRU DAEMON 17 pool-2-thread-1 system 5 WAITIN 67 0:0 false false 27 Timer-for-arthas-dashb system 10 RUNNAB 32 0:0 false true 11 AsyncAppender-Worker-a system 9 WAITIN 0 0:0 false true 9 Attach Listener system 9 RUNNAB 0 0:0 false true 3 Finalizer system 8 WAITIN 0 0:0 false true 2 Reference Handler system 10 WAITIN 0 0:0 false true 4 Signal Dispatcher system 9 RUNNAB 0 0:0 false true 26 as-command-execute-dae system 10 TIMED_ 0 0:0 false true 13 job-timeout system 9 TIMED_ 0 0:0 false true 1 main main 5 TIMED_ 0 0:0 false false 14 nioEventLoopGroup-2-1 system 10 RUNNAB 0 0:0 false false 18 nioEventLoopGroup-2-2 system 10 RUNNAB 0 0:0 false false 23 nioEventLoopGroup-2-3 system 10 RUNNAB 0 0:0 false false 15 nioEventLoopGroup-3-1 system 10 RUNNAB 0 0:0 false false Memory used total max usage GC heap 32M 155M 1820M 1.77% gc.ps_scavenge.count 4 ps_eden_space 14M 65M 672M 2.21% gc.ps_scavenge.time(m 166 ps_survivor_space 4M 5M 5M s) ps_old_gen 12M 85M 1365M 0.91% gc.ps_marksweep.count 0 nonheap 20M 23M -1 gc.ps_marksweep.time( 0 code_cache 3M 5M 240M 1.32% ms) Runtime os.name Mac OS X os.version 10.13.4 java.version 1.8.0_162 java.home /Library/Java/JavaVir tualMachines/jdk1.8.0 _162.jdk/Contents/Hom e/jre
3.4 通过 thread 命令来获取到math-game
进程的 Main Class
thread 1
会打印线程 ID 1 的栈,通常是 main 函数的线程。
$ thread 1 | grep 'main(' at demo.MathGame.main(MathGame.java:17)
3.5. 通过 jad 来反编译 Main Class
$ jad demo.MathGame ClassLoader: +-sun.misc.Launcher$AppClassLoader@3d4eac69 +-sun.misc.Launcher$ExtClassLoader@66350f69 Location: /tmp/math-game.jar /* * Decompiled with CFR 0_132. */ package demo; import java.io.PrintStream; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import java.util.Random; import java.util.concurrent.TimeUnit; public class MathGame { private static Random random = new Random(); private int illegalArgumentCount = 0; public static void main(String[] args) throws InterruptedException { MathGame game = new MathGame(); do { game.run(); TimeUnit.SECONDS.sleep(1L); } while (true); } public void run() throws InterruptedException { try { int number = random.nextInt(); List<Integer> primeFactors = this.primeFactors(number); MathGame.print(number, primeFactors); } catch (Exception e) { System.out.println(String.format("illegalArgumentCount:%3d, ", this.illegalArgumentCount) + e.getMessage()); } } public static void print(int number, List<Integer> primeFactors) { StringBuffer sb = new StringBuffer("" + number + "="); Iterator<Integer> iterator = primeFactors.iterator(); while (iterator.hasNext()) { int factor = iterator.next(); sb.append(factor).append('*'); } if (sb.charAt(sb.length() - 1) == '*') { sb.deleteCharAt(sb.length() - 1); } System.out.println(sb); } public List<Integer> primeFactors(int number) { if (number < 2) { ++this.illegalArgumentCount; throw new IllegalArgumentException("number is: " + number + ", need >= 2"); } ArrayList<Integer> result = new ArrayList<Integer>(); int i = 2; while (i <= number) { if (number % i == 0) { result.add(i); number /= i; i = 2; continue; } ++i; } return result; } } Affect(row-cnt:1) cost in 970 ms.
3.6. watch
通过watch命令来查看demo.MathGame#primeFactors
函数的返回值:
$ watch demo.MathGame primeFactors returnObj Press Ctrl+C to abort. Affect(class-cnt:1 , method-cnt:1) cost in 107 ms. ts=2018-11-28 19:22:30; [cost=1.715367ms] result=null ts=2018-11-28 19:22:31; [cost=0.185203ms] result=null ts=2018-11-28 19:22:32; [cost=19.012416ms] result=@ArrayList[ @Integer[5], @Integer[47], @Integer[2675531], ] ts=2018-11-28 19:22:33; [cost=0.311395ms] result=@ArrayList[ @Integer[2], @Integer[5], @Integer[317], @Integer[503], @Integer[887], ] ts=2018-11-28 19:22:34; [cost=10.136007ms] result=@ArrayList[ @Integer[2], @Integer[2], @Integer[3], @Integer[3], @Integer[31], @Integer[717593], ] ts=2018-11-28 19:22:35; [cost=29.969732ms] result=@ArrayList[ @Integer[5], @Integer[29], @Integer[7651739], ]
更多的功能可以查看进阶使用。
3.7. 退出 arthas
如果只是退出当前的连接,可以用quit
或者exit
命令。Attach 到目标进程上的 arthas 还会继续运行,端口会保持开放,下次连接时可以直接连接上。
如果想完全退出 arthas,可以执行stop
命令。
4 进阶使用
4.1 通过浏览器连接 arthas
Arthas 目前支持 Web Console,用户在 attach 成功之后,可以直接访问:http://127.0.0.1:8563/在新窗口打开。
可以填入 IP,远程连接其它机器上的 arthas。
注意
默认情况下,arthas 只 listen 127.0.0.1,所以如果想从远程连接,则可以使用 --target-ip
参数指定 listen 的 IP,更多参考-h
的帮助说明。 注意会有安全风险,考虑下面的 tunnel server 的方案。
-
在 Web Console 复制粘贴快捷键参考: https://github.com/alibaba/arthas/issues/1056在新窗口打开
提示
3.5.4 版本后,在 Web Console 可以鼠标右键复制粘贴。
4.2 scrollback URL 参数
提示
3.5.5 版本后支持
默认 Web Console 支持向上回滚的行数是 1000。可以在 URL 里用scrollback
指定。比如
http://127.0.0.1:8563/?scrollback=3000在新窗口打开
4.3 使用 arthas tunnel server
其余参考官网
5 idea插件arthas idea
5.1 Arthas-idea(部分命令可视化)
提示
插件由社区开发者提供。
-
Jetbrains 插件获取地址: https://plugins.jetbrains.com/plugin/13581-arthas-idea在新窗口打开
5.2 Alibaba Cloud Toolkit 热部署组件(一键 retransform)
提示
热部署组件支持一键将编辑器中修改的 Java 源码快速编译,并更新到远端应用服务中,免去手动 dump、mc 的过程。此外,也可以一键还原 retransform 的类文件。
-
Jetbrains 插件获取地址: https://plugins.jetbrains.com/plugin/11386-alibaba-cloud-toolkit在新窗口打开
-
使用文档:https://help.aliyun.com/document_detail/381077.html在新窗口打开
-
联系我们:请加 Alibaba Cloud Toolkit (应用观测器) 钉钉用户交流群(群号:34965379)
5.3 安装插件
快速生成命令
对应的方法右击--》选择Arthas Command-->选择对应的命令
在Arthas中输入复制命令【trace -E com.bridge.controller.RedisHashController getSysDictConfig -n 5】图一,接口请求后图二
图一
图二
6 相同功能工具介绍【skywalking】
1.1 概念
SkyWalking 是什么?
FROM Apache SkyWalking
分布式系统的应用程序性能监视工具,专为微服务、云原生架构和基于容器(Docker、K8s、Mesos)架构而设计。
提供分布式追踪、服务网格遥测分析、度量聚合和可视化一体化解决方案。
1.2 功能列表
SkyWalking 有哪些功能?
FROM Apache SkyWalking
多种监控手段。可以通过语言探针和 service mesh 获得监控是数据。
多个语言自动探针。包括 Java,.NET Core 和 Node.JS。
轻量高效。无需大数据平台,和大量的服务器资源。
模块化。UI、存储、集群管理都有多种机制可选。
支持告警。
优秀的可视化解决方案。
1.3 整体架构
SkyWalking 整体架构如何?
FROM Apache SkyWalking
整个架构,分成上、下、左、右四部分:
考虑到让描述更简单,我们舍弃掉 Metric 指标相关,而着重在 Tracing 链路相关功能。
-
上部分 Agent :负责从应用中,收集链路信息,发送给 SkyWalking OAP 服务器。目前支持 SkyWalking、Zikpin、Jaeger 等提供的 Tracing 数据信息。而我们目前采用的是,SkyWalking Agent 收集 SkyWalking Tracing 数据,传递给服务器。
-
下部分 SkyWalking OAP :负责接收 Agent 发送的 Tracing 数据信息,然后进行分析(Analysis Core) ,存储到外部存储器( Storage ),最终提供查询( Query )功能。
-
右部分 Storage :Tracing 数据存储。目前支持 ES、MySQL、Sharding Sphere、TiDB、H2 多种存储器。而我们目前采用的是 ES ,主要考虑是 SkyWalking 开发团队自己的生产环境采用 ES 为主。
-
左部分 SkyWalking UI :负责提供控台,查看链路等等。
更多推荐
所有评论(0)