Java博文
JAVA 21 都体验了吧
Java程序员必备的Intellij插件(长期更新,截止到2018-05-03) - 掘金
32.6k star🔥原来国内的独立开发者都在做这些事情
工作六年,我学会了用 Arthas 来辅助我的日常工作
太方便了!Arthas,生产问题大杀器 - 掘金
新一代Java高性能构建工具Maven-mvnd【实践可行版】
怎么在业务团队写好发消息的代码?
Intellij 开源热加载插件 HotSwapHelper 发布,兼容若依、jeecg 等框架
SpringBoot多环境日志配置_Java_快乐非自愿限量之名_InfoQ写作社区
VSCode配置JAVA开发环境_Java_IT蜗壳-Tango_InfoQ写作社区
Java虚拟线程探究与性能解析
Jakarta EE 11 发布,增强企业 Java 开发人员生产力和性能
重要:Java25正式发布(长期支持版)!
Access Token + Refresh Token 全解析:前后端分离架构的认证与安全方案
设计一个支持千万级用户的 IM 系统:消息推送如何保证可靠性
Spring Boot + CRaC 启动速度提升了10倍!
Java 25 新特性 更简洁、更高效、更现代
玩转 Java8 Stream,让你代码更高效紧凑简洁文章目录前言一、Stream特性二、Stream创建2.1用集合创 - 掘金
Guava 简介:让 Java 开发更高效
横空出世!MyBatis-Plus 同款 ES ORM 框架,用起来够优雅!
一个Java工程师的17个日常效率工具
Quarkus:轻量级 Java 的未来?
OpenJDK、Temurin、GraalVM...到底该装哪个?
Lombok坑哭了!若依框架一行@Data炸出Param为null,我卡了一下午才发现BaseEntity的猫腻
缓存性能王者,阿里巴巴二级缓存JetCache框架
MapStruct使用反思与简单易用性封装
Dockerfile 构建 Java 应用瘦身优化
还在手动搭Maven多模块?这款IDEA插件让我效率提升10倍(真实体验)
本文档使用 MrDoc 发布
-
+
工作六年,我学会了用 Arthas 来辅助我的日常工作
_很久就想写一篇介绍 Arthas 的文章,虽然 Arthas 已有大量文章介绍;但我依然想结合我的实际工作,来聊聊这款我喜爱的 Java 监控诊断产品。_ > 🔊一位 Java 开发者的使用总结,只谈使用经验,不聊原理。 ## 📆 那些辛酸的过往 **_历历在目的场景_🥹**(❁´◡`❁)(❁´◡`❁) - 客户线上问题,应该如何复现,让客户再点一下吗? - 异常被吃掉,手足无措,看是哪个家伙写的,竟然是自己! - 排查别人线上的 bug,不仅代码还没看懂,还没一行日志,捏了一把汗! - 预发 debug,稍微时间长点,群里就怨声载道! - 加日志重新部署,半个小时就没了,问题还没有找到,头顶的灯却早已照亮了整层楼...... - 线上机器不能 debug,也不能开 debug 端口,重新部署会不会破坏现场呢? - 怀疑入参有问题,怀疑合并代码有问题,怀疑没有部署成功,全是问号...... - 一个问题排查一天,被 Diss 排查问题慢...... > _直到我遇到了 Arthas,那些曾经束手无策的问题,都变得轻而易举。于是想把这些遇到的场景和用法做个总结。_ ## 📕一、通过命令执行方法--vmtool **vmtool 命令是我最喜欢用的,也是用最多的一个命令。通过这个命令执行方法,检查各种不符合预期的分支逻辑,入参出参,以及各种外部依赖接口,甚至还能修改数据等。** #### 1.1 场景 | 解决过的场景 | 具体描述 | | --- | --- | | 发布导致线上的缓存 key 错误,需要清理,但过期时间还长,没有删除 key 的远程接口 | 通过执行 service 方法,删除缓存 key;另外读取 redis 中的 key 也极其方便 | | 缺少日志,不知道上游是否返回数据合理 | 通过执行方法,确定依赖返回数据不正确 | | 发布应用同时修改分布式配置,导致推送配置到该节点失败 | 通过执行方法,查询配置信息不是最新 | | 常量值不符合预期,配置在 properties 中的免登 url 失效 | 通过执行方法,查询当前常量值,判断读取不合理 | | 新增配置信息、删除脏数据 | 通过接口执行方法,添加了配置、删除了脏数据 | | 集群环境,想要请求打在指定机器上查看日志 | 需要反复请求多次才能命中特定机器查看日志,通过vmtool 执行方法,快速实现日志查看 | | 出参入参不符合预期 | 在调用链路上执行所有可疑方法 | | 以前需要写 controller 调用触发的测试方法 | 直接用这个命令,减少代码,还能测试上下游的各种二方接口,十分方便 | _`案例还有很多很多,因为真的可以拿着入参尽情的 invoke`_ 提升了排查问题、解决问题的效率,也帮助其他人解决他们的问题。不再依赖打印大量日志反复部署服务,也不再申请 debug 端口进行远程 debug ,因为确实方便。 #### 1.2 使用 工欲善其事必先利其器,我在 IDEA 装上一个 Arthas 插件,用它来快速复制命令,想执行哪个方法拷贝即可。  > 上图是使用 Arthas 插件生成执行命令。光标放在执行方法上右击选择 vmtool 即可得到可运行命令。 **情景一: 执行的方法是对象**:需要对参数对象赋值,以下图中的方法为例:  `queryIBCcContactConfig` 方法参数是对象, 首先通过 Arthas 工具查找到参数 `IbCcContactConfigParam` 的**classLoaderHash**, 如下命令:(sc -d 路径)  对参数对象进行字段赋值,方式参考下面加粗部分(ognl方式): > vmtool -x 3 -c 76707e36 --action getInstances --className com.xxx.impl.IbCcContactConfigServiceImpl --express 'instances\[0\].queryIbCcContactConfig(**(#demo=new com.xxx.param.IbCcContactConfigParam(), #demo.setContactBizCode('12345L'),#demo)**)' 情景二、基础类型,比如String、Long、Int。直接填充数值即可 | 举例 | 语句 | 描述 | | --- | --- | --- | | 基础类型,比如String、Int、Long类型等 | vmtool -x 3 --action getInstances --className com.xxl.mq.admin.service.IXxlMqMessageService --express 'instances\[0\].delete(0)' | 执行 IXxlMqMessageService#delete 方法,参数为0 | | | | | | 参数 | 解释 | | --- | --- | | \-x 3 | 返回参数展开形式的,默认1,如果返回体是对象,建议设置3,方便观察返回结果 | | \-c xxx | 指定classLoaderHash,如果不指定,new 方法报错 | #### 1.3 限制 其一、尽量避开 ThreadLocal 。执行线程没有 ThreadLocal 的上下文; 其二、只能有一个端口,只支持一个arthas-server,用完及时关掉。 #### 1.4 扩展 使用 getstatic 命令查看静态变量 | 场景描述 | 语句执行 | 解释 | | --- | --- | --- | | 查看静态变量的实际值 | getstatic com.xxx.xxx.interceptor.env.EnvIsolationInterceptor FILL\_FIELD\_NAME -x 3 | 查看 EnvIsolationInterceptor # FILL\_FIELD\_NAME 的静态变量值 | | 配置application.properties的免登 uri,发现没有生效 | getstatic com.xxx.sso.filter.InitParamContext excludeList -x 3 | 查看自己的免登 uri 是否在集合里面,从而快速定位问题 | | 修改静态变量值 | ognl -x 3 '#field=@[com.xxl.mq.admin.conf.XxlMqBrokerImpl@class.getDeclaredField](https://link.juejin.cn?target=mailto%3Acom.xxl.mq.admin.conf.XxlMqBrokerImpl%40class.getDeclaredField)("ENV"),#field.setAccessible(true),#field.set(null," ")' |  | ## 🖥️二、热部署 # redefine && retransform 😭**拍桌子拍大腿感叹发布的的代码少写或者漏写;拍脑门惋惜为啥不多打一行日志;口吐芬芳为什么把判断条件写死......,那些只能发布才能调试、部署一次要半小时的应用,真的会让生命变得廉价。** #### 2.1 场景 | 解决过的场景 | 描述 | | --- | --- | | 加日志语句,入参出参观察 | 联调查看参数 | | 将判断条件恒定成了 false,目标分支无法执行,阻塞进度 | 修改判断逻辑 | | 漏写一行赋值代码 | 对象自己赋值给自己,字段值为NULL | | 研发、联调阶段,代码验证 | 需要反复修改代码验证 | | 测试同学提Bug及时修复验证 | 快速修复问题,不影响测试进度 | **热部署的优势用过的都说好**👍。 #### 2.2 使用 IDEA 集成 ArthasHotSwap 插件,方便快捷:  > 很多公司通过 API 方式已经集成了工具,定制化更好用😄。 #### 2.3 限制 - 不允许新增加 field/method - 正在跑的函数,没有退出不能生效 - redefine 和 watch/trace/jad/tt 等命令冲突 热部署能力,是一个很强大的能力,线上谨慎使用,属于高危操作。 ## 📑三、OGNL && 条件过滤 **顶流功能,可以使用 OGNL 解决很多复杂场景,其条件过滤属于绝佳。 适用于 watch、trace、stack、monitor等,有大量请求、 for 场景等。**  #### 3.1 场景 条件过滤的适用场景实在太多,简单举例 | 解决过的场景 | 描述 | | --- | --- | | 想拦截特定参数值的方法入参出参,过滤其他参数请求 | 只有特定参数才会被拦截,否则跳过,不影响其他人使用 | | 拦截特定参数,这个参数方法调用耗时长 | 排查到了参数异常情况,特定账号数据量太大 | | 指定账号登录异常 | 通过监控指定 userId 的调用栈,排查问题 | #### 3.2 使用 条件判断形式:形如 params\[0\] == "orgIdxxx726" (OGNL) | 场景 | 案例 | 描述 | | --- | --- | --- | | **watch 命令**:只监控特定组织的数据信息 | watch com.xxx.controller.OrgServiceController getOrgInfo '{params,returnObj,throwExp}' 'params\[0\] == "orgIdxxx726"' -n 5 -x 3 | 通过“ '**params\[0\] == "orgIdxxx726**"'”命令,判断只有当参数为“orgIdxxx726” watch 才生效 | | **trace 命令**:只有特定组织的数据比较消耗时间 | trace com.xxx.controller.OrgServiceController getOrgInfo 'params\[0\] == "orgIdxxx726"' -n 5 --skipJDKMethod false | 查询只要特定组织耗时长,忽略其他参数,精准定位 | | **stack 命令**:查看调用栈,非常适合代理调用、AOP、Filter等 | stack com.xxx.controller.OrgServiceController getOrgInfo 'params\[0\] == "orgIdxxx726"' -n 5 | 排查调用链路 | 更多使用条件判断的案例如下 ```java -- 判空 trace com.xxx.controller.OrgServiceController getOrgInfo'params[0] != null' -- 等于 trace *com.xxx.controller.OrgServiceController getOrgInfo 'params[0] == 1L' -- 字符串不等于 trace com.xxx.controller.OrgServiceController getOrgInfo 'params[1] != "AA"' ``` OGNL 可以组合各种形式的条件判断。非常适合 watch、trace、stack 等场景。 #### 3.3 扩展 [更多灵活的用法](https://link.juejin.cn?target=https%3A%2F%2Fgithub.com%2Falibaba%2Farthas%2Fissues%2F11) [ognl | arthas](https://link.juejin.cn?target=https%3A%2F%2Farthas.aliyun.com%2Fdoc%2Fognl.html) ## 🔖 四、其他命令汇总 #### 4.1 logger 在写代码的时候,也可以刻意加 log.debug 级别的日志。日志级别一般为 info ,当需要排查问题的时候,可以修改日志级别为 debug。 | 解决过的场景 | 描述 | | --- | --- | | 自定义日志失效,排查日志的实现类由哪个包引入或者提供 | 排查间接引入的日志依赖包 | | 改变当前类的日志级别,查看日志 | 将 info 级别修改成 debug 级别 | ```css logger -n com.xxx.controller.OrgServiceControlle 通过sc 查看这个类的claasLoaderHash; logger --name ROOT --level debug -c 4839ebd ``` #### 4.2 monitor 监控某个方法的调用次数。包括调用次数,平均RT、成功率等信息。在性能调优使用: ```arduino monitor com.XXXX.handler.HandlerManager process -n 10 --cycle 10 ``` #### 4.3 thread 排查线程死锁,以及线程状态: | 语句 | 详细 | | --- | --- | | thread -b | 排查死锁情况,注意,当 Arthas 不能加载的时候,还是继续使用原来的 top 命令那一套排查问题 | | thread -n 3 | 查询当前最忙的 N 个线程 | #### 4.4 jad 命令、反编译 | 场景 | 描述 | | --- | --- | | 排查 jar 中的 class 文件加载是否符合预期。比如:突然发现某一台机器上的执行结果和其他的机器的结果不一致。 | 怀疑机器部署异常 | | 依赖包冲突,加载类不符合预期或者支合并的时候出错 | 检查运行的代码 | 案例:springBoot 应用遇到 NoSuchMethodError 等问题,可以使用 Jad 反编译确认,看一下加载的类是否有问题。 #### 4.5 watch watch 用来查看入参出参,配合 OGNL 条件过滤非常实用: ```arduino watch com.xxl.mq.admin.service.IXxlMqMessageService pageList '{params,returnObj,throwExp}' -n 5 -x 4 ```  条件判断 #cost>200(单位ms) 表示只有当耗时大于200ms才输出: ```arduino watch demo... primeFactors '{params, returnObj}' '#cost>200' -x 2 ``` 如果 x 设置超过 4 也就只展示4。使用 x=4 的情况比较常见,因为展开的信息最多。但需要注意线上数据量太大情况。 #### 4.6 tt (Time Tunnel) tt 可以实现重做,实现方法调用;个人比较喜欢 vmtool,不过多介绍, tt 功能也十分强大。 #### 4.7 用得不多的命令 下面几个命令个人用得少,但很重要: | 命令 | 描述 | | --- | --- | | memory | 查看内存信息 | | options | 全局开关,jvm 比较高级少用的命令 | | sysprop / sysenv | 当前 JVM 的系统属性,环境属性 | | profiler | [火焰图](https://link.juejin.cn?target=https%3A%2F%2Farthas.aliyun.com%2Fdoc%2Fprofiler.html) | | dashboard | [实时数据面板](https://link.juejin.cn?target=https%3A%2F%2Farthas.aliyun.com%2Fdoc%2Fdashboard.html) | 其他命令就不再赘述了📎。 #### 4.8 Arthas 插件功能 Arthas 插件生成的命令如下:  > 注:图片来源于 [arthas 插件作者](https://link.juejin.cn?target=https%3A%2F%2Fgithub.com%2FWangJi92%2Farthas-idea-plugin%2Fblob%2Fmaster%2FREADME.md),插件和文章都很好🌺 针对插件的热部署配置详见: [(Hot Swap) Redefine 热更新支持](https://link.juejin.cn?target=https%3A%2F%2Fwww.yuque.com%2Farthas-idea-plugin%2Fhelp%2Fpwxhb4)); 个人更推荐热部署用 ArthasHotSwap 插件。 ## 📌五、一些限制 && 注意事项 - 执行trace / tt 等命令时,本质上是在 method 的前后插入代码,会影响原来 JVM 里面 JIT 编译生成的代码。可能执行并发高的函数有抖动; - 只能有一个端口,只支持一个 arthas-server; - 热部署有限制且不一定能成功,线上属于高危操作; - 如果服务不能响应,可能 Arthas 不能启动使用,需要使用 Linux 相关命令排查问题。 ## 📇六、好文推荐 1. [官网文档](https://link.juejin.cn?target=https%3A%2F%2Farthas.aliyun.com%2F) 2. [个人最推荐的学习资料: arthas idea plugin手册](https://link.juejin.cn?target=https%3A%2F%2Fwww.yuque.com%2Farthas-idea-plugin%2Fhelp%2Fpe6i45) ## 🧣七、最后的话 🖲要成为 Arthas 使用的好手,一定多多练习:**纸上得来终觉浅,绝知此事要躬行**。
admin
2024年7月28日 07:09
转发文档
收藏文档
上一篇
下一篇
手机扫码
复制链接
手机扫一扫转发分享
复制链接
Markdown文件
PDF文档(打印)
分享
链接
类型
密码
更新密码