5、Skywalking的埋点-插件化架构设计

插件化架构设计

插件化架构另一种叫法是微内核架构,是一种面向功能进行拆分的可扩展性架构,通常用于存在多个版本、需要下载安装或激活才能使用的客户端应用;包含两类组件:核心系统(core system)和插件模块(plug-in modules)

  • 核心系统 Core System 功能比较稳定,不会因为业务功能扩展而不断修改,通常负责和具体业务功能无关的通用功能,例如模块加载等
  • 插件模块负责实现具体的业务逻辑,可以根据业务功能的需要不断地扩展,将变化部分封装在插件里面,从而达到快速灵活扩展的目的,而又不影响整体系统的稳定

如下图所示:

Skywalking的插件化实现

Skywalking中每个组件的埋点实现就是一个插件,针对有差异的版本也可能一个组件有多个实现,分别应对不同的版本。

组件加载管理的核心流程

Skywalking是对这些组件埋点插件的加载管理的大致流程如下:

  1. 初始化配置,并明确插件所在的路径。
  2. 在给定的路径下查找并解析 skywalking-plugin.def 插件文件。
  3. 通过独立的类加载器AgentClassLoader 加载插件类。
  4. 通过PluginFinder对插件进行管理分类。
  5. 使用 Byte Buddy 字节码增强库创建 AgentBuilder,其会根据已加载的插件动态增强目标类,插入埋点逻辑。
  6. 使用 JDK的SPI 加载并启动 BootService 服务。BootService就理解为通常我们编写的Service服务,就是功能的内聚封装。
  7. 添加一个 JVM 钩子,在 JVM 退出时关闭所有 BootService 服务。

下边通过关键技术点的拆解,进一步理解上述的流程。

1. 初始化配置

这里有3层配置,其过程以及覆盖原理如下:

  1. 解析/agent/config/agent.config,获取配置,填充到Config中
  2. 遍历环境变量(即 System.getProperties() 集合),查找"skywalking." 开头的配置 更新Config中的值
  3. 解析 Java Agent 的参数,更新Config中的值
2. 自定义ClassLoader

SkyWalking 的Agent 加载插件时使用到一个自定义的ClassLoader :AgentClassLoader,有了这个AgentClassLoader,就不会在应用的 Classpath 中引入 SkyWalking 的插件 jar 包,来达到对插件的管理让应用无依赖、无感知的目的。

AgentClassLoader扫描并加载指定Agent目录下的plugins和 activations 目录中的插件jar包。

3. 解析插件定义

当自定义类加载器扫描到插件jar,除了要加载类之外,还有最重要的一个目的,要明确的知道这个插件jar要增强组件中的哪些类以及如何增强,而承载这些信息的类被skywalking约定在每个插件jar包的resource目录下skywalking-plugin.def 文件中,其中其中每一行都是一个插件类的定义,如tomcat-7.x-8.x-plugin 插件中 skywalking-plugin.def 文件的内容如下:

tomcat-7.x/8.x=org.apache.skywalking.apm.plugin.tomcat78x.define 
.TomcatInstrumentation

tomcat-7.x/8.x=org.apache.skywalking.apm.plugin.tomcat78x.define
.ApplicationDispatcherInstrumentation

插件类中指定了待增强的类、方法,以及增强的逻辑,体现在AbstractClassEnhancePluginDefine类以及其内部的几个方法上:

  • enhanceClass() 方法:返回的 ClassMatch,用于匹配当前插件要增强的目标类。
  • define() :插件类增强逻辑的入口,采用了模板方法的设计模式,实现中会调用下面的 enhance() 方法和 witnessClass() 方法。
  • enhance() :真正执行增强逻辑的地方。
  • witnessClass() :一个开源组件可能有多个版本,通过该方法识别组件的不同版本,防止对不兼容的版本进行增强。
  • getConstructorsInterceptPoints() :构造方法的切入点,并指定增强的逻辑实现
  • getInstanceMethodsInterceptPoints():实例方法切入点,并指定增强的逻辑实现
  • getStaticMethodsInterceptPoints():静态方法切入点,并指定增强的逻辑实现
4. PluginFinder

JavaAgent 启动时挂在的运行机制是当一个类被首次加载的时候,会给我们机会进行字节码增强处理,即回调transform方法,在这个方法中传入被加载,待增强类,sw需找到跟这个类匹配的所有的插件类,这个工作就由PluginFinder来完成。简单来说就是根据传入的新加载的类,查找与其匹配的执行增强处理的 AbstractClassEnhancePluginDefine 集合。

5. AgentBuilder

AgentBuilder 是 Byte Buddy 库专门用来支持 Java Agent 的一个 API,其作用是方便使用者配置增强哪些类,忽略哪些package,对于要增强的类,回传给指定的transform方法执行增强,在这个transform方法中会调用PluginFinder的查找增强类的功能,找到增强类,然后通过其define方法对目标类执行增强。

6. BootService

Skywalking的Agent端,也需要跟OAPServer之间进行各种交互以提供丰富完善的功能,比如trace数据的上传,Metric数据上传,配置的拉取等等。skywalking中约定,这些功能逻辑要内聚后,封装到不同的BootService中,比如:

  • ConfigurationDiscoveryService //检测配置更新
  • KafkaJVMMetricsSender//向Kafka发送Metric
  • KafkaTraceSegmentServiceClient//通过Kafka发送Trace
  • TraceSegmentServiceClient//通过gRPC发送Trace

BootService是在Skywalking中由ServiceManager通过SPI的方式进行管理,在META-INF.services中可以看到BootService全限定名的文件,文件中列出了当前Jar包中的所有的暴露出去提供服务的BootService的实现类。

image.png

org.apache.skywalking.apm.agent.core.remote.TraceSegmentServiceClient
org.apache.skywalking.apm.agent.core.context.ContextManager
org.apache.skywalking.apm.agent.core.sampling.SamplingService
org.apache.skywalking.apm.agent.core.remote.GRPCChannelManager
org.apache.skywalking.apm.agent.core.jvm.JVMMetricsSender
org.apache.skywalking.apm.agent.core.jvm.JVMService
org.apache.skywalking.apm.agent.core.remote.ServiceManagementClient
org.apache.skywalking.apm.agent.core.context.ContextManagerExtendService
org.apache.skywalking.apm.agent.core.commands.CommandService
org.apache.skywalking.apm.agent.core.commands.CommandExecutorService
org.apache.skywalking.apm.agent.core.profile.ProfileTaskChannelService
org.apache.skywalking.apm.agent.core.profile.ProfileSnapshotSender
org.apache.skywalking.apm.agent.core.profile.ProfileTaskExecutionService
org.apache.skywalking.apm.agent.core.meter.MeterService
org.apache.skywalking.apm.agent.core.meter.MeterSender
org.apache.skywalking.apm.agent.core.context.status.StatusCheckService
org.apache.skywalking.apm.agent.core.remote.LogReportServiceClient
org.apache.skywalking.apm.agent.core.conf.dynamic.ConfigurationDiscoveryService
org.apache.skywalking.apm.agent.core.remote.EventReportServiceClient
org.apache.skywalking.apm.agent.core.ServiceInstanceGenerator

Skywalking中可以定义默认的服务并且可以定义新的服务来覆盖默认的服务,通过= BootService 上的 @DefaultImplementor@OverrideImplementor 注解来实现:

  1. @DefaultImplementor 注解用于标识 BootService 接口的默认实现。
  2. @OverrideImplementor 注解用于覆盖默认 BootService 实现,通过其 value 字段指定要覆盖的默认实现,比如KafkaJVMMetricsSender覆盖JVMMetricsSender
@OverrideImplementor(JVMMetricsSender.class)
public class KafkaJVMMetricsSender extends JVMMetricsSender 

ServiceManager 将统一初始化 BootServices 集合中的 BootService 实现,同样是在 ServiceManager#boot 方法中,会逐个调用 BootService实现的 prepare()startup()onComplete()方法

在 JVM 退出时,通过钩子关闭所有 BootService 服务,通过调用ServiceManagershutdown方法,遍历其熟悉bootServices集合,并调用他们shutdown方法来关闭所有的BootService`。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 196,264评论 5 462
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 82,549评论 2 373
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 143,389评论 0 325
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,616评论 1 267
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,461评论 5 358
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,351评论 1 273
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,776评论 3 387
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,414评论 0 255
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,722评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,760评论 2 314
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,537评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,381评论 3 315
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,787评论 3 300
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,030评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,304评论 1 252
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,734评论 2 342
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,943评论 2 336

推荐阅读更多精彩内容