当前位置: 首页 > news >正文

使用Arthas定位问题

功能概述

首先,Arthas的常用功能大概有以下几个:

  • 解决依赖冲突

sc命令:模糊查看当前 JVM 中是否加载了包含关键字的类,以及获取其完全名称。 sc -d 关键字
注意使用 sc -d 命令,获取

classLoaderHash命令:通过 classloader 查看 class 文件来自哪个 jar 包 注意 classloader -c
后面的值填上面获取到的 classLoaderHash值

  • 查看线上运行的代码源码,是否是预期的(确认代码是否提交,分支是否正确)

jad --source-only:可以查看源代码。

watch命令:查看方法调用情况。后面跟上完全类名和方法名,以及一个 OGNL的表达式,-f 表示不论正常返回还是异常返回都进行观察,-x 表示输出结果的属性遍历深度,默认为 1,建议无脑写 4就行,最大的遍历深度,再大就不支持了

tt命令:观测方法调用情况,tt命令可以查看「多次调用」并选择其中一个进行观测,但是如果输出结果是多层嵌套就没办法看了,而 watch 可以查看「多层嵌套」的结果。

这两个命令都是用来查看方法调用过程的,不同的是 watch 命令是调用一次打印一次方法的调用情况,而 tt 命令可以先生成一个不断增加的调用列表,然后指定其中某一项进行观测。

  • 热启动(类似JRebel)

redefine 命令:「热替换」线上的代码,注意应用重启之后会失效,这在某些紧急情况下会有奇效。
比如说我们修改一下方法体里面的代码,加了一行日志打印

  • 看程序运行时的整体情况

dashboard命令:可以查看当前系统的实时数据面板,当运行在Ali-tomcat时,会显示当前tomcat的实时信息,如HTTP请求的qps, rt, 错误数,线程池信息,内存使用情况,系统参数等等。

  • 查看程序运行时的jvm状态

jvm 命令:可以查看 JVM 的实时运行状态。

  • 定位应用运行中的热点分析系统瓶颈

profiler 命令:支持生成应用热点的火焰图。本质上是通过不断的采样,然后把收集到的采样结果生成火焰图。

应用实例

背景

项目使用了MumbleSDK 2.x, rmb请求先到一个Dispatcher类, 然后Dispatcher根据请求参数里的bizServiceId把请求分发到不同的子服务接口. 各个子服务接口上有个@MumbleMessageService标注着自己对应的bizServiceId.

上个月有个一次性的补数需求, 图方便我就直接在子服务的类里用@Async写了个异步方法, 分发服务Dispatcher就识别不到@MumbleMessageService注解找不到子服务了. 根据组内其他小伙伴的经验, 是因为这个类被spring代理了导致的. 后来把异步方法抽到单独的类实现, 服务就正常了.
但这个bug在测试环境没有复现过, 如果是代理问题,那么在什么环境都应该复现才对, 这篇文章就是寻找测试环境没复现的原因, 以及从源码层面上分析为什么@Async会导致找不到子服务的注解.

本地调试

开发环境运行后bug复现了, 看了Dispatcher分发服务的源码, 原理是系统启动时扫描所有继承了MumbleBaseService的类, 然后遍历实现类以及父类里的方法是否带有@MumbleMessageService, 如果有就放在缓存里, 请求过来时就从缓存里取出对应的服务.
在扫描结束的位置加了断点, 可以看到出问题的那个类由于有个方法用了@Async, 类名带有$Proxy, 是个JDK动态代理类. 而JDK动态代理类和它的父类java.lang.reflect.Proxy 方法上都没有@MumbleMessageService, 所以不会被Dispatcher放进缓存, 子服务自然识别不到了.
在这里插入图片描述
那么测试环境的类是什么样的呢?为什么注解能识别到呢? 使用神器Arthas试试.

使用Arthas

1. 首先使用sc命令查看jvm里加载的类信息

在这里插入图片描述
发现有个类名带有 $EnhancerBySpringCGLIBEnhancerBySpringCGLIBEnhancerBySpringCGLIB, 是cglib代理类, 而本地调试时类名带有$Proxy, 是JDK代理类, 这个差异很可能就是造成测试环境bug没复现的原因. 而且有好多个在开发环境正常的类测试环境也变成代理类了. 应该是有个地方统一给这些类做了增强. 于是现在问题就变成了 哪里使用了cglib代理了这些类, 而且只在测试环境才使用了呢? 我自己项目里的代码里是没这样用的, 可能是在某个引用的包里. 继续挖.

2. 这次使用trace命令查看方法的调用链, 想看看调用链里有没有发现

在这里插入图片描述
输入命令后, 发送一笔请求, 发现只有各个节点的耗时时长, 没有别的信息了. 官方文档这个命令的说明是方法内部调用路径,并输出方法路径上的每个节点上耗时, 看来只能看到方法内部的调用链, 方法外的看不到, 而我要找的是哪里增强了这个方法.

3. 接下去尝试使用stack命令查询方法被调用的调用路径

下图是发送请求后stack命令打印出来的东西, 出现了一个mumbleSDK里的类, 名字看起来就是使用了AOP切面
在这里插入图片描述
找到这个类源码, 就是它了! MumbleSDK里的dao,rmb调用耗时监控组件, 给项目里service目录下的类都做了cglib代理, 而且只有测试环境满足了@Conditional里的条件所以开启了.
在这里插入图片描述
让我们验证下, 在项目的配置文件里加上 mumble.monitor.web.enabled=false 关闭这个监控服务. 部署到测试环境后bug终于重现了. 再次使用sc查看, 之前的cglib代理类已经变成JDK代理了
在这里插入图片描述

4. 用jad命令反编译两种不同的代理类

下图是cglib的, 可以看到继承的父类是原来的类. 再复习下MumbleSDK Dispatcher识别服务的原理: 遍历实现类以及父类的方法扫描@MumbleMessageService注解. 所以可以识别到方法上的@MumbleMessageService并把子服务加进缓存. 这就是一开始测试环境能识别到子服务的原因.
在这里插入图片描述
下图是jdk代理类, 父类是Proxy, 方法上没有@MumbleMessageService. 也就会出现找不到子服务的问题了.
在这里插入图片描述
所以这个bug的根本原因是不同类型的动态代理的实现差异导致的, 而不是一开始认为的单纯是因为被代理了.
下图是@EnableAsync里的代码, 默认是jdk代理.
在这里插入图片描述
回到本地开发环境, 把@EnableAsync改成 @EnableAsync(proxyTargetClass = true), 强制使用cglib代理. 重启服务, 开发环境的服务也正常了.
但是, 为了能乱放@Async而去改spring的默认代理配置是不合理的, 还是要把@Async方法独立出去.

Arthas Idea插件

命令或类名太长记不得可以安装使用Aethas的idea插件,如下图,在方法上右键选中相应的命令, 就可以把命令复制到剪贴板, 直接去终端粘贴使用就行了. 比如下图粘贴的结果是 stack cn.webank.pmbank.cp.ocr.service.impl.OcrCorePojoService DoCommonOcr -n 5
在这里插入图片描述

总结

  • 以前只了解过两种动态代理的实现机制及区别, 没感受过这种区别对系统运行造成的影响. 就这个bug来说, 是代理类的父类不同造成的.
    以后如果遇到这类问题也多了个debug思路.
  • Arthas真香. 以前debug时用的笨方法都可以用它代替. 比如定位接口耗时长问题, 不用在代码里一段段打印耗时日志再重新部署了,
    一行trace命令就可以打印出各个链路的耗时; 比如不确定部署的代码是不是刚才更新的, 可以使用jad反编译查看变更的类.
  • 带有@Async @Schedule @Transation 等注解的方法最好分类放到单独的类里, 比如专门的异步任务类, 定时任务类等.不仅能避免代理方面的问题, 也能使代码结构更清晰整洁.

相关文章:

使用Arthas定位问题

功能概述 首先,Arthas的常用功能大概有以下几个: 解决依赖冲突 sc命令:模糊查看当前 JVM 中是否加载了包含关键字的类,以及获取其完全名称。 sc -d 关键字 注意使用 sc -d 命令,获取 classLoaderHash命令&#xff1a…...

性能测试之tomcat+nginx负载均衡

nginx tomcat 配置准备工作:两个tomcat 执行命令 cp -r apache-tomcat-8.5.56 apache-tomcat-8.5.56_2修改被复制的tomcat2下conf的server.xml 的端口号,不能与tomcat1的端口号重复,不然会启动报错 ,一台电脑上想要启动多个tomcat&#xff0c…...

【手写 Vuex 源码】第十一篇 - Vuex 插件的开发

一,前言 上一篇,主要介绍了 Vuex-namespaced 命名空间的实现,主要涉及以下几个点: 命名空间的介绍和使用;命名空间的逻辑分析与代码实现;命名空间核心流程梳理; 本篇,继续介绍 Vu…...

opencv基础知识和绘图图形

大家好,我是csdn的博主:lqj_本人 这是我的个人博客主页: lqj_本人的博客_CSDN博客-微信小程序,前端,python领域博主lqj_本人擅长微信小程序,前端,python,等方面的知识https://blog.csdn.net/lbcyllqj?spm1011.2415.3001.5343哔哩哔哩欢迎关注…...

15- 决策回归树, 随机森林, 极限森林 (决策树优化) (算法)

1. 决策回归树: from sklearn.tree import DecisionTreeRegressor model DecisionTreeRegressor(criterionmse,max_depth3) model.fit(X,y) # X是40个点 y是一个圆 2. 随机森林 稳定预测: from sklearn.ensemble import RandomForestClassifier # model RandomForestC…...

Flink相关的记录

Flink源码编译首次编译的时候,去除不必要的操作,同时install会把Flink中的module安装到本地仓库,这样依赖当前module的其他组件就无需去远程仓库拉取当前module,节省了时间。mvn clean install -T 4 -DskipTests -Dfast -Dmaven.c…...

配置可视化-基于form-render的无代码配置服务(一)

背景 有些业务场景需要产品或运营去配置JSON数据提供给开发去使用(后面有实际业务场景的说明),原有的业务流程,非开发人员(后面直接以产品指代)把数据交给开发,再由开发去更新JSON数据。对于产…...

Java 代理模式详解

1、代理模式 代理模式是一种比较好理解的设计模式。简单来说就是 我们使用代理对象来代替对真实对象(real object)的访问,这样就可以在不修改原目标对象的前提下,提供额外的功能操作,扩展目标对象的功能。 代理模式的主要作用是扩展目标对象…...

知识付费小程序怎么做_分享知识付费小程序的作用

在线知识付费产业的主要业务逻辑是基于用户的主动学习需求,为其提供以跨领域基础知识与技能为核心的在线知识服务,提升其达到求知目的的效率。公众号和小程序的迅速发展,又为知识付费提供了技术支持,从而促进了行业的进一步发展。…...

14- 决策树算法 (有监督学习) (算法)

决策树是属于有监督机器学习的一种决策树算法实操: from sklearn.tree import DecisionTreeClassifier # 决策树算法 model DecisionTreeClassifier(criterionentropy,max_depthd) model.fit(X_train,y_train)1、决策树概述 决策树是属于有监督机器学习的一种,起源…...

如何编译和运行C++程序?

C 和C语言类似,也要经过编译和链接后才能运行。在《C语言编译器》专题中我们讲到了 VS、Dev C、VC 6.0、Code::Blocks、C-Free、GCC、Xcode 等常见 IDE 或编译器,它们除了可以运行C语言程序,还可以运行 C 程序,步骤是一样的&#…...

Golang 给视频添加背景音乐 | Golang工具

目录 前言 环境依赖 代码 总结 前言 本文提供给视频添加背景音乐,一如既往的实用主义。 主要也是学习一下golang使用ffmpeg工具的方式。 环境依赖 ffmpeg环境安装,可以参考我的另一篇文章:windows ffmpeg安装部署_阿良的博客-CSDN博客 …...

让AI护理医疗:解决卫生系统的痛点

一、引言 1.对医疗领域中AI技术的介绍 随着人工智能的不断发展,它已经成为了各个领域中的重要组成部分。在医疗领域中,AI技术也逐渐发挥着越来越重要的作用。从诊断到治疗,从健康管理到研究,人工智能已经深刻地影响着医疗领域的…...

Windows 离线安装 MySQL 8

目录 1. 下载离线安装包 2. 上传解压 3 配置 my.ini 文件 4 设置系统环境变量 5 安装 MySQL 6 登录 MySQL 客户环境是内网环境,不能访问外网,只能离线安装 MySQL 了。 1. 下载离线安装包 MySQL 离线压缩包官网下载地址:MySQL :: Down…...

【前端攻城狮之vue基础】02路由+嵌套路由+路由query/params传参+路由props配置+replace属性+编程式路由导航+缓存路由组件

路由的基础知识1.路由简介2.路由基本使用3.嵌套路由4.传递路由的query传参# 5.传递路由的params参数6.路由的props传参配置7.路由router-link标签的replace属性8.编程式路由导航9.缓存路由组件1.路由简介 路由是一条条对应的key-value关系,key就是前端地址栏的路径…...

CHAPTER 1 Zabbix介绍及安装

Zabbix介绍及安装1.1 Zabbix监控1 为什么要监控1.1 网站可用性2 监控什么东西2.1 监控范畴3 怎么来监控3.1 远程管理服务器3.2 监控硬件3.3 查看cpu相关3.4 内存3.5 磁盘3.6 监控网络4 监控工具总览5 zabbix介绍5.1 zabbix的组成5.2 zabbix监控范畴1.2 安装zabbix1 环境检查2 安…...

认识V模型、W模型、H模型

软件测试与软件工程息息相关,软件测试是软件工程组成中不可或缺的一部分。 在软件工程、项目管理、质量管理得到规范化应用的企业,软件测试也会进行得比较顺利,软件测试发挥的价值也会更大。 要关注软件工程、质量管理以及配置管理与软件测试…...

excel ttest检测

1、excel函数含义 TTEST(array1,array2,tails,type) ▪ Array1: 第一组数据集 ▪ Array2: 第二组数据集 ▪ Tails: 用于定义所返回的分布的尾数: 1 代表单尾;2 代表双尾 ▪ Type: 用于定义 t-检验的类型: 1 代表成对检验;2 代表双样本等方差假设&am…...

PDFPrinting.Net操作进行细粒度控制

PDFPrinting.Net操作进行细粒度控制 PDFPrinting.Net能够容易且灵活地预测完美的打印结果以及用户文件的示例性显示。可以快速浏览.NET PDF打印中最关键的元素。如果用户需要获得更详细的概述,那么他可以查看快速入门手册,甚至是现有文档的详细概述参考。…...

SegPGD

在这项工作中,我们提出了一种有效和高效的分割攻击方法,称为SegPGD。此外,我们还提供了收敛性分析,表明在相同次数的攻击迭代下,所提出的SegPGD可以创建比PGD更有效的对抗示例。此外,我们建议应用我们的Seg…...

ESP-IDF + Vscode ESP32 开发环境搭建以及开发入门

ESP-IDF Vscode ESP32 开发环境搭建以及开发入门 文章目录ESP-IDF Vscode ESP32 开发环境搭建以及开发入门1. 前言2. 下载开发工具3. 配置工具4. 创建工程5. 解决vscode找不到头文件,波浪线警告6. 添加自己的组件6.1 组件说明6.2 添加项目组件6.3 添加扩展组件7. …...

SpringMvc的请求和响应

SpringMvc的数据响应 1.springmvc的数据相应方式 &#xff08;1&#xff09;页面跳转 直接返回字符串 通过ModelAndView对象返回 &#xff08;2&#xff09;回写数据 直接返回字符串 返回对象或集合 页面跳转 jsp页面 <% page contentType"text/html;charsetUTF-8&q…...

【Vue3】首页主体-面板组件封装

首页主体-面板组件封装 新鲜好物、人气推荐俩个模块的布局结构上非常类似&#xff0c;我们可以抽离出一个通用的面板组件来进行复用 目标&#xff1a;封装一个通用的面板组件 思路分析 图中标出的四个部分都是可能会发生变化的&#xff0c;需要我们定义为可配置主标题和副标题…...

部署 K8s 集群

1 .部署k8s的两种方式目前生产部署Kubernetes集群主要有两种方式&#xff1a;kubeadmKubeadm是一个K8s部署工具&#xff0c;提供kubeadm init和kubeadm join&#xff0c;用于快速部署Kubernetes集群。二进制包从github下载发行版的二进制包&#xff0c;手动部署每个组件&#x…...

关于北京君正:带ANC的2K网络摄像头用户案例

如果远程办公是您的未来&#xff0c;或者您经常通过视频通话与远方的朋友和亲戚交谈&#xff0c;那么您可以考虑购买网络摄像头以显著改善您的沟通。Anker PowerConf C200是个不错的选择。 Anker PowerConf C200专为个人工作空间而设计&#xff0c;能够以每秒30帧的速度拍摄2K…...

ccc-Backpropagation-李宏毅(7)

文章目录NotationBackpropagationForward passBackward passSummaryNotation 神经网络求解最优化Loss function时参数非常多&#xff0c;反向传播使用链式求导的方式提升计算梯度向量时的效率&#xff0c;链式法则如下&#xff1a; Backpropagation 损失函数计算为所有样本…...

找出字符串中第一个匹配项的下标-力扣28-java

一、题目描述给你两个字符串 haystack 和 needle &#xff0c;请你在 haystack 字符串中找出 needle 字符串的第一个匹配项的下标&#xff08;下标从 0 开始&#xff09;。如果 needle 不是 haystack 的一部分&#xff0c;则返回 -1 。示例 1&#xff1a;输入&#xff1a;hayst…...

SpringBoot 监听Redis key过期回调

SpringBoot 监听Redis key过期回调 场景 Spring boot实现监听Redis key失效事件可应对某些场景例如&#xff1a;处理订单过期自动取消、用户会员到期… 开启Redis键过期回调通知 Redis默认是没有开启键过期监听功能的&#xff0c;需要手动在配置文件中修改。Linux操作系统 修…...

蓝桥杯C/C++VIP试题每日一练之回形取数

💛作者主页:静Yu 🧡简介:CSDN全栈优质创作者、华为云享专家、阿里云社区博客专家,前端知识交流社区创建者 💛社区地址:前端知识交流社区 🧡博主的个人博客:静Yu的个人博客 🧡博主的个人笔记本:前端面试题 个人笔记本只记录前端领域的面试题目,项目总结,面试技…...

四控、三管、一协调

四控指的是进度控制&#xff0c;质量控制&#xff0c;成本控制&#xff0c;变更控制。三管指的是合同管理&#xff0c;安全管理&#xff0c;资料管理。一协调指的是协调甲方&#xff0c;总包及设备材料供应方的关系。信息系统工程监理是指依法设立且具备相应资质的信息系统工程…...

网站是用什么做的吗/超级seo助手

http://www.zhangxinxu.com/wordpress/?p2277 一、你至少应该知道ARIA是什么东西&#xff01; WAI-ARIA指无障碍网页应用。主要针对的是视觉缺陷&#xff0c;失聪&#xff0c;行动不便的残疾人以及假装残疾的测试人员。尤其像盲人&#xff0c;眼睛看不到&#xff0c;其浏览网页…...

网页设计与制作相关书籍/河南网站关键词优化代理

一些常用语句&#xff1a; 1. sender.title(for:.selected)!获取按钮Button的titile属性值 2.定义一个自定义类型的视图控制器 blueViewController storyboard?.instantiateViewController(withIdentifier:“Blue”) as! BlueViewController//创建了一个自定义类型为BlueView…...

广州专门做网站/seo推广排名公司

.col-lg-*: //*:代表列数&#xff0c;一行12列 //表示在屏幕大于等于≥1200px时按照这个规律展示 如&#xff1a; .col-lg-2 //表示在屏幕大于等于≥1200px时占2列而其他的按照表中的信息对照即可 也可以自己去bootstrap官网查找&#xff1a; 网址:https://v3.bootcss.com/cs…...

网站建设优化服务器/seo优化关键词

2008/03/04skate 今天测试人员提出有某个人的个人空间的文章无法访问,因为这块是由存储过程来实现的,所以检查下存数过程 ORA-01422: 实际返回的行数超出请求的行数ORA-06512: 在 "PRO_USERARTICLE_MANAGE", line 202ORA-06512: 在 line 8 看来有重复额记录啊,经过…...

南昌成都网站建设方案/企业网站排名优化

-- Start 我们已经知道了在正常情况下&#xff0c;点号(.)能够匹配除换行符以外的任何字符。事实上这句话并不准确&#xff0c;确切的说&#xff0c;点号(.)能够匹配除换行符以外的任何单个代码点。由于处于辅助平面内的字符由两个代码点构成&#xff0c;所以&#xff0c;为了匹…...

做网站搞流量挂联盟广告变现/国外免费网站域名服务器

1. 目标把定时任务通过集群的方式进行管理调度&#xff0c;并采用分布式部署&#xff0c;保证系统的高可用&#xff0c;提高了容错。那么如何保证定时任务只在集群的某一个节点上执行&#xff0c;或者一个任务如何拆分为多个独立的任务项&#xff0c;由分布式的机器去分别执行&…...