摘要: 原创出处 www.iocoder.cn/SkyWalking/… 「芋道源码」欢迎转载,保留摘要,谢谢!
本文主要基于 SkyWalking 3.2.6 正式版
🙂🙂🙂关注微信公众号:【芋道源码】有福利:
- RocketMQ / MyCAT / Sharding-JDBC 所有源码分析文章列表
- RocketMQ / MyCAT / Sharding-JDBC 中文注释源码 GitHub 地址
- 您对于源码的疑问每条留言都将得到认真回复。甚至不知道如何读源码也可以请教噢。
- 新的源码解析文章实时收到通知。每周更新一篇左右。
- 认真的源码交流微信群。
1. 概述
本文主要分享 SkyWalking Agent 启动初始化的过程。
SkyWalking Agent 基于 JavaAgent 机制,实现应用透明接入 SkyWalking 。关于 JavaAgent 机制,笔者推荐如下两篇文章 :
友情提示 :建议自己手撸一个简单的 JavaAgent ,更容易理解 SkyWalking Agent 。
笔者练手的 JavaAgent 项目地址 :github.com/YunaiV/lear…
2. SkyWalkingAgent
org.skywalking.apm.agent.SkyWalkingAgent ,在 apm-sniffer/apm-agent Maven 模块项目里,SkyWalking Agent 启动入口。为什么说它是启动入口呢?在 apm-sniffer/apm-agent 的 pom.xml 文件的【第 73 行】,我们可以看到 SkyWalkingAgent 被配置成 JavaAgent 的 PremainClass 。
#premain(...) 方法,代码如下 :
- 第 58 行 :调用
SnifferConfigInitializer#initialize()方法,初始化 Agent 配置。 - 第 61 行 :调用
PluginBootstrap#loadPlugins()方法,加载 Agent 插件们。而后,创建 PluginFinder 。 - 第 64 行 :调用
ServiceManager#boot()方法,初始化 Agent 服务管理。在这过程中,Agent 服务们会被初始化。 - 第 79 至 133 行 :基于 byte-buddy ,初始化 Instrumentation 的
java.lang.instrument.ClassFileTransformer。
3. SnifferConfigInitializer
org.skywalking.apm.agent.core.conf.SnifferConfigInitializer ,Agent 配置初始化器。
在看具体代码实现之前,我们先看下 org.skywalking.apm.agent.core.conf 包的大体结构 :
配置类有 Config 和 RemoteDownstreamConfig 两种。从命名上可以看出 :
- Config 为 Agent 本地配置类,使用 SnifferConfigInitializer 进行初始化。
- RemoteDownstreamConfig 为 Agent 远程配置类,从 Collector Server 读取。
#initialize() 方法,初始化 Agent
本地配置,代码如下 :
- 第 59 至 67 行 :从配置文件(
agent.config) 加载配置。配置文件所在固定路径为${AGENT_PACKAGE_PATH}/config/agent.config,其中${AGENT_PACKAGE_PATH}通过org.skywalking.apm.agent.core.boot.AgentPackagePath初始化。Agent 整理目录如下图 : - 第 70 至 74 行 :从环境变量覆盖配置。环境变量 Key 需以
"skywalking."开头。例如,Config.Agent.APPLICATION_CODE在agent.config为agent.application_code,环境变量为skywalking.agent.application_code。另外,环境变量包括 JVM 进程的和系统的。 - 第 77 至 82 行 :校验配置是否正确加载。
3.1 Config
org.skywalking.apm.agent.core.conf.Config ,Agent 本地配置类。
打开 Config ,我们会看到拆分了 Agent / Collector / Jvm / Buffer / Dictionary / Logging / Plugin 七个小类。如下图 :
本文暂不对配置项详细解析,胖友可以看下每个属性的英文注释。
3.2 RemoteDownstreamConfig
org.skywalking.apm.agent.core.conf.RemoteDownstreamConfig ,Agent 远程配置类。
打开 RemoteDownstreamConfig ,我们会看到拆分了 Agent / Collector 两小类。如下图 :
本文暂不对配置项详细解析,胖友可以看下每个属性的英文注释。
4. Plugin
SkyWalking Agent 提供了多种插件,实现不同框架的透明接入 SkyWalking 。在 《官方文档 —— supported list》 里,有目前的插件列表。
另外,在 apm-sniffer/apm-sdk-plugin 目录下,有插件的实现代码 :
本小节会分享的较为简单,在 《SkyWalking 源码分析 —— Agent 插件体系》 详细解析。
4.1 PluginBootstrap
org.skywalking.apm.agent.core.plugin.PluginBootstrap ,插件引导程序类,创建需要加载的插件对象数组。
#loadPlugins() 方法,代码如下 :
- 第 47 行 :初始化 AgentClassLoader 。
- 第 50 至 56 行 :获得插件定义路径数组。
- 第 59 至 66 行 :获得插件定义(
org.skywalking.apm.agent.core.plugin.PluginDefine)数组。 - 第 69 至 82 行 :创建类增强插件定义(
org.skywalking.apm.agent.core.plugin.AbstractClassEnhancePluginDefine)对象数组。不同插件通过实现 AbstractClassEnhancePluginDefine 抽象类,定义不同框架的切面,记录调用链路。以 Spring 插件为例子,如下是相关类图 :
4.2 PluginFinder
org.skywalking.apm.agent.core.plugin.PluginFinder ,插件发现者。其提供 #find(...) 方法,获得类增强插件定义( org.skywalking.apm.agent.core.plugin.AbstractClassEnhancePluginDefine )对象。
PluginFinder 构造方法,代码如下 :
- 第 57 至 77 行 :循环 AbstractClassEnhancePluginDefine 对象数组,添加到
nameMatchDefine/signatureMatchDefine属性,方便#find(...)方法查找 AbstractClassEnhancePluginDefine 对象。- 第 65 至 72 行 :处理 NameMatch 为匹配的 AbstractClassEnhancePluginDefine 对象,添加到
nameMatchDefine属性。 - 第 74 至 76 行 :处理非 NameMatch 为匹配的 AbstractClassEnhancePluginDefine 对象,添加到
signatureMatchDefine属性。
- 第 65 至 72 行 :处理 NameMatch 为匹配的 AbstractClassEnhancePluginDefine 对象,添加到
5. ServiceManager
org.skywalking.apm.agent.core.boot.ServiceManager ,BootService 管理器。负责管理、初始化 BootService 实例们。
#boot() 方法,代码如下 :
-
第 47 行 :调用
#loadAllServices()方法,加载所有 BootService 实现类的实例数组。ServiceManager 基于 SPI (Service Provider Interface) 机制,在 /resources/META-INF.services/org.skywalking.apm.agent.core.boot.BootService 文件里,定义了所有 BootService 的实现类。如果胖友对 SPI 机制不熟悉,可以看下如下文章 : -
第 50 行 :调用
#beforeBoot()方法,调用每个BootService#beforeBoot()方法。 - 第 52 行 :调用
#startup()方法,调用每个BootService#boot()方法。 - 第 54 行 :调用
#afterBoot()方法,调用每个BootService#afterBoot()方法。
5.1 BootService
org.skywalking.apm.agent.core.boot.BootService ,Agent 启动服务接口,定义了 #beforeBoot() / #boot() / #afterBoot() / #shutdown() 接口方法。
BootService 目前有七个实现类,在后续的文章,我们会解析相关实现。
666. 彩蛋
每次写初始化相关的文章,写少了,怕太水;写多了,又怕太复杂。
嗯,送一发妹子。
胖友,分享个朋友圈可好?