歡迎光臨
每天分享高質量文章

鏈路追蹤 SkyWalking 原始碼分析 —— Agent 初始化

本文主要基於 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 目前有七個實現類,在後續的文章,我們會解析相關實現。


 

赞(0)

分享創造快樂