banner
lMingyul

lMingyul

记录穿过自己的万物
jike
twitter
github
bilibili

用好系列-arthas之入门篇

在公司定位故障问题的时候,一般我们会采用在代码中关键代码中打印日志,然后采用在环境容器内换 Jar 包的形式进行问题定位分析。但是这样定位的问题流程很麻烦:

  • 首先你要确保你打印日志的全面性,万一某个关键信息没有打印出来你就需要重新打印、换包、重启服务,一套流程下来浪费很多时间;
  • 其次不是所有环境都运行换包和重启服务

所以最近我一直在找更好的故障问题定位方法,然后我发现阿里开源的 Java 服务诊断工具好像还不错,它可以查看方法调用入参、返回值,被调用的调用路径、调用耗时、方法调用次数、成功次数、失败次数等这些都可以记录,所以学习记录一下这个工具。

什么是 arthas#

官方介绍:
Arthas 是一款线上监控诊断产品,通过全局视角实时查看应用 load、内存、gc、线程的状态信息,并能在不修改应用代码的情况下,对业务问题进行诊断,包括查看方法调用的出入参、异常,监测方法执行耗时,类加载信息等,大大提升线上问题排查效率。

运行环境#

  • 只支持 JDK 6 + 的环境
  • 由 Java 编写的,支持跨平台:支持 Linux(主要)、Mac、Windows

特性#

  • 采用命令行交互模式
  • 提供 Tab 键自动补全的功能

初步使用#

因为平时公司使用的环境主要是在容器中,所以以下就主要记录在 Linux 环境下如何使用这个工具

下载使用包#

由于公司环境是内网环境,不支持直接访问连接 Github 进行安装包的下载,这里防止机器的网络问题无法下载,所以采用的是手动先从 Github 下载拷贝到服务容器内部的方式进行使用

在 Github 中下载完整的安装包,下载地址 :https://github.com/alibaba/arthas/releases

CleanShot-2023-04-30-00-13-53@2x

容器环境下解压#

CleanShot-2023-04-30-00-44-29@2x

卸载#

定位完问题之后也要打扫好战场,那卸载这个工具的方法也记录一下

执行完以下三步即可卸载工具

运行#

首先启动一个不会停止的 Java 程序服务,官方的安装包下就附带了一个给我们练手的 Jar 包:math-game.jar (不过一般我们的服务也是一直运行的,这里就使用官方的包作为记录)

然后再启动 arthas

CleanShot-2023-04-30-00-50-48@2x


常用命令#

help#

dashboard#

仪表板:显示当前系统的实时数据面板,平时没有这个 dashboard 的时候我们一般只能通过 Linux 自带的 top 命令查看系统运行的信息

输入 dashboard,按 回车/enter,会展示当前进程的信息,按 ctrl+c 或输入 q 可以中断执行。
CleanShot-2023-04-30-01-01-50@2x

显示的信息大概分为 3 大块:

  • 最上面的是线程相关信息
  • 中间区域是 JVM 内存相关的信息
  • 最下面的是 Java 的运行环境信息
    具体每一列的信息可以参考官方文档

thread#

查看当前线程信息堆栈

当没有参数时,显示第一页线程的信息#

默认按照 CPU 增量时间降序排列,只显示第一页数据。

CleanShot-2023-05-03-11-59-07@2x

支持一键展示当前最忙的前 N 个线程并打印堆栈#

CleanShot-2023-05-03-12-00-56@2x 1

thread --all, 显示所有匹配的线程#

CleanShot-2023-05-03-16-43-24@2x

thread id, 显示指定线程的运行堆栈#

thread -b, 找出当前阻塞其他线程的线程#

watch#

观察指定方法的调用情况
可以观察到:
方法返回值、入参、方法抛出的异常,还可以通过编写 OGNL 表达式进行对应变量的查看

观察函数调用返回时的参数、this 对象和返回值#

同时观察函数调用前和函数返回后#

观察当前对象中的属性#

如果想查看函数运行前后,当前对象中的属性,可以使用 target 关键字,target 代表当前对象,然后使用 target.field_name 访问当前对象的某个属性

trace#

方法内部调用路径,并输出路径上的每个节点上耗时,服务间调用时间过长时使用

  • 输出结果中 #24 表示 在源文件的第 24 行调用了 primeFactors() 函数
  • 输出结果中 #25 表示 在源文件的第 25 行调用了 print() 函数

stack#

输出当前方法被调用的调用路径,当我们需要知道这个方法(被很多地方调用过)从那里开始执行了就可以使用这个命令(适合寻根溯源)

jad#

反编译指定已加载类的源码,便于在线上理解业务逻辑,反编译出来的代码是带语法高亮的

CleanShot-2023-05-11-00-34-53@2x


参考资料#

加载中...
此文章数据所有权由区块链加密技术和智能合约保障仅归创作者所有。