分布式链路追踪专栏——分布式链路追踪:Skywalking 探针模型设计

这些精彩的技术类型的体系化文章,后面我会放到公众号上,并集中在合集“分布式链路追踪专栏”中,欢迎大家去订阅我的公众号和视频号“架构随笔录”,大家可以订阅合集,这样更加方便喔,后面会出电子版本,更加方便。

另外本人也出版过“Spring Cloud Alibaba微服务架构实战派上下册”的技术类书籍,另外新书“RocketMQ分布式架构实战派”即将上架。

SkyWalking 是一个开源 APM 系统,包括针对 Cloud Native 体系结构中的分布式系统的监视,跟踪,诊断功能。核心功能如下:

  • 服务、服务实例、端点指标分析

  • 根本原因分析,在运行时分析代码

  • 服务拓扑图分析

  • 服务,服务实例和端点依赖性分析

  • 检测到慢速服务和端点

  • 性能优化

  • 分布式跟踪和上下文传播

  • 数据库访问指标。检测慢速数据库访问语句(包括 SQL 语句)

  • 报警

SkyWalking 目前是 Apache 顶级项目,作为这么优秀的开源项目,它的架构设计理念肯定会有很多值得我们借鉴。

本文会包含如下内容:

  • 基于 SDK 的探针模型

  • Java Agent 字节码原理

  • Skywalking 探针模型设计

  • Skywalking 探针采集数据如何收集

本篇文章适合人群:架构师、技术专家以及对全链路监控非常感兴趣的高级工程师。

基于SDK的探针模型

基于 SDK 的探针模型,其实在我们常规的框架技术中都有使用,比如事务原理,就是最典型的场景,里面用到了动态代理,并通过 AOP 切面来完成事务逻辑的植入。那么在传统的分布式链路追踪系统中,基于 Spring Cloud 的 ZipKin 就是采用的基于 SDK 的探针模型。

分布式链路追踪专栏——分布式链路追踪:Skywalking 探针模型设计_第1张图片

ZipKin 的探针具体分布在 instrumentation 项目中,会根据不同的组件形成不同的子项目,以便业务通过 SDK 依赖探针的时候,可以比较灵活的应用各种不同的组件。

但是如果只是 ZipKin 的探针还不能完成侵入,需要封装切面,通过 SDK 零侵入到业务代码,那么是否有组件已经实现了这种解决方案呢?答案就是 Spring Cloud Sleuth。

Spring Cloud Sleuth 为分布式跟踪提供了基于 Spring Boot 的自动配置。封装了 Brave 的跟踪程序库,Brave 库又是 openzipkin 的探针组件库。Sleuth 配置业务需要的所有分布式追踪能力。包括跟踪数据(span)的传输通道、保留多少跟踪数据(采样率)、是否发送 baggage 以及具备开关功能的链路探针。

Spring Cloud Sleuth 如何上手?

第一步:将 Sleuth 添加到应用工程中

spring.application.name 定义要规范,因为在 Sleuth 整合 ZipKin 中,链路追踪的隔离级别基本都是应用级。

Sleuth 整合 ZipKin,通信通道为 HTTP。

 (1)
      
          
              org.springframework.cloud
              spring-cloud-dependencies
              ${release.train.version}
              pom
              import
          
      

 (2)
    org.springframework.cloud
    spring-cloud-starter-zipkin

Sleuth 整合 ZipKin,通信通道为 Kafka 或者 RabbitMQ。配置属性 spring.zipkin.sender.type: kafka:

 (1)
      
          
              org.springframework.cloud
              spring-cloud-dependencies
              ${release.train.version}
              pom
              import
          
      

 (2)
    org.springframework.cloud
    spring-cloud-starter-zipkin

 (3)
    org.springframework.amqp
    spring-rabbit

第二步:覆盖 Zipkin 的自动配置

通过 ZipkinAutoConfiguration.REPORTER_BEAN_NAME 和 ZipkinAutoConfiguration.SENDER_BEAN_NAME,重新定义 Bean,并覆盖原有 Zipkin 对应的 bean 的定义。

可以这样理解,Spring Cloud Sleuth 是在 Zipkin 的升级版,可以兼容 Zipkin。

Java Agent字节码原理

Java Instrumentation

从 Java 5 开始,JDK 中新增了一个 java.lang.instrument.Instrumentation 类,它提供在运行时重新加载某个类的的 class 文件的 API。

Java Agent

通过操作 Instrumentation 的 API 就可以实现不重启服务对单个类进行简单的修改。

通常有两种方式拿到 Instrumentation 对象:

  • 在 JVM 启动时指定 agent,Instrumentation 对象会通过 agent 的 premain 方法传递。

  • 在 JVM 启动后通过 JVM 提供的机制加载 agent,Instrumentation 对象会通过 agent 的 agentmain 方法传递。

Skywalking 就是通过在 JVM 启动时指定 agent,因为这样其实对于业务来说会减少一些不确定性,从用户角度,谁也不希望自己的代码被毫无感知的情况下被侵入,如果实在运行期间侵入,至少在启动的过程中能够预判一些不确定性,具体详情代码请参考:org.apache.skywalking.apm.agent.SkyWalkingAgent。

业务应用在 Skywalking 中如何被零侵入,配置属性文件 env.properties,内容如下,注意要将 skywalking-agent.jar 放到指定的路径上。

JAVA_HOME="/data/java/jdk1.8.0_161"
JAVA_PARAMS="$JAVA_PARAMS -DSW_AGENT_NAME=application-name"
JAVA_PARAMS="$JAVA_PARAMS -javaagent:/data/skywalking/skywalking-agent.jar"

然后写入 shell 脚本,并通过脚本启动程序的 jar 包。

作为一个中间件框架,Skywalking 不可能自己去造一个轮子来实现 Java Agent 字节码原理,所以它也利用了轮子 byte-buddy。

Byte Buddy 是一个代码生成和操作库,用于在 Java 应用程序运行时创建和修改 Java 类,并且无需编译器的帮助。除了 Java 类库附带的代码生成实用程序之外,Byte Buddy 允许创建任意类,而且不限于实现创建运行时代理的接口。此外,Byte Buddy 提供了一个方便的 API,可以使用 Java 代理或在构建过程中手动更改类。

为了使用字节码框架 Buddy,我们可以不需要理解 Java 字节代码或类文件格式。相反,Byte Buddy 的 API 的目标是代码简洁且易于理解。在 Buddy 中字节码仍然是完全可自定义的,甚至可以是自定义的字节代码。此外,API 是零侵入的,因此,Byte Buddy 不会在它创建的类中留下任何被侵入的痕迹。

Skywalking 如何应用和落地 Byte Buddy?答案就在如下模块包:

  • apm-agent

  • apm-agent-core

SkyWalkingAgent 类中定义了 premain 函数,传参:agentArgs 和 Instrumentation,并且通过插件加载器 PluginFinder 和 PluginBootstrap,从插件生态模块中加载各种资源。如何加载,答案就在 skywalking-plugin.def 文件。

每个插件模块的 resources 目录下面都会有一个文件 skywalking-plugin.def,文件内容如下,当然下面这个是 dubbo-2.7.x-plugin 的举例。

dubbo=org.apache.skywalking.apm.plugin.asf.dubbo.DubboInstrumentation

找到插件目录路径之后,再通过 Byte Buddy 框架构建 AgentBuilder,这个类是框架的核心,然后整个字节码植入都是这个类的功劳。

从如下的代码片段可以理解,插件需要匹配,然后通过 Transformer 将插件流转换为字节码,并植入到业务应用中。

agentBuilder.type(pluginFinder.buildMatch())
                    .transform(new Transformer(pluginFinder))
                    .with(AgentBuilder.RedefinitionStrategy.RETRANSFORMATION)
                    .with(new Listener())
                    .installOn(instrumentation);

Skywalking探针模型设计

Skywalking 的核心领域概念包括:探针、OAP 平台、UI 和存储,本文作者就会探讨探针模型及其架构。

探讨探针之前,我们得先了解探针生态,Skywalking 是如何支持探针生态的。

分布式链路追踪专栏——分布式链路追踪:Skywalking 探针模型设计_第2张图片

领域核心模型

Instrumentation

Skywalking 通过 Instrumentation 定义切面点,包括:需要增强的类域和方法域,比如要侵入 Dubbo,就会定义要侵入的 ENHANCE_CLASS 为 org.apache.dubbo.monitor.support.MonitorFilter;定义构造方法拦截点,比如 ConstructorInterceptPoint,定义实例方法拦截点,比如 InstanceMethodsInterceptPoint。当然也会有静态方法拦截点,比如 StaticMethodsInterceptPoint。

Interceptor

就如 AOP 一样,有了拦截点,就需要业务切面,所以 Skywalking 就通过拦截器来完成链路切面的功能。封装了 beforeMethod、afterMethod 和 handleMethodException 方法;这里再列举 DubboInterceptor 的功能逻辑,通过拦截 Dubbo RPC 请求中的 Invoker 和 Invocation,获取整个 RPC 请求的元数据,包括 URL 元数据,当前 Consumer 和 Provider 的服务信息,然后通过通过 RpcContext,这个 Dubbo 自己封装的上下文类(线程本地变量存储全本次请求的线程范围的信息),植入基于 Span 的链路模型数据。在切面点对应的业务方法和构造函数的前后植入链路模型,并通过 Entrance 和 Exit,来标注探针组件的链路数据的走向,完成链路数据的串联,再通过 TraceID、SpanID 以及 SegmentID 来形成树状的链路数据,并最终落地存储,关于链路模型,作者将会在另外一篇文章:《分布式链路追踪:Skywalking 的链路模型设计》做详细的分析。

从具体的细节来分析基于 SDK 的探针模型,哈哈作者最喜欢图解来分析,再次展示模型图。

分布式链路追踪专栏——分布式链路追踪:Skywalking 探针模型设计_第3张图片

 Skywalking探针采集数据如何收集

既然是分布式链路平台,那么数据收集肯定的核心功能,在 Skywalking 中,数据是通过探针侵入业务,然后通过通信通道传输到 OAP Server 端。针对每一个探针,其实收集的逻辑都不太一样,这里我就重点分析下常用技术中间件的探针数据是如何收集的。

gateway-2.1.x-plugin

Spring Cloud Gateway 是一个非常火的服务治理网关,所以 Skywalking 肯定是要支持对它的性能数据的采集。

  • 定义探针 FilteringWebHandlerInstrumentation,用于增强 org.springframework.cloud.gateway.handler.FilteringWebHandler,拦截 FilteringWebHandler 中以 handle 开头的方法。

  • 定义拦截器 FilteringWebHandlerInterceptor,在 beforeMethod 方法中植入需要采集的数据,从 allArguments 参数中,获取到当前网关路由的 ServerWebExchange,然后拼装 operationName,例如: operationName + route.getId()。

  • HttpClientOperationsSendInterceptor,创建 AbstractSpan 并设置组件类型为 ComponentsDefine.SPRING_CLOUD_GATEWAY,最后调用 ContextManager.stopSpan(span) 存储链路数据。

dubbo-2.7.x-plugin

Dubbo 框架肯定是得支持的,如何支持?

定义探针 DubboInstrumentation,并增强类 org.apache.dubbo.monitor.support.MonitorFilter,这个类是 Dubbo 服务治理的核心类,拦截的方法必须是要含有 invoke 字段。

拦截器 DubboInterceptor,通过 beforeMethod,获取到 Invoker、Invocation 和 RpcContext,然后再区分是消费者还是提供者,如果是消费者,那么就是 ExitSpan,如果是提供者就是 EntrySpan,从链路数据流向来看,消费者是出去,而提供者流量是流入。createExitSpan 和 createEntrySpan,就会植入一些性能采集指标,比如 RT 等。

jedis-2.x-plugin

定义探针-JedisInstrumentation,这个探针用于植入类 redis.clients.jedis.Jedis。

定义一批特殊处理的拦截器——最常规的拦截器就是 JedisMethodInterceptor,并通过 beforeMethod、afterMethod 和 handleMethodException 采集链路信息。

其他组件我这边就不一一列举了,可以说基本都是一样的,都是通过基于字节码的 AOP 技术来植入链路采集数据。

关于 Skywalking 探针的链路数据采集我们需要知道底层核心,我在这里就列举下:

  • StaticMethodsInter

  • ConstructorInter

  • InstMethodsInter

StaticMethodsInter

用于拦截类实例方法的实际字节 buddy 拦截器。这个类用于连接 Byte-buddy 和 Skywalking plugin。

ConstructorInter

用于拦截构造函数方法的实际字节 buddy 拦截器,然后通过自定义 intercept 方法逻辑,调用拦截器的 onConstruct 逻辑,完成基于构造函数的请求拦截。

InstMethodsInter

用于拦截实例方法的实际字节 buddy 拦截器,自定义 intercept 方法,然后再方法中国封装拦截器对 beforeMethod、handleMethodException 和 afterMethod 这三个方法的调用。

总结

本人是 Skywalking 的长期使用者和爱好者,也落地了 Skywalking 的全链路监控,但是由于时间有限,有些内容没来的及细讲,但是后续如果有时间,会出一期专题,专门去讲 Skywalking 的原理及技术栈。

游侠-胡弦——一名对技术孜孜不倦的高级码农,欢迎关注本人的微信公众号——架构随笔录。

另外我的新书RocketMQ消息中间件实战派上下册,在京东已经上架啦,目前都是5折,非常的实惠。

https://item.jd.com/14337086.html​编辑https://item.jd.com/14337086.html

RocketMQ消息中间件实战派上下册”是我既“Spring Cloud Alibaba微服务架构实战派上下册”之后,又一本历时超过1年半的巨无霸技术实战类型的书籍。

为了提高读者阅读本书的体验性,本书总共设计了十个特色,下面我一一的给技术小伙伴阐述一下。 

【特色一】由浅到深

本书将RocketMQ的技术原理和最佳实践体系化,按照由浅到深的顺序呈现给读者,使读者可以按照章节顺序按部就班地学习。当学习完全书内容之后,读者不仅能熟悉RocketMQ的核心原理,还能充分理解RocketMQ的“根”。

【特色二】技术新

本书不仅包括RocketMQ4.x4.9.2版本)的核心原理分析和最佳实践,还包括RocketMQ5.x5.1. 0版本)的新特性分析和最佳实践。

【特色三】精心设计的主线:零基础入门,循序渐进,直至彻底掌握RocketMQ

本书精心研究了程序类、架构类知识的认知规律,全书共分为6篇:基础;进阶;高级;高并发、高可用和高性能;应用;新特性,是一条相对科学的主线,让读者快速从“菜鸟”向“RocketMQ分布式架构实战高手”迈进。

【特色四】绘制了大量的图,便于读者理解RocketMQ的原理、架构、流程 

一图胜于文,书中在涉及原理、架构、流程的地方配有插图,以便读者更加直观地理解。

【特色五】从架构师和技术专家的视角分析RocketMQ 

本书创造性地分析了RocketMQ具备高并发、高可用和高性能的功能及原理,并从架构的视角展开分析,这些也是程序员进阶为技术专家或架构师必备的技能。

以下为从架构师和技术专家的视角分析RocketMQ典型案例,读者阅读完本书之后,也能够达到这样的水准。

【特色六】不仅有原理分析,还有大量的实战案例 

本书介绍了大量的实战案例,能让读者“动起来”,在实践中体会功能,而不只是一种概念上的理解。

在讲解每一个知识模块时,我在思考:在这个知识模块中,哪些是读者必须实现的“标准动作”(实例);哪些“标准动作”是可以先完成的,以求读者能快速有一个感知;哪些“标准动作”具有一定难度, 需要放到后面完成。读者在实践完书中的案例之后,就能更容易理解那些抽象的概念和原理了。

本书的目标之一是,让读者在动手中学习,而不是“看书时好像全明白了,一动手却发现什么都不会”。通过体系化的理论和实战案例去培养读者的主动学习能力,这样本书的价值就会被最大化。 

本书相信“知行合一”的理念,而不是“只知,而不行”,避免开发人员出现眼高手低的现象。尤其是在技术面试过程中,面试官更加看重的是既懂原理,又能够主动是实践技术的技术人。

【特色七】深入剖析原理 

 本书以系统思维的方式,从业务功能视角剖析 RocketMQ 底层的技术原理,使读者具备快速阅读 RocketMQ 框架源码的能力。读者只有具备了这种能力,才能举一反三,实现更复杂的功能,应对更复杂的应用场景。

 【特色八】从运维的视角分析 RocketMQ 的最佳实践

【特色九】参与开源 

 本书向读者展示了如何修改 RocketMQ 源码,并快速验证案例分析。这样,读者可以从中学到参与开源的技能,并为后续自己能够参与开源做准备。

【特色十】双色印刷,读者体验会更好 

为了提高读者阅读本书的体验,在有上下两册的前提下(巨无霸,超过800页),出版社不吝啬印刷成本,依然采用双色印刷。

【推荐】本书的最佳学习路径 

 为了提高读者学习RocketMQ的效率,我这边结合我自身从RocketMQ小白到RocketMQ专家的经历,为读者汇总了一条最佳学习路径。

【寄语】作者寄语 

RocketMQ是我深度参与研究的一款开源消息中间件,无论是从源码,还是架构场景,我都提炼了很多最佳实践。

在开源领域,技术小伙伴可以使用的开源消息中间件非常的多,比如KafkaPulsar等,我之所以选择研究RocketMQ,除了工作内容和角色需要之外,更多的还是自己感兴趣,因此我建议技术小伙伴一定要先培养自己的兴趣,兴趣才是提升技术硬实力的第1要素。

当然我并不止研究了RocketMQ,还研究了PulsarKafka等(包括开源消息中间件生态中的主流框架),只是本书作为一本关于RocketMQ实战派的书籍,我必须要以RocketMQ为主。

假如技术小伙伴想成为Java领域的架构师或者技术专家,我强烈建议你去研究RocketMQ,它会给你带来很多意想不到的技术和架构方法论的收获,这个也是我写本书的主要目的之一。

建议技术小伙伴按照本书设计的学习路线,逐章的去阅读和实战,这样学习效果会更好。

如果技术小伙伴有技术交流的,可以通过博文视点官方的读者群找到我的联系方式,并与我沟通,我会实时的解答读者的疑问。

本文公众号“架构随笔录”

本人视频号“架构随笔录”

【博文视点】2021年度优秀作者

2021年我和博文视点合作了一本技术类型的书籍“Spring Cloud Alibaba微服务架构实战派上下册”,它是我涉足知识输出领域以来的第一本书,同时它也是我自己积累的技术池中部分技术的产出。

为了写好那本书,我几乎花费了所有的休息时间,并主动的承担了书的售后技术辅导和咨询的职责(几乎是有问必答,坚持了整整两年)。

所谓有付出总会有回报,Alibaba这本书的销量还不错,我也因此获得了博文视点颁发的2021年度优秀作者。

我很清楚,这个是博文视点为了鼓励我继续去用心写书,因此我又花了接近1年半的时间去写了RocketMQ消息中间件实战派上下册这本书。

所谓一分耕耘一份收获,我将我对RocketMQ的理解体系化的输出给喜欢技术的技术人,希望真的对大家有帮助。

 【博文视点】2023技术成长领路人

2022年,我开始涉足技术直播和技术讲师领域,并和博文视点合作几次技术直播,直播效果还不错,再加上我孜孜不倦的布道“Spring Cloud Alibaba微服务架构实战派上下册”这本书相关的技术,并且这些技术都是有助于“技术人”快速成长的,因此也获得了博文视点颁发的“2023技术成长领路人”这个技术奖项,这个奖项也是为了鼓励我继续通过技术直播的方式给技术人去布道技术,因此只要我有时间,我就会孜孜不倦的去讲和聊技术。

【四维口袋】2022 KVP最具价值技术专家 

2022年,我开始涉足企业培训和相关技术直播,并和“四维口袋”合作了几次技术直播,并荣获了2022 KVP最具价值技术专家的技术奖项。

你可能感兴趣的:(分布式链路追踪,Spring,Cloud,Alibaba,分布式,skywalking)