SkyWalking
2025-09-16 11:18:09 0 举报
AI智能生成
SkyWalking 链路监控源码分析
作者其他创作
大纲/内容
SkyWalkingAgent.premain()<br>Agent 原理
启动方式
静态启动: 使用 -javaagent 参数
入口方法 premain()
在类加载时可以对字节码做任意修改,只要最后的结果符合字节码规范
SkyWalking 只支持这种方式启动 Agent
典型应用:APM 监控
动态附加:使用 Attach API
入口方法 agentmain()
类已经完成加载并使用,这时候只能对目标类的字节码做有限修改
不能增减父类
不能增加接口
不能更改 field
典型应用:系统诊断 Arthas,JVM-SANDBOX
启动流程
<div>SnifferConfigInitializer.initialize()<br>初始化配置<br></div>
<div>SnifferConfigInitializer.loadConfig()<br></div>读取配置文件 /config/agent.config
<div>ConfigInitializer.initialize()<br></div>将上面读取到的配置属性赋值给 Config.Class
<div>SnifferConfigInitializer.overrideConfigBySystemProp()<br></div>使用系统环境变量覆盖, 环境变量必须以 skywalking 开头<br>
<div>SnifferConfigInitializer.overrideConfigByAgentOptions()<br></div>使用 agent 参数覆盖,优先级最高
优先级从低到高
<div></div><div>new PluginFinder(new PluginBootstrap().loadPlugins())<br>加载插件并分类</div>
<div>PluginBootstrap.loadPlugins()<br></div>加载所有插件
AgentClassLoader.initDefaultLoader()<div></div><div>初始化 AgentClassLoader</div>
PluginResourcesResolver.getResources()<div></div><div>读取所有的 skywalking-plugin.def 资源文件</div>
PluginCfg.load()<div></div><div>解析文件内容, 将其封装成 PluginDefine 集合</div>
AbstractClassEnhancePluginDefine<div></div><div>使用 classloader 实例化插件对象</div>
<div>new PluginFinder()<br>在构造方法中对所有插件进行分类</div>
定制 Agent
创建 ByteBuddy 实例
指定需要忽略增强的类
BootstrapInstrumentBoost.inject()<br>把一些必要的工具类注册到 Bootstrap ClassLoader 中
BootstrapInstrumentBoost.prepareJREInstrumentation()<br>把 jdk 核心类库的动态生成的代理模板放到 classesTypeMap 中
把 skywalking 的一些核心工具类加载到 classesTypeMap
把 ByteBuddy 的一些核心工具类加载到 classesTypeMap
把 classesTypeMap 中定义的一些字节码加载到 BootstrapCL 中
定制 agentBuilder
type(pluginFinder.buildMatch())<br>指定要拦截的类, 这里构造一个巨大的插件查询条件
transform(new Transformer(pluginFinder))<br>指定 Transformer 插桩增强类<br>
with(AgentBuilder.RedefinitionStrategy.RETRANSFORMATION)<br>指定字节码增强的模式,使用 RETRANSFORMATION<br>
with(new Listener())<br>对 Transformer 后的监听, 输出日志<br>
installOn(instrumentation)<br>将 Agent 安装到 instrumentation
ServiceManager.INSTANCE.boot()<br>加载并启动服务
ServiceManager.loadAllServices()<br>加载所有服务实例,需要实现 BootService 接口
ServiceManager.load()<br>使用 serviceloader 加载所有的 BootService SPI 实例<br>
@DefaultImplementor<br>默认实现
@OverrideImplementor<br>覆盖实现
ServiceManager.prepare()<br>分别调用 prepare() 方法<br>
ServiceManager.startup()<br>分别调用 startup() 方法<br>
ServiceManager.onComplete()<br>分别调用 onComplete() 方法<br>
注册 JVM ShutdownHook
ServiceManager.shutdown()<br>分别调用 shutdown() 方法
Transformer.transform()<br>Plugin 原理
PluginFinder.find()<br>查找所有对指定类型能够生效的插件<br>
nameMatchDefine<br>直接匹配,按照类名匹配
signatureMatchDefine<br>间接匹配, 需要调用 IndirectMatch.isMatch() 方法判断<br>
AbstractClassEnhancePluginDefine.define()<br>调用插件的拦截方法, 获取拦截后的字节码<br>
witnessClasses()<br>所有插件都可以定义一些 witnessClasses
ClassEnhancePluginDefine.enhance()<br>增强目标类
ClassEnhancePluginDefine.enhanceClass()<br>增强静态方法<br>
getStaticMethodsInterceptPoints()<br>获取生效插件定义的静态方法拦截点
静态方法拦截点处理
重写入参
是 JDK 类库
不是 JDK 类库
不重写入参
是 JDK 类库
BootstrapInstrumentBoost.forInternalDelegateClass()<br>直接构造出之前放入到 BootstrapCL 中的 xx_internal 对象,也就是之前定义的模板对象<br>
InstanceMethodInterTemplate<br>假设以这个为例
InstanceMethodInterTemplate.intercept()<br>拦截处理
InstanceMethodInterTemplate.prepare()<br>JDK 的核心类库会首先调用 prepare() 方法
其它处理逻辑同静态方法
不是 JDK 类库
getMethodsInterceptor()<br>获取自定义的方法拦截点, 它是一个字符串(类限定名), 后面会反射创建实例对象<br>
StaticMethodsInter<br>使用 ByteBuddy api 将真正的代理逻辑交给这个类
StaticMethodsInter.intercept()<br>拦截处理
InterceptorInstanceLoader.load()<br>根据传入的静态方法拦截器类限定名反射创建实例对象
interceptor.beforeMethod()<br>调用拦截器的 beforeMethod() 方法<br>
zuper.call()<br>调用原方法
如果执行时抛出异常<br>调用拦截器的 handleMethodException() 异常方法
interceptor.afterMethod()<br>在 finally 中调用拦截器的 afterMethod() 方法
集合,循环处理
ClassEnhancePluginDefine.enhanceInstance()<br>增强构造方法和实例方法<br>
getConstructorsInterceptPoints()<br>获取生效插件定义的构造方法拦截点<br>
getInstanceMethodsInterceptPoints()<br>获取生效插件定义的实例方法拦截点<br>
判断当前类是否已经被增强过了, 因为不能重复定义字段, 所以这里需要判断一下<br>未增强过就给这个类定义一个字段 _$EnhancedClassField_ws 同时实现 EnhancedInstance 接口<br>最后通过 context.extendObjectCompleted() 标记已经完成了增强
构造方法拦截点处理
是 JDK 类库
不是 JDK 类库
ConstructorInter<br>使用 ByteBuddy api 将真正的代理逻辑交给这个类<br>
ConstructorInter.<init><br>在构造函数中初始化
InterceptorInstanceLoader.load()<br>根据传入的构造方法拦截器类限定名反射创建实例对象
ConstructorInter.intercept()<br>拦截处理
onConstruct()<br>当原生的构造方法执行完成后, 会调用 onConstruct() 方法<br>
实例方法拦截点处理
判断是不是声明式拦截点,有些没有办法直接定位到具体的方法名称<br>类似标注了 @RestController 都需要拦截, 但并不清楚具体的方法名称
不重写入参
是 JDK 类库
不是 JDK 类库
InstMethodsInter<br>使用 ByteBuddy api 将真正的代理逻辑交给这个类<br>
分析原理基本同静态方法
重写入参
是 JDK 类库
不是 JDK 类库
集合,循环处理
集合,循环处理
EnhanceContext.initializationStageCompleted()<br>标记这个类已经增强过, 防止重复增强(比如重复定义字段)<br>
BootService 原理
GRPCChannelManager<br>负责 Agent 到 OAP 的 GRPC 网络连接
ServiceAndEndpointRegisterClient<br>负责上报服务信息和心跳
CommandService<br>负责接收 OAP 的响应
SamplingService<br>采样是否需要上报到 OAP
JVMService<br>JVM 信息上报
TraceSegmentServiceClient<br>收集上报 trace 信息
0 条评论
下一页