赞
踩
agent 开发的一些心得,适合熟悉agent或者有agent开发需求的同学
1 有个基础的agent,是java 标准的agent。这是agent代码入口
2 设计包结构,
基础agent
agent下有plugin,加载plugin可以自己定义一个类加载器
plugin:插件定义具体的模块功能module,module是要加入到业务的类加载器中,因为是和业务相关的具体功能
module: 具体对业务增强的jar包
conf: 一些配置文件
3 设计类加载机制
plugin 有独立的Plugin加载器,加载plugin定义
module 会被添加到系统类加载器或者bootstrap加载器中
spring boot的项目需要对JarLauncher进行字节码增强
bootstrap层module: 将module jar放入bootstrap层类加载器完成字节码增强,具体的业务功能放到系统类加载器。
也就是有2个module,一个bootstrap层的字节码增强module,一个是具体业务的系统类加载器层module。bootstrap层module通过类加载器去加载系统类加载器层的业务module
类加载机制架构图:
4 module 功能扩展手段
4.1. 通过spi扩展机制,像spring boot dubbo都有spi扩展机制
4.2. 将开源的jar包通过类加载机制添加到业务类加载器中,相当于无侵入帮助用户完成pom文件依赖。如果代码不满足需求,可以修改源码后,在将修改后的jar加载到类加载器
4.3. 使用字节码增强工具进行字节码增强
5 独立日志设计
要有自己的独立日志打印,最好不要用log4j logback这类框架,因为可能和业务的日志打印出现冲突。
可以使用java.util.logging.Logger ,但是只能打印到控制台日志,和业务日志混合在一起了。
6 依赖包独立
agent内部依赖的公共工具包,需要通过maven-shade-plugin 插件进行打包,这样避免业务和agent使用了同一个包的不同版本,导致冲突
代码上能不依赖外部包就不依赖外部。
7 版本适配
agent作为一个公共的agent,使用agent的业务系统可能有很多不同的版本。适配的module jar也是有所不同的。
这里需要在plugin里对业务所使用的版本(dubbo/spring boot等)做个判断,根据不同的版本依赖不同的module jar
判断业务使用框架的版本: 像dubbo spring boot都有对应的Version类,如果没有Version类的,可以通过判断某个版本有某个类来判断。
8 字节码增强工具选择
asm :成熟的开源框架
bytekit:arthas内部使用的字节码工具,可以支持注解使用,屏蔽了字节码操作细节。首选
在进行字节码增强时,可以将业务逻辑直接植入字节码。也可以字节码增强去调用另外的静态方法,在静态方法里面做具体业务逻辑。
9 字节码增强延时机制设计
addTransformer(transformer,false)。只有在类首次加载时,才会触发transform进行字节码增强
addTransformer(transformer,true)。可以通过inst.retransformClasses进行再次增强,再次增强也是有限制,增强的类不能有对类基本结构(增加/修改/删除字段或方法,方法返回值不能被修改),否则增强失败。
可以在一定时间(保证业务启动成功后),调用retransformClasses 进行二次增强,用以避免增强前类就已经被加载过了。
10 热加载/卸载
字节码增强的功能: 可以通过retransformClasses 二次增强,进行热加载。redefineClasses 可以重新定义类字节码,可以把原始字节码重新加载。重新定义类不能有对类基本结构(增加/修改/删除字段或方法,方法返回值不能被修改),否则失败。
spi 扩展的功能: 没法进行热加载和协助,因为这部分是由应用启动的时候进行加载的。可以加开关,将开关配置下发来动态控制功能是否生效
采坑:
agent使用的第三方公共包和业务使用的第三方公共包有版本冲突,使用maven-shade-plugin 解决
有时候日志打印不出来,因为agent使用的日志包和业务的有冲突
和定时任务saturn框架有冲突。因为saturn框架是采用独立lib加载的方式,在对saturn lib下的类进行字节码增强后,saturn lib下的类没有办法找到在系统类加载器的agent 类。典型案例就是skywalking agent
agent增强某个类,这个类已经被加载过了,增强就不生效了。多个agent对同个类进行增强时,经常有这个问题
有个节点偶发性出现jvm异常导致pod重启,重启1-2次后正常
agent 的增强和jfr机制在并发下有bug
加入io.lettuce.core.jfr=false 解决
参考:
jdk jfr bug:https://bugs.openjdk.org/browse/JDK-8249009
lettuce jfr: https://github.com/lettuce-io/lettuce-core/wiki/Connection-Events
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。