天天看點

SkyWalking 源碼分析 —— Collector 初始化1. 概述2. CollectorBootStartUp2. ApplicationConfigLoader3. ModuleManager

1. 概述

本文主要分享 SkyWalking Collector 啟動初始化的過程。在分享的過程中,我們會簡單介紹 Collector 每個子產品及其用途。

ps :Collector 是 SkyWalking 的 Server 端。整體如下圖 :

FROM https://github.com/apache/incubating-skywalking
SkyWalking 源碼分析 —— Collector 初始化1. 概述2. CollectorBootStartUp2. ApplicationConfigLoader3. ModuleManager

2. CollectorBootStartUp

org.skywalking.apm.collector.boot.CollectorBootStartUp

 ,在 

apm-sniffer/apm-agent

 Maven 子產品項目裡,SkyWalking Collector 啟動入口。

#main(args)

 方法,啟動 Collector ,代碼如下 :

  • 第 45 行 :調用 

    ApplicationConfiguration#load()

     方法,加載 Collector 配置。
  • 第 47 行 :調用 

    ModuleManager#init(...)

     方法,初始化 Collector 元件們。
  • 第 60 行 :調用 

    Thread#sleep(60000)

     方法,等待 Collector 内嵌的 Jetty Server 啟動完成。

2. ApplicationConfigLoader

org.skywalking.apm.collector.boot.config.ApplicationConfigLoader

 ,實作 

org.skywalking.apm.collector.boot.config.ConfigLoader

 接口,Collector 配置( 

org.skywalking.apm.collector.core.module.ApplicationConfiguration

 )加載器。

在看具體代碼實作之前,我們先了解下 ApplicationConfiguration 整體類結構。如下圖所示 :

SkyWalking 源碼分析 —— Collector 初始化1. 概述2. CollectorBootStartUp2. ApplicationConfigLoader3. ModuleManager
  • Collector 使用元件管理器( ModuleManager ),管理多個元件( Module )。
    • 一個元件有多種元件服務提供者( ModuleProvider ),同時一個元件隻允許使用一個元件服務提供者。這塊下面會有代碼解析說明。
  • Collector 使用一個應用配置類( ApplicationConfiguration )。
    • 一個應用配置類包含多個元件配置類( ModuleConfiguration )。每個元件對應一個元件配置類。
    • 一個元件配置類包含多個元件服務提供者配置( ProviderConfiguration )。每個元件服務提供者對應一個元件配置類。注意:因為一個元件隻允許同時使用一個元件服務提供者,是以一個元件配置類隻設定一個元件服務提供者配置。
  • 整個配置檔案,對應應用配置類。綠框部分,對應一個元件配置類。紅框部分,對應一個元件服務提供者配置類。

下面,我們來看看 

ApplicationConfigLoader#load()

 方法,代碼如下 :

  • 第 47 行 :調用 

    #loadConfig()

     方法,從 

    apm-collector-core

     的 

    application.yml

     加載自定義配置。
  • 第 49 行 :調用 

    #loadDefaultConfig()

     方法,從 

    apm-collector-core

     的 

    application-default.yml

     加載預設配置。
  • 兩個方法邏輯基本一緻,已經添加代碼注釋,胖友自己閱讀了解。

3. ModuleManager

org.skywalking.apm.collector.core.module.ModuleManager

 ,元件管理器,負責元件的管理與初始化。

#init()

 方法,初始化元件們,代碼如下 :

  • 第 51 至 53 行 :調用 

    java.util.ServiceLoader#load(Module.class)

     方法,加載所有 Module 實作類的執行個體數組。ServiceManager 基于 SPI (Service Provider Interface) 機制,在每個 

    apm-collector-xxx-define

     項目的 

    /resources/META-INF.services/org.skywalking.apm.collector.core.module.Module

     檔案裡,定義了該項目 Module 的實作類。如果胖友對 SPI 機制不熟悉,可以看下如下文章 :
    • 《SPI 和 ServiceLoader》
    • 《跟我學Dubbo系列之Java SPI機制簡介》
  • 第 55 至 75 行 :周遊所有 Module 實作類的執行個體數組,建立在配置中的 Module 實作類的執行個體,并執行 Module 準備階段的邏輯,後添加到加載的元件執行個體的映射( 

    loadedModules

     )。
    • 第 59 至 67 行 :建立 Module 對象。
    • 第 69 行 :調用 

      Module#prepare(...)

       方法,執行 Module 準備階段的邏輯。在改方法内部,會建立 Module 對應的 ModuleProvider 。在 「3.1 Module」 詳細解析。
    • 第 71 行 :添加到 

      loadedModules

       。
  • 第 77 至 80 行 :校驗在配置中的 Module 實作類的執行個體都建立了,否則抛出異常。
  • 第 84 行 :調用 

    BootstrapFlow#start(...)

     方法,執行 Module 啟動邏輯。「3.4 BootstrapFlow」 詳細解析。
  • 第 86 行 :調用 

    BootstrapFlow#notifyAfterCompleted()

     方法,執行 Module 啟動完成,通知 ModuleProvider 。「3.4 BootstrapFlow」 詳細解析。
  • 總的來說,Module 初始化的過程,可以了解成三個階段,如下圖所示 :
    SkyWalking 源碼分析 —— Collector 初始化1. 概述2. CollectorBootStartUp2. ApplicationConfigLoader3. ModuleManager

3.1 Module

org.skywalking.apm.collector.core.module.Module

 ,元件抽象類。通過實作 Module 抽象類,實作不同功能的元件。目前 Collector 的 Module 實作類如下圖 :

SkyWalking 源碼分析 —— Collector 初始化1. 概述2. CollectorBootStartUp2. ApplicationConfigLoader3. ModuleManager

#name()

 抽象方法,獲得元件名。目前元件名有 :

SkyWalking 源碼分析 —— Collector 初始化1. 概述2. CollectorBootStartUp2. ApplicationConfigLoader3. ModuleManager

#providers()

 方法,獲得 ModuleProvider 數組。實際上,一個 Module 同時隻能有一個 ModuleProvider ,參見 

#provider()

 方法。

#services()

 抽象方法,獲得 Service 類數組。具體 Service 對象,在 ModuleProvider 對象裡擷取,參見 

#getService(serviceType)

 方法。

#prepare(...)

 方法,執行 Module 準備階段的邏輯,代碼如下 :

  • 第 69 行 :調用 

    java.util.ServiceLoader#load(ModuleProvider.class)

     方法,加載所有 ModuleProvider 實作類的執行個體數組。ServiceManager 基于 SPI (Service Provider Interface) 機制,在每個 

    apm-collector-xxx-yyy-provider

     項目的 

    /resources/META-INF.services/org.skywalking.apm.collector.core.module.ModuleProvider

     檔案裡,定義了該項目 ModuleProvider 的實作類。
  • 第 72 至 93 行 :周遊所有 ModuleProvider 實作類的執行個體數組,建立在配置中的 ModuleProvider 實作類的執行個體,後添加到加載的元件服務提供者執行個體的映射( 

    loadedProviders

     )。
  • 第 95 至 98 行 :校驗有 ModuleProvider 初始化,否則抛出異常。
  • 第 100 至 104 行 :調用 

    ModuleProvider#prepare(...)

     方法,執行 ModuleProvider 準備階段的邏輯。在改方法内部,會建立 ModuleProvider 對應的 Service 。在 「3.2 ModuleProvider」 詳細解析。

3.2 ModuleProvider

org.skywalking.apm.collector.core.module.ModuleProvider

 ,元件服務提供者抽象類。通過實作 ModuleProvider 抽象類,實作不同功能的元件服務提供者。目前 Collector 的 ModuleProvider 實作類如下圖 :

SkyWalking 源碼分析 —— Collector 初始化1. 概述2. CollectorBootStartUp2. ApplicationConfigLoader3. ModuleManager

#name()

 抽象方法,獲得元件服務提供者名。目前元件服務提供者名有 :

SkyWalking 源碼分析 —— Collector 初始化1. 概述2. CollectorBootStartUp2. ApplicationConfigLoader3. ModuleManager

#module()

 抽象方法,獲得 ModuleProvider 對應的 Module 類。注意,ModuleProvider 的名字可以重複,例如上圖的 

jetty

 ,通過對應的 Module 類來區分。

#requiredModules()

 抽象方法,獲得 ModuleProvider 依賴的 Module 名字數組。

———- Service 相關方法 Begin ———-

#registerServiceImplementation(Class<? extends Service>, Service)

 方法,注冊 Service 對象。一個 ModuleProvider 可以有 0 到 N 個 Service 對象。

#getService(Class<T>)

 方法,獲得 Service 對象。

#requiredCheck(...)

 方法,校驗 ModuleProvider 包含的 Service 們都建立成功。

  • 方法參數,從 

    Module#services()

     方法獲得。
  • 該方法會被 

    BootstrapFlow#start()

     方法調用,在 「3.4 BootstrapFlow」 詳細解析。

———- Service 相關方法 End ———-

#prepare(Properties)

 抽象方法,執行 ModuleProvider 準備階段的邏輯:Service 的建立,私有變量的建立等等。例如,

StorageModuleH2Provider#prepare(Properties)

 。

#start(Properties)

 抽象方法,執行 ModuleProvider 啟動階段的邏輯:私有變量的初始化等等。例如,

StorageModuleH2Provider#start(Properties)

 。

  • 該方法會被 

    BootstrapFlow#start()

     方法調用,在 「3.4 BootstrapFlow」 詳細解析。

#notifyAfterCompleted()

 抽象方法,執行 ModuleProvider 啟動完成階段的邏輯:私有變量的初始化等等。例如,

StorageModuleEsProvider#notifyAfterCompleted(Properties)

 。

  • 該方法會被 

    BootstrapFlow#notifyAfterCompleted()

     方法調用,在 「3.4 BootstrapFlow」 詳細解析。

3.3 Service

org.skywalking.apm.collector.core.module.Service

 ,服務接口。通過實作 Service 接口,實作不同功能的服務。目前 Collector 的 Service 實作類如下圖 :

SkyWalking 源碼分析 —— Collector 初始化1. 概述2. CollectorBootStartUp2. ApplicationConfigLoader3. ModuleManager

這裡有一點要注意下,實際上 Module 是與 Service “直接” 一對多的關系。中間 有一層 ModuleProvider 存在的原因是,相同 Module 可以有多種 ModuleProvider 實作,而 ModuleProvider 提供提供相同功能的 Service ,但是實作不同。

以 

apm-collector-storage

 舉例子,如下圖所示 :

SkyWalking 源碼分析 —— Collector 初始化1. 概述2. CollectorBootStartUp2. ApplicationConfigLoader3. ModuleManager
  • StorageModuleEsProvider / StorageModuleH2Provider 分别基于 ES / H2 實作,其提供存儲相同資料的不同實作。例如 :
    SkyWalking 源碼分析 —— Collector 初始化1. 概述2. CollectorBootStartUp2. ApplicationConfigLoader3. ModuleManager

一般 

collector-xxx-define

 的 

service

 包下,會定義目前子產品提供的 Service 接口,如下圖所示 :

SkyWalking 源碼分析 —— Collector 初始化1. 概述2. CollectorBootStartUp2. ApplicationConfigLoader3. ModuleManager

這也是為什麼有 

Module#services()

 和 

#requiredCheck(Class<? extends Service>[])

 這樣的方法涉及的原因。

另外,如下是 Service 接口的解釋:

The 

Service

 implementation is a service provided by its own modules.

And every {@link ModuleProvider} must provide all the given services of the {@link Module}.

3.4 BootstrapFlow

org.skywalking.apm.collector.core.module.BootstrapFlow

,元件啟動流程。

BootstrapFlow 構造方法,調用 

#makeSequence()

 方法,獲得 ModuleProvider 啟動順序,這個是該類的重點。

#start()

 方法,執行 Module 啟動邏輯。

  • 第 54 至 63 行 :校驗依賴 Module 已經都存在。
  • 第 67 行 :校驗 ModuleProvider 包含的 Service 們都建立成功。
  • 第 70 行 :調用 

    ModuleProvider#start(...)

     方法,執行 ModuleProvider 啟動階段邏輯。

#notifyAfterCompleted()

 方法,調用 

ModuleProvider#notifyAfterCompleted()

 方法,執行 ModuleProvider 啟動完成階段的邏輯。

繼續閱讀