|
| 1 | +# 带你一起使用Alibaba Java诊断利器 Arthas |
| 2 | + |
| 3 | +> 本文适合有 Java 基础知识的人群,跟着本文可学习 `Java` 线上问题定位利器 `Arthas`。 |
| 4 | +
|
| 5 | + |
| 6 | + |
| 7 | +<p align="center">本文作者:HelloGitHub-<strong>秦人</strong></p> |
| 8 | + |
| 9 | +HelloGitHub 推出的[《讲解开源项目》](https://github.com/HelloGitHub-Team/Article)系列,今天给大家带来一款 Alibaba Java诊断利器 Arthas 项目—— [Arthas](https://github.com/alibaba/arthas) |
| 10 | + |
| 11 | +> 项目源码地址:https://github.com/alibaba/arthas |
| 12 | +
|
| 13 | +## 一、简介 |
| 14 | + |
| 15 | +为什么要用arthas,好多`Java`开发的小伙伴可能有遇到下面这些问题: |
| 16 | +- 项目中导入了一个jar包的不同版本,那么这个类从哪个 jar 包加载的?线上环境为什么会报各种异常? |
| 17 | + |
| 18 | +- 本地项目运行没问题,线上环境运行的结果为什么和本地不同?数据原因没有执行到?代码没有 commit?环境上使用的分支搞不对? |
| 19 | + |
| 20 | +- 线上环境遇到偶先问题,难道只能通过加日志,调整项目日志级别,重新打包发布验证问题吗? |
| 21 | + |
| 22 | +- 线上环境遇到某个用户的审批流程走的不对,线下环境无法重现,怎么在线上进行远程调试呢? |
| 23 | + |
| 24 | +- 有没一个监控系统的运行整体状况的功能? |
| 25 | + |
| 26 | +- `jdk`自带了一些监控工具,本地可动态监控 `jvm `运行状态,那么线上环境有什么办法可以监控到 JVM 的实时运行状态? |
| 27 | + |
| 28 | +- 在线上环境怎么快速定位应用的热点,生成火焰图? |
| 29 | + |
| 30 | + |
| 31 | +**arthas实现原理** |
| 32 | + |
| 33 | +整体宏观模块调用图如下: |
| 34 | + |
| 35 | + |
| 36 | +**arthas主要功能** |
| 37 | +Arthas提供的功能主要可以分为以下3个方面: |
| 38 | + |
| 39 | +1. 信息监控<br/> |
| 40 | +进程运行基本信息包括:内存、CPU占用、线程信息、线程堆栈、线程数统计、环境变量信息。<br/> |
| 41 | +对象信息:类对象静态属性、 Mbean 的属性信息、已加载类信息、类加载器、类方法信息。 |
| 42 | +2. 方法调用<br/> |
| 43 | +方法调用入参、返回值查看。<br/> |
| 44 | +方法被调用的调用路径、调用耗时、方法调用次数、成功次数、失败次数等统计。<br/> |
| 45 | +记录和重做方法调用。 |
| 46 | +3. 类文件处理<br/> |
| 47 | +dump已加载类的字节码、字节码反编译、类编译、类重新热加载。 |
| 48 | + |
| 49 | +## 三、安装和使用 |
| 50 | + |
| 51 | +### 3.1 Linux环境使用 |
| 52 | +登录`Linux`环境,下载 `arthas-boot.jar`,然后使用命令`java -jar xxx.jar`直接运行`jar`包。 |
| 53 | +下面两个命令效果一样,都可以下载。 |
| 54 | +```bash |
| 55 | +curl -O https://alibaba.github.io/arthas/arthas-boot.jar |
| 56 | +wget https://alibaba.github.io/arthas/arthas-boot.jar |
| 57 | +``` |
| 58 | +进入`arthas`第一步需要选择项目 |
| 59 | + |
| 60 | + |
| 61 | +### 3.2 Docker环境使用 |
| 62 | +进入一个之前已经启动的 `Docker` 容器,这里我进入了 `tomcat7` 容器,。 |
| 63 | + |
| 64 | +```bash |
| 65 | +docker ps -a #查看所有容器 |
| 66 | +docker cp arthas-boot.jar tomcat7:/home #拷贝jar到容器home目录 |
| 67 | +docker exec -it tomcat7 bash #进入名称叫tomcat7的容器 |
| 68 | +cd /home |
| 69 | +java -jar arthas-boot.jar #运行jar包 |
| 70 | +``` |
| 71 | +注意:选择的`Docker`容器必须是以`Jdk`为基础依赖构建的。 |
| 72 | + |
| 73 | +在命令行输入`dashboard`,就可以进入仪表板的所有数据。 |
| 74 | + |
| 75 | + |
| 76 | +### 3.2 开发工具Idea使用 |
| 77 | +Cloud Toolkit是一个IDE 插件,帮助开发者更高效地开发、测试、诊断并部署应用。方便地将本地应用一键部署到任意机器,或 ECS、EDAS、Kubernetes。这里只介绍一下连接远程服务器,使用`arthas`。 |
| 78 | +1. `idea`安装插件 |
| 79 | + 在`File`->`Settings`->`Plugins`,搜索 `Alibaba Cloud Toolkit` |
| 80 | +  |
| 81 | + 插件安装完重启`IDE`。 |
| 82 | + |
| 83 | +2. 使用工具 |
| 84 | + 添加远程服务器,如下图操作 |
| 85 | +  |
| 86 | + 服务器配置成功后,选择`More`->`Diagnostic`,即可连接到服务器上。 |
| 87 | +  |
| 88 | +3. 运行效果 |
| 89 | +  |
| 90 | + |
| 91 | +## 四、实战案例分析 |
| 92 | + |
| 93 | +1. 以线上代码热更新,这里我写了一个小的`Sprinboot`项目,主要就是一个获取学习信息的接口。 |
| 94 | + ```java |
| 95 | + @RestController |
| 96 | + public class StudentConroller { |
| 97 | + |
| 98 | + @GetMapping("getUserInfo") |
| 99 | + public Student getUserInfo() { |
| 100 | + return new Student("小刘",12,"西安市雁塔区"); |
| 101 | + } |
| 102 | + } |
| 103 | + ``` |
| 104 | + 通过 `curl http://localhost:9000/getUserInfo`,访问内容如下: |
| 105 | + |
| 106 | + ```json |
| 107 | + {"name":"小刘","id":12,"address":"西安市雁塔区"} |
| 108 | + ``` |
| 109 | + |
| 110 | +2. 在服务运行要测试的项目`demo-0.0.1-SNAPSHOT.jar` |
| 111 | + ```bash |
| 112 | + nohup java -jar demo-0.0.1-SNAPSHOT.jar & #后台运行 |
| 113 | + curl http://localhost:9000/getUserInfo #访问接口 |
| 114 | + ``` |
| 115 | +3. 运行`arthas`主程序`arthas-boot.jar`,选择进入`demo-0.0.1-SNAPSHOT.jar` |
| 116 | +  |
| 117 | + |
| 118 | +4. 使用 `jad` 反编译`StudentConroller.java`代码 |
| 119 | + ```bash |
| 120 | + jad --source-only com.example.demo.controller.StudentConroller > /tmp/StudentConroller.java |
| 121 | + ``` |
| 122 | +5. 打开`/tmp/StudentConroller.java`下的文件,修改反编绎出来的代码,修改内容如下: |
| 123 | + ```java |
| 124 | + @RestController |
| 125 | + public class StudentConroller { |
| 126 | + @GetMapping(value={"getUserInfo"}) |
| 127 | + public Student getUserInfo() { |
| 128 | + return new Student("小刘1", 122, "西安市高新区"); |
| 129 | + } |
| 130 | + } |
| 131 | + ``` |
| 132 | +6. `sc` 命令查找加载 `StudentConroller` 的ClassLoader |
| 133 | + ```bash |
| 134 | + $ sc -d *StudentConroller | grep classLoaderHash |
| 135 | + classLoaderHash 2e0fa5d3 |
| 136 | + ``` |
| 137 | +7. `mc` 命令内存编绎代码 |
| 138 | + ```bash |
| 139 | + $ mc -c 2e0fa5d3 /tmp/StudentConroller.java -d /tmp |
| 140 | + Memory compiler output:/tmp/com/example/demo/arthas/user/controller/StudentConroller.class |
| 141 | + Affect(row-cnt:1) cost in 346 ms |
| 142 | + ``` |
| 143 | +8. `redefine` 命令热更新代码 |
| 144 | + ```bash |
| 145 | + $ redefine /tmp/com/example/demo/controller/StudentConroller.class |
| 146 | + redefine success, size: 1 |
| 147 | + ``` |
| 148 | +9. 检测热更新结果 |
| 149 | + 再次访问 `curl http://localhost:9000/getUserInfo`,显示如下内容: |
| 150 | +  |
| 151 | + |
| 152 | +`Arthas` 的jad/mc/redefine 一条龙来线上热更新代码,非常强大,但也很危险,需要做好权限管理。 |
| 153 | + |
| 154 | +## 五、总结 |
| 155 | +本文最开讲`Arthas`有什么作用,我们为什么要用它。接着讲了三种场景是如何使用`Arthas` 的。最后以`java`代码在线热部署为例,感受了 `Arthas` 的强大。看到这里我想你也对`Arthas`工具的有一个简单的认识。现在的趋势开发人员做了久了慢慢就变为`DevOps`,了解更多的底层逻辑也能更好的反馈到代码层面的`上层建筑`。本文带大家入门,`Arthas`更多强大的功能期待的发掘! |
| 156 | + |
| 157 | +## 六、附录 |
| 158 | +- [arthas官方文档](https://alibaba.github.io/arthas/quick-start.html) |
| 159 | +- [Arthas脑图—常用命令汇总](https://github.com/alibaba/arthas/issues/1003) |
| 160 | + |
0 commit comments