本文主要基於 SkyWalking 3.2.6 正式版
- 1. 概述
- 2. SkyWalkingAgent
- 3. SnifferConfigInitializer
- 3.1 Config
- 3.2 RemoteDownstreamConfig
- 4. Plugin
- 4.1 PluginBootstrap
- 4.2 PluginFinder
- 5. ServiceManager
- 5.1 BootService
1. 概述
本文主要分享 SkyWalking Agent 啟動初始化的過程。
SkyWalking Agent 基於 JavaAgent 機制,實現應用透明接入 SkyWalking 。關於 JavaAgent 機制,筆者推薦如下兩篇文章 :
- 《Instrumentation 新功能》
- 《JVM原始碼分析之javaagent原理完全解讀》
友情提示 :建議自己手擼一個簡單的 JavaAgent ,更容易理解 SkyWalking Agent 。
筆者練手的 JavaAgent 專案地址 :https://github.com/YunaiV/learning/tree/master/javaagent01
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` 屬性。
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 機制不熟悉,可以看下如下文章 :- 《SPI 和 ServiceLoader》
- 《跟我學Dubbo系列之Java 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 目前有七個實現類,在後續的文章,我們會解析相關實現。