PDF书籍《手写调用链监控APM系统-Java版》第9章 插件与链路的结合:Mysql插件实现

本人阅读了 Skywalking 的大部分核心代码,也了解了相关的文献,对此深有感悟,特此借助巨人的思想自己手动用JAVA语言实现了一个 “调用链监控APM” 系统。本书采用边讲解实现原理边编写代码的方式,看本书时一定要跟着敲代码。

作者已经将过程写成一部书籍,奈何没有钱发表,如果您知道渠道可以联系本人。一定重谢。

本书涉及到的核心技术与思想

JavaAgent , ByteBuddy,SPI服务,类加载器的命名空间,增强JDK类,kafka,插件思想,切面,链路栈等等。实际上远不止这么多,差不多贯通了整个java体系。

适用人群

自己公司要实现自己的调用链的;写架构的;深入java编程的;阅读Skywalking源码的;

版权

本书是作者呕心沥血亲自编写的代码,不经同意切勿拿出去商用,否则会追究其责任。

原版PDF+源码请见:

本章涉及到的工具类也在这里面:

PDF书籍《手写调用链监控APM系统-Java版》第1章 开篇介绍-CSDN博客

第9章 插件与链路的结合:Mysql插件实现

9.1 Mysql插件的流程分析

数据库归根结底就是JDBC的操作,在学习时期,我们肯定会学习基本的jdbc查询数据库的写法:

// 1. 加载驱动
Class.forName("com.mysql.jdbc.Driver");
// 2. 获取连接 对象
ConnectionImpl connection = (ConnectionImpl) DriverManager.getConnection("", "", "");
// 3. 准备 statement
PreparedStatement statement = connection.prepareStatement("select * from t_user");
// 4. 执行sql
statement.executeQuery();

无论用什么框架,数据库操作都避免不了上面原始步骤。我们分析下上面的流程:

1. 加载驱动,我们不关心。

2. 通过DriverManager的静态方法getConnection获取到ConnectionImpl 连接对象。

3. 通ConnectionImpl的prepareStatement方法,去配合sql准备一个PreparedStatement 。

4. 最后通过PreparedStatement的executeQuery方法去查询sql语句并返回结果。

数据库插件要想采集到调用的sql信息,就必须要拦截ConnectionImpl类的prepareStatement方法。 如果还要采集sql调用的返回信息,还需要拦截 PreparedStatement 类的executeQuery方法。但是我们还需要数据库服务器的地址信息,这个还必须要拦截 DriverManager.getConnection 。

拦截的三个类我们梳理出来了,但是这里有个很严重的问题,当我们拦截DriverManager.getConnection获取到数据库地址后,没办法向后传递到ConnectionImpl类的prepareStatement中。

我们架设一个猜想:

拦截DriverManager.getConnection返回的是ConnectionImpl。如果能在这个阶段将数据库的地址信息设置到返回的ConnectionImpl对象中,后面拦截ConnectionImpl的prepareStatement方法时,方法切面那里是不是有个参数能获取到当前对象,也就能拿到DriverManager.getConnection拦截时的数据库信息了。

这也就需要在增强类中添加Object字段,用于参数传递的思想。

我们目前的字节码增强代码时无法实现上述思想的,需要进行改造。接下来我们来讲解下如何实现。

9.2 插桩类改造,新增Object字段和实现EnhancedInstance接口

由于篇幅过长,请到第一章查看原版PDF和源码:

PDF书籍《手写调用链监控APM系统-Java版》第1章 开篇介绍-CSDN博客


9.3 Mysql插件真正实现

根据前面的分析,我们依次需要拦截

类名: java.sql.DriverManager

方法:getConnection

JDK类库

然后拦截:

类名: com.mysql.jdbc.ConnectionImpl

方法:prepareStatement

非JDK类库

最后拦截:

类名: com.mysql.jdbc.PreparedStatement

方法:executeQuery

非JDK类库

在插件模块下新增apm-mysql-plugin项目,POM内容:

<dependency><groupId>com.hadluo.apm</groupId><artifactId>apm-commons</artifactId><version>1.0</version>
</dependency><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>5.1.44</version><scope>provided</scope>
</dependency>

hadluo-apm-plugin.def 插件定义文件:

mysql5-DriverConnect=com.hadluo.apm.plugin.mysql5.DriverConnectInstrumentationmysql5-PrepareStatement=com.hadluo.apm.plugin.mysql5.PrepareStatementInstrumentationmysql5-PrepareStatementExecute=com.hadluo.apm.plugin.mysql5.PrepareStatementExecuteInstrumentation

三个类我就不建了,值得注意的是,DriverManager#getConnection方法最终调用下面方法:

DriverConnectInstrumentation配置拦截类名时,还需要指定参数签名:

还有就是isBootstrapInstrumentation 一定要返回true, 因为它是rt.jar的JDK类。

三个方法环绕执行器分别是:

DriverConnectInterceptor

PrepareStatementInterceptor

PrepareStatementExecuteInterceptor

DriverConnectInterceptor 代码实现:

由于篇幅过长,请到第一章查看原版PDF和源码:

PDF书籍《手写调用链监控APM系统-Java版》第1章 开篇介绍-CSDN博客

打包测试,kafka数据json如下:

{"msgTypeClass": "com.hadluo.apm.commons.kafka.Segment","sampleTime": 1734056030540,"serviceName": null,"serviceInstance": "1a91d6d937ea4d6b8c2cb34dc75bf240@192.168.2.125","traceId": "c133c183325b48fdbd3c94eca8bf341e.44.17340560303730001","traceSegmentId": "c133c183325b48fdbd3c94eca8bf341e.44.17340560303710000","spans": [{"spanId": 1,"parentSpanId": 0,"startTime": 1734056030528,"endTime": 1734056030529,"refs": [],"operationName": "jdbc:mysql://127.0.0.1:3306/test/select * from t_user/executeQuery","peer": null,"spanType": "Exit","spanLayer": "DB","component": "MySQL","tags": {"remotePeer": "jdbc:mysql://127.0.0.1:3306/test","extra": "{password=, user=root}","sql": "select * from t_user"},"logs": {}},{"spanId": 0,"parentSpanId": -1,"startTime": 1734056030373,"endTime": 1734056030538,"refs": [],"operationName": "/order","peer": null,"spanType": "Entry","spanLayer": "HTTP","component": "Tomcat","tags": {"http.method": "GET","url": "/order"},"logs": {}}]
}

上述json我想应该很熟悉了,不用我过多分析,只是还有一个问题,就是serviceName为空。 熟悉SkyWalking的读者都应该知道,应用名称是在启动参数上通过 agent name 来配置的。

作者不这样做,我们可以拦截SpringBoot的启动流程,在解析到Enviroment后,将 spring.application.name 的值设置到Config,

当然,这仅限制于springboot服务生效。下节我们就来分析如何拦截springboot的Enviroment。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/64162.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

关于Vue的子组件改变父组件传来的值

一、组件直接传值 大家都知道父子组件传值的方案&#xff0c;有以下几个&#xff0c;不再详细敖述 Props&#xff1a;父组件向子组件传递数据 $emit&#xff1a;子组件通过自定义事件向父组件传递数据 .sync修饰符&#xff1a;一个方便且强大的工具&#xff0c;可以简化父子组…

Flink的Watermark水位线详解

一、Flink的时间语义 Flink有如下三种时间语义&#xff1a; Flink的三种时间语义-CSDN博客 在实际应用中&#xff0c;一般会采用事件时间语义。而正如前面所说的&#xff0c;事件时间语义需要等窗口的数据全部到齐了&#xff0c;才能进行窗口计算。那么&#xff0c;什么时候数…

ES学习Promise对象(九)

这里写目录标题 一、概念二、示例基本使用使用 Promise 对象封装Ajaxthen() 方法catch() 方法 一、概念 简单说就是一个容器&#xff0c;里面保存着某个未来才会结束的事件&#xff08;通常是一个异步操作&#xff09;的结果。Promise 是一个对象&#xff0c;Promise 提供统一…

Kibana:LINUX_X86_64 和 DEB_X86_64两种可选下载方式的区别

最近需要在vm&#xff08;操作系统是 Ubuntu 22.04.4 LTS&#xff0c;代号 Jammy。这是一个基于 x86_64 架构的 Linux 发行版&#xff09;上安装一个7.17.8版本的Kibana&#xff0c;并且不采用docker方式。 在下载的时候发现有以下两个选项&#xff0c;分别是 LINUX_X86_64 和 …

CMake 构建项目并整理头文件和库文件

本文将介绍如何使用 CMake 构建项目、编译生成库文件&#xff0c;并将头文件和库文件整理到统一的目录中以便在其他项目中使用。 1. 项目结构 假设我们正在构建一个名为 rttr 的开源库&#xff0c;初始的项目结构如下&#xff1a; D:\WorkCode\Demo\rttr-master\|- src\ …

【FAQ】HarmonyOS SDK 闭源开放能力 — Vision Kit(2)

1.问题描述&#xff1a; 人脸活体检测返回上一页App由沉浸式变为非沉浸式多了上下安全区域。 解决方案&#xff1a; 检测结束后需要自己去设置沉浸式配置。 2.问题描述&#xff1a; Vision Kit文字识别是本地识别&#xff0c;还是上传至服务器&#xff0c;由服务器来识别文…

AIA - IMSIC之二(附IMSIC处理流程图)

本文属于《 RISC-V指令集基础系列教程》之一,欢迎查看其它文章。 1 ​​​​​​​通过IMSIC接收外部中断的CSR 软件通过《AIA - 新增的CSR》描述的CSR来访问IMSIC。 machine level 的 CSR 与 IMSIC 的 machine level interrupt file 可相互互动;而 supervisor level 的 CSR…

Vue单页应用的配置

前面通过几篇文章了解并掌握了 Vue 项目构建及运行的前期工作 。接下来我们可以走进 Vue 项目的内部&#xff0c;一探其内部配置的基本构成。 1. 路由配置 由于 Vue 这类型的框架都是以一个或多个单页构成&#xff0c;在单页内部跳转并不会重新渲染 HTML 文件&#xff0c;其路…

CocosCreator-引擎案例-TS:spine

工程1&#xff1a;LoadSpine&#xff1a;简单加载spine资源 建立工程&#xff0c;在层级上建立一个空对象&#xff0c;改名spine 在spine上添加spine组件&#xff1a; 添加组件>渲染组件>spine 在spine上挂上脚本loadspine onLoad () {cc.resources.load(loadSpine/ali…

使用FreeNAS软件部署ISCSI的SAN架构存储(IP-SAN)练习题

一&#xff0c;实验用到工具分别为&#xff1a; VMware虚拟机&#xff0c;安装教程&#xff1a;VMware Workstation Pro 17 安装图文教程 FreeNAS系统&#xff0c;安装教程&#xff1a;FreeNAS-11.2-U4.1安装教程2024&#xff08;图文教程&#xff09; 二&#xff0c;新建虚…

【ANGULAR网站开发】初始环境搭建

1. 初始化angular项目 1.1 创建angular项目 需要安装npm和nodejs&#xff0c;这边不在重新安装 直接安装最新版本的angular npm install -g angular/cli安装指定大版本的angular npm install -g angular/cli181.2 启动angular 使用idea启动 控制台启动 ng serve启动成功…

lua debug相关方法详解

lua debug相关方法详解 1. debug.debug()2. debug.getinfo(func | level [, what])3. debug.getlocal(func-or-level, localindex)4. debug.setlocal(level, local_number, value)5. debug.getupvalue(func, upvalue_index)6. debug.setupvalue(func, upvalue_index, value)7. …

《计算机网络(第7版)-谢希仁》期末考试复习题和答案(总结整理)

目录 前言&#xff1a; 一、选择题。 二、填空题。 三、名词解释。 四、简答题。 前言&#xff1a; 这个自动标题自己带了序号&#xff0c;一开始想全部选项和题号都改过来的&#xff0c;结果一看一百多个全是&#xff0c;懒得改了 一、选择题。 1、广域网覆盖的地理范围…

【再谈设计模式】享元模式~对象共享的优化妙手

一、引言 在软件开发过程中&#xff0c;我们常常面临着创建大量细粒度对象的情况&#xff0c;这可能会导致内存占用过高、性能下降等问题。享元模式&#xff08;Flyweight Pattern&#xff09;就像是一位空间管理大师&#xff0c;它能够在不影响功能的前提下&#xff0c;有效地…

Milvus×EasyAi:如何用java从零搭建人脸识别应用

如何从零搭建一个人脸识别应用&#xff1f;不妨试试原生Java人工智能算法&#xff1a;EasyAi Milvus 的组合拳。 本文将使用到的软件和工具包括&#xff1a; EasyAi&#xff1a;人脸特征向量提取Milvus&#xff1a;向量数据库用于高效存储和检索数据。 01. EasyAi&#xff1a;…

NS3学习——tcpVegas算法代码详解(2)

NS3学习——tcpVegas算法代码详解&#xff08;1&#xff09;-CSDN博客 目录 4.TcpVegas类中成员函数 (5) CongestionStateSet函数 (6) IncreaseWindow函数 1.检查是否启用 Vgas 2.判断是否完成了一个“Vegas 周期” 2.1--if&#xff1a;判断RTT样本数量是否足够 2.2--e…

GitLab 将停止为中国区用户提供服务,60天迁移期如何应对? | LeetTalk Daily

“LeetTalk Daily”&#xff0c;每日科技前沿&#xff0c;由LeetTools AI精心筛选&#xff0c;为您带来最新鲜、最具洞察力的科技新闻。 GitLab作为一个广受欢迎的开源代码托管平台&#xff0c;近期宣布将停止服务中国大陆、澳门和香港地区的用户提供服务。根据官方通知&#x…

华为实训课笔记 2024 1223-1224

华为实训 12/2312/24 12/23 [Huawei]stp enable --开启STP display stp brief --查询STP MSTID Port Role STP State Protection 实例ID 端口 端口角色 端口状态 是否开启保护[Huawei]display stp vlan xxxx --查询制定vlan的生成树计算结…

企业数字化转型中如何区分“IT投入”和“业务投入”

在数字化转型的浪潮中&#xff0c;企业往往面临一个关键问题&#xff1a;如何区分“IT投入”和“业务投入”&#xff1f;在很多企业中&#xff0c;这两个概念往往被混淆&#xff0c;不少公司甚至认为“数字化转型”就是“IT的事情”&#xff0c;但实际上&#xff0c;它们之间有…

【Spring AI】Spring AI Alibaba的简单使用

提示&#xff1a;文章最后有详细的参考文档。 前提条件 SpringBoot版本为3.x以上JDK为17以上申请api-key&#xff0c;地址&#xff1a;百炼平台 引入依赖 说明&#xff1a;我的springboot版本为3.2.4&#xff0c;spring-ai-alibaba-starter版本为1.0.0-M2.1(对应spring-ai版本…