1. 概述

本文主要分享 SkyWalking Collector 启动初始化的过程。在分享的过程中,我们会简单介绍 Collector 每个模块及其用途。

ps :Collector 是 SkyWalking 的 Server 端。整体如下图 :

FROM https://github.com/apache/incubating-skywalking 

2. CollectorBootStartUp

org.skywalking.apm.collector.boot.CollectorBootStartUp ,在 apm-sniffer/apm-agentMaven 模块项目里,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 整体类结构。如下图所示 :

  • 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 初始化的过程,可以理解成三个阶段,如下图所示 :

3.1 Module

org.skywalking.apm.collector.core.module.Module ,组件抽象类。通过实现 Module 抽象类,实现不同功能的组件。目前 Collector 的 Module 实现类如下图 :

#name() 抽象方法,获得组件名。目前组件名有 :

#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 实现类如下图 :

#name() 抽象方法,获得组件服务提供者名。目前组件服务提供者名有 :

#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 实现类如下图 :

这里有一点要注意下,实际上 Module 是与 Service "直接" 一对多的关系。中间 有一层 ModuleProvider 存在的原因是,相同 Module 可以有多种 ModuleProvider 实现,而 ModuleProvider 提供提供相同功能的 Service ,但是实现不同。

以 apm-collector-storage 举例子,如下图所示 :

  • StorageModuleEsProvider / StorageModuleH2Provider 分别基于 ES / H2 实现,其提供存储相同数据的不同实现。例如 :

一般 collector-xxx-define 的 service 包下,会定义当前模块提供的 Service 接口,如下图所示 :

这也是为什么有 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 启动完成阶段的逻辑。

4. Module 实现类简介

  • Naming Module :《SkyWalking 源码分析 —— Collector Naming Server 命名服务》

  • UI Module :

    • 《SkyWalking 源码分析 —— 运维界面(一)之应用视角》

    • 《SkyWalking 源码分析 —— 运维界面(二)之应用实例视角》

    • 《SkyWalking 源码分析 —— 运维界面(三)之链路追踪视角》

    • 《SkyWalking 源码分析 —— 运维界面(四)之操作视角》

  • Queue Module :《SkyWalking 源码分析 —— Collector Queue 队列组件》

  • Cache Module :《SkyWalking 源码分析 —— Collector Cache 缓存组件》

  • Cluster Module :《SkyWalking 源码分析 —— Collector Cluster 集群管理》

  • Component Libraries :《SkyWalking 源码分析 —— Collector Client Component 客户端组件》 、《SkyWalking 源码分析 —— Collector Server Component 服务器组件》

  • Core :

    • 《SkyWalking 源码分析 —— Collector Storage 存储组件》「2. apm-collector-core」

    • 《SkyWalking 源码分析 —— Collector 初始化》「3. ModuleManager」

  • Storage Module :《SkyWalking 源码分析 —— Collector Storage 存储组件》

    • 《SkyWalking 源码分析 —— Collector Streaming Computing 流式处理(一)》「2. apm-collector-core/graph」

    • 《SkyWalking 源码分析 —— Collector Streaming Computing 流式处理(二)》「2. Data」

  • Agent Module :参见 Agent Streaming Computing 。

  • Jetty Manager Module :《SkyWalking 源码分析 —— Collector Jetty Server Manager》

  • gRPC Manager Module :《SkyWalking 源码分析 —— Collector gRPC Server Manager》

  • Agent Streaming Computing :

    • 《SkyWalking 源码分析 —— Collector Streaming Computing 流式处理(一)》「2. apm-collector-core/graph」

    • 《SkyWalking 源码分析 —— Collector Streaming Computing 流式处理(二)》「2. Data」

    • 《SkyWalking 源码分析 —— Collector Remote 远程通信服务》

    • 《SkyWalking 源码分析 —— Agent 收集 Trace 数据》

    • 《SkyWalking 源码分析 —— Agent 发送 Trace 数据》

    • 《SkyWalking 源码分析 —— Collector 接收 Trace 数据》

    • 《SkyWalking 源码分析 —— Collector 存储 Trace 数据》

  • Baseline Module :TODO 【4001】

  • Alerting Module :TODO 【4001】


©著作权归作者所有:来自51CTO博客作者mb5ff80520dfa04的原创作品,如需转载,请注明出处,否则将追究法律责任

更多相关文章

  1. 链路追踪 SkyWalking 源码分析 —— Collector Storage 存储组件
  2. 链路追踪 SkyWalking 源码分析 —— Collector Cache 缓存组件
  3. DoDAF2.0方法论探究
  4. http协议请求方法都有哪些?网络安全学习提升
  5. 超实用的VueJS滑块组件,支持级联滑动和渐变色
  6. 【前端词典】8 个提高 JS 性能的方法
  7. AngularJS 日期时间选择组件(附详细使用方法)
  8. 5 种方法教你用Python玩转histogram直方图
  9. IDEA Debug 无法进入断点的解决方法

随机推荐

  1. Android(安卓)8.1 锁屏界面 壁纸半透明改
  2. 23.《Android安全攻防权威指南》笔记
  3. Android下native code(C++)的编译,NDK的使用
  4. android每日一问【2011-09-17】
  5. Android(安卓)Spinner 文字居中、其下拉
  6. How to discovery memory usage on my ap
  7. Android Studio官方文档之Android Studio
  8. android log日志工具的使用
  9. Android技能树 — 树基础知识小结(一)
  10. Android 消息推送