微服务框架(十六)Spring Boot及Dubbo zipkin 链路追踪组件埋点

本文涉及的产品
可观测链路 OpenTelemetry 版,每月50GB免费额度
简介: 此系列文章将会描述Java框架Spring Boot、服务治理框架Dubbo、应用容器引擎Docker,及使用Spring Boot集成Dubbo、Mybatis等开源框架,其中穿插着Spring Boot中日志切面等技术的实现,然后通过gitlab-CI以持续集成为Docker镜像。 本文第一部分为调用链、OpenTracing、Zipkin和Jeager的简述;第二部分为Spring Boot及Dubbo zipkin 链路追踪组件埋点

  此系列文章将会描述Java框架Spring Boot、服务治理框架Dubbo、应用容器引擎Docker,及使用Spring Boot集成Dubbo、Mybatis等开源框架,其中穿插着Spring Boot中日志切面等技术的实现,然后通过gitlab-CI以持续集成为Docker镜像。
  本文第一部分为调用链、OpenTracing、Zipkin和Jeager的简述;第二部分为Spring Boot及Dubbo zipkin 链路追踪组件埋点

本系列文章中所使用的框架版本为Spring Boot 2.0.3-RELEASE,Spring 5.0.7-RELEASE,Dubbo 2.6.2。

调用链

在广义上,一个调用链代表一个事务或者流程在(分布式)系统中的执行过程。在 OpenTracing 标准中,调用链是多个 Span 组成的一个有向无环图Directed Acyclic Graph,简称 DAG),每一个 Span代表调用链中被命名并计时的连续性执行片段。

下图是一个分布式调用的例子:客户端发起请求,请求首先到达负载均衡器,接着经过认证服务、计费服务,然后请求资源,最后返回结果。

数据被采集存储后,分布式追踪系统一般会选择使用包含时间轴的时序图来呈现这个调用链。

OpenTracing

为了解决不同的分布式追踪系统 API 不兼容的问题,诞生了 OpenTracing 规范。
OpenTracing 是一个轻量级的标准化层,它位于应用程序/类库追踪或日志分析程序之间。

+-------------+  +---------+  +----------+  +------------+
| Application |  | Library |  |   OSS    |  |  RPC/IPC   |
|    Code     |  |  Code   |  | Services |  | Frameworks |
+-------------+  +---------+  +----------+  +------------+
       |              |             |             |
       |              |             |             |
       v              v             v             v
  +------------------------------------------------------+
  |                     OpenTracing                      |
  +------------------------------------------------------+
     |                |                |               |
     |                |                |               |
     v                v                v               v
+-----------+  +-------------+  +-------------+  +-----------+
|  Tracing  |  |   Logging   |  |   Metrics   |  |  Tracing  |
| System A  |  | Framework B |  | Framework C |  | System D  |
+-----------+  +-------------+  +-------------+  +-----------+

OpenTracing 的优势

  • OpenTracing 已进入 CNCF,正在为全球的分布式追踪,提供统一的概念和数据标准。
  • OpenTracing 通过提供平台无关、厂商无关的 API,使得开发人员能够方便的添加(或更换)追踪系统的实现。

Zipkin

Zipkin是一种分布式跟踪系统。它有助于收集解决微服务架构中的延迟问题所需的时序数据。它管理这些数据的收集和查找。Zipkin的设计基于 Google Dapper论文。

Jeager

Jaeger受DapperOpenZipkin的启发,是Uber Technologies公开发布的分布式跟踪系统。它用于监视和排除基于微服务的分布式系统,包括:

  • 分布式上下文传播
  • 分布式事务监控
  • 根本原因分析
  • 服务依赖分析
  • 性能/延迟优化

Uber发表了一篇博客文章[Evolving Distributed Tracing at Uber],在那里他们解释了Jaeger所做的架构性选择的历史和原因

依赖

brave依赖

<properties>
     <brave.version>5.4.2</brave.version>
     <zipkin-reporter.version>2.7.9</zipkin-reporter.version>
 </properties>

 <dependencyManagement>
     <dependencies>
         <!-- 引入 zipkin brave 的 BOM 文件 -->
         <dependency>
             <groupId>io.zipkin.brave</groupId>
             <artifactId>brave-bom</artifactId>
             <version>${brave.version}</version>
             <type>pom</type>
             <scope>import</scope>
         </dependency>

         <!-- 引入 zipkin repoter 的 BOM 文件 -->
         <dependency>
             <groupId>io.zipkin.reporter2</groupId>
             <artifactId>zipkin-reporter-bom</artifactId>
             <version>${zipkin-reporter.version}</version>
             <type>pom</type>
             <scope>import</scope>
         </dependency>
     </dependencies>
 </dependencyManagement>

 <dependencies>
     <!-- 1. brave 的 spring bean 支持 -->
     <dependency>
         <groupId>io.zipkin.brave</groupId>
         <artifactId>brave-spring-beans</artifactId>
         <version>${brave.version}</version>
     </dependency>

     <!-- 2. 在 SLF4J 的 MDC (Mapped Diagnostic Context) 中支持 traceId 和 spanId -->
     <dependency>
         <groupId>io.zipkin.brave</groupId>
         <artifactId>brave-context-slf4j</artifactId>
         <version>${brave.version}</version>
     </dependency>

     <!-- 3. 使用 okhttp3 作为 reporter -->
     <dependency>
         <groupId>io.zipkin.reporter2</groupId>
         <artifactId>zipkin-sender-okhttp3</artifactId>
         <version>${zipkin-reporter.version}</version>
     </dependency>
 </dependencies>

Dubbo & brave

<!-- 1. brave 对 dubbo 的集成 -->
<dependency>
    <groupId>io.zipkin.brave</groupId>
    <artifactId>brave-instrumentation-dubbo-rpc</artifactId>
    <version>${brave.version}</version>
</dependency>

Spring web & brave

<!-- brave 对 spring web 的集成 -->
<dependency>
    <groupId>io.zipkin.brave</groupId>
    <artifactId>brave-instrumentation-spring-web</artifactId>
    <version>${brave.version}</version>
</dependency>
<dependency>
    <groupId>io.zipkin.brave</groupId>
    <artifactId>brave-instrumentation-spring-webmvc</artifactId>
    <version>${brave.version}</version>
</dependency>

使用方法

zipkin

zipkin.url = http://<domain>/api/v2/spans?userName=<username>&userKey=<userkey>

Spring bean 注入

  • @ComponentScan
  • 配置 autoconfigurespring.factories)。
org.springframework.boot.autoconfigure.EnableAutoConfiguration=brave.webmvc.TracingConfiguration

服务端

dubbo.provider.filter=tracing

客户端

dubbo.consumer.filter=tracing
tracing为链路追踪filter组件启用

插件埋点

RPC插件埋点

通过brave.dubbo.rpcTracingFilter实现Dubbo Filter接口,注入对应的spring bean

@Configuration
public class TracingConfiguration {

    @Value("${zipkin.url}")
    private String url;

    /**
     * Configuration for how to send spans to Zipkin
     */
    @Bean
    Sender sender() {
        return OkHttpSender.create(url);
    }

    /**
     * Configuration for how to buffer spans into messages for Zipkin
     */
    @Bean
    AsyncReporter<Span> spanReporter() {
        return AsyncReporter.create(sender());
    }

    /**
     * Controls aspects of tracing such as the name that shows up in the UI
     */
    @Bean
    Tracing tracing(@Value("${spring.application.name}") String serviceName) {
        return Tracing.newBuilder()
                .localServiceName(serviceName)
                .propagationFactory(ExtraFieldPropagation.newFactory(B3Propagation.FACTORY, "user-name"))
                .currentTraceContext(ThreadLocalCurrentTraceContext.newBuilder()
                        .addScopeDecorator(MDCScopeDecorator.create())
                        .build()
                )
                .spanReporter(spanReporter()).build();
    }
}

HTTP插件埋点

通过brave.servletTracingFilter实现Servlet Filter接口,注入对应的spring bean

@Configuration
@Import(SpanCustomizingAsyncHandlerInterceptor.class)
public class HttpTracingConfiguration {


    @Value("${zipkin.url}")
    private String url;

    /**
     * Configuration for how to send spans to Zipkin
     */
    @Bean
    Sender sender() {
        return OkHttpSender.create(url);
    }

    /**
     * Configuration for how to buffer spans into messages for Zipkin
     */
    @Bean
    AsyncReporter<Span> spanReporter() {
        return AsyncReporter.create(sender());
    }

    /**
     * Controls aspects of tracing such as the name that shows up in the UI
     */
    @Bean
    Tracing tracing(@Value("${spring.application.name}") String serviceName) {
        return Tracing.newBuilder()
                .localServiceName(serviceName)
                .propagationFactory(ExtraFieldPropagation.newFactory(B3Propagation.FACTORY, "user-name"))
                .currentTraceContext(ThreadLocalCurrentTraceContext.newBuilder()
                        .addScopeDecorator(MDCScopeDecorator.create())
                        .build()
                )
                .spanReporter(spanReporter()).build();
    }

    /**
     * decides how to name and tag spans. By default they are named the same as the http method.
     */
    @Bean
    HttpTracing httpTracing(Tracing tracing) {
        return HttpTracing.create(tracing);
    }

    /**
     * Creates client spans for http requests
     * <p>
     * We are using a BPP as the Frontend supplies a RestTemplate bean prior to this configuration
     */
    @Bean
    BeanPostProcessor connectionFactoryDecorator(final BeanFactory beanFactory) {
        return new BeanPostProcessor() {
            @Override
            public Object postProcessBeforeInitialization(Object bean, String beanName) {
                return bean;
            }

            @Override
            public Object postProcessAfterInitialization(Object bean, String beanName) {
                if (!(bean instanceof RestTemplate)) {
                    return bean;
                }
                RestTemplate restTemplate = (RestTemplate) bean;
                List<ClientHttpRequestInterceptor> interceptors =
                        new ArrayList<>(restTemplate.getInterceptors());
                interceptors.add(0, getTracingInterceptor());
                restTemplate.setInterceptors(interceptors);
                return bean;
            }

            // Lazy lookup so that the BPP doesn't end up needing to proxy anything.
            ClientHttpRequestInterceptor getTracingInterceptor() {
                return TracingClientHttpRequestInterceptor.create(beanFactory.getBean(HttpTracing.class));
            }
        };
    }

    /**
     * Creates server spans for http requests
     */
    @Bean
    Filter tracingFilter(HttpTracing httpTracing) {
        return TracingFilter.create(httpTracing);
    }
}

参考资料:

  1. 链路追踪 Tracing Analysis
  2. 在 Dubbo 中使用 Zipkin
  3. 分布式系统调用跟踪实践
  4. Zipkin vs Jaeger: Getting Started With Tracing
  5. Zipkin官方文档
  6. Jeager官方文档
  7. 开放分布式追踪(OpenTracing)入门与 Jaeger 实现
  8. 全链路监控(一):方案概述与比较
相关实践学习
基于OpenTelemetry构建全链路追踪与监控
本实验将带领您快速上手可观测链路OpenTelemetry版,包括部署并接入多语言应用、体验TraceId自动注入至日志以实现调用链与日志的关联查询、以及切换调用链透传协议以满足全链路打通的需求。
分布式链路追踪Skywalking
Skywalking是一个基于分布式跟踪的应用程序性能监控系统,用于从服务和云原生等基础设施中收集、分析、聚合以及可视化数据,提供了一种简便的方式来清晰地观测分布式系统,具有分布式追踪、性能指标分析、应用和服务依赖分析等功能。 分布式追踪系统发展很快,种类繁多,给我们带来很大的方便。但在数据采集过程中,有时需要侵入用户代码,并且不同系统的 API 并不兼容,这就导致了如果希望切换追踪系统,往往会带来较大改动。OpenTracing为了解决不同的分布式追踪系统 API 不兼容的问题,诞生了 OpenTracing 规范。OpenTracing 是一个轻量级的标准化层,它位于应用程序/类库和追踪或日志分析程序之间。Skywalking基于OpenTracing规范开发,具有性能好,支持多语言探针,无侵入性等优势,可以帮助我们准确快速的定位到线上故障和性能瓶颈。 在本套课程中,我们将全面的讲解Skywalking相关的知识。从APM系统、分布式调用链等基础概念的学习加深对Skywalking的理解,从0开始搭建一套完整的Skywalking环境,学会对各类应用进行监控,学习Skywalking常用插件。Skywalking原理章节中,将会对Skywalking使用的agent探针技术进行深度剖析,除此之外还会对OpenTracing规范作整体上的介绍。通过对本套课程的学习,不止能学会如何使用Skywalking,还将对其底层原理和分布式架构有更深的理解。本课程由黑马程序员提供。
相关文章
|
22天前
|
Cloud Native Java Nacos
微服务时代的新宠儿!Spring Cloud Nacos实战指南,带你玩转服务发现与配置管理,拥抱云原生潮流!
【8月更文挑战第29天】Spring Cloud Nacos作为微服务架构中的新兴之星,凭借其轻量、高效的特点,迅速成为服务发现、配置管理和治理的首选方案。Nacos(命名和配置服务)由阿里巴巴开源,为云原生应用提供了动态服务发现及配置管理等功能,简化了服务间的调用与依赖管理。本文将指导你通过五个步骤在Spring Boot项目中集成Nacos,实现服务注册、发现及配置动态管理,从而轻松搭建出高效的微服务环境。
93 0
|
22天前
|
Dubbo Java 应用服务中间件
💥Spring Cloud Dubbo火爆来袭!微服务通信的终极利器,你知道它有多强大吗?🔥
【8月更文挑战第29天】随着信息技术的发展,微服务架构成为企业应用开发的主流模式,而高效的微服务通信至关重要。Spring Cloud Dubbo通过整合Dubbo与Spring Cloud的优势,提供高性能RPC通信及丰富的生态支持,包括服务注册与发现、负载均衡和容错机制等,简化了服务调用管理并支持多种通信协议,提升了系统的可伸缩性和稳定性,成为微服务通信领域的优选方案。开发者仅需关注业务逻辑,而无需过多关心底层通信细节,使得Spring Cloud Dubbo在未来微服务开发中将更加受到青睐。
45 0
|
14天前
|
缓存 Java 应用服务中间件
随着微服务架构的兴起,Spring Boot凭借其快速开发和易部署的特点,成为构建RESTful API的首选框架
【9月更文挑战第6天】随着微服务架构的兴起,Spring Boot凭借其快速开发和易部署的特点,成为构建RESTful API的首选框架。Nginx作为高性能的HTTP反向代理服务器,常用于前端负载均衡,提升应用的可用性和响应速度。本文详细介绍如何通过合理配置实现Spring Boot与Nginx的高效协同工作,包括负载均衡策略、静态资源缓存、数据压缩传输及Spring Boot内部优化(如线程池配置、缓存策略等)。通过这些方法,开发者可以显著提升系统的整体性能,打造高性能、高可用的Web应用。
43 2
|
15天前
|
Cloud Native 安全 Java
Micronaut对决Spring Boot:谁是微服务领域的王者?揭秘两者优劣,选对框架至关重要!
【9月更文挑战第5天】近年来,微服务架构备受关注,Micronaut和Spring Boot成为热门选择。Micronaut由OCI开发,基于注解的依赖注入,内置多种特性,轻量级且启动迅速;Spring Boot则简化了Spring应用开发,拥有丰富的生态支持。选择框架需考虑项目需求、团队经验、性能要求及社区支持等因素。希望本文能帮助您选择合适的微服务框架,助力您的软件开发项目取得成功!
59 2
|
19天前
|
Java 微服务 Spring
驾驭复杂性:Spring Cloud在微服务构建中的决胜法则
【8月更文挑战第31天】Spring Cloud是在Spring Framework基础上打造的微服务解决方案,提供服务发现、配置管理、消息路由等功能,适用于构建复杂的微服务架构。本文介绍如何利用Spring Cloud搭建微服务,包括Eureka服务发现、Config Server配置管理和Zuul API网关等组件的配置与使用。通过Spring Cloud,可实现快速开发、自动化配置,并提升系统的伸缩性和容错性,尽管仍需面对分布式事务等挑战,但其强大的社区支持有助于解决问题。
31 0
|
4月前
|
JSON Dubbo Java
微服务框架(二十)Dubbo Spring Boot 生产就绪特性
  此系列文章将会描述Java框架Spring Boot、服务治理框架Dubbo、应用容器引擎Docker,及使用Spring Boot集成Dubbo、Mybatis等开源框架,其中穿插着Spring Boot中日志切面等技术的实现,然后通过gitlab-CI以持续集成为Docker镜像。   本文为Dubbo Spring Boot 生产就绪特性
|
12月前
|
Dubbo Java 应用服务中间件
由浅入深Dubbo核心源码剖析SpringBoot整合使用
由浅入深Dubbo核心源码剖析SpringBoot整合使用
113 0
|
1月前
|
Dubbo Java Nacos
【实战攻略】破解Dubbo+Nacos+Spring Boot 3 Native打包后运行异常的终极秘籍——从零开始彻底攻克那些让你头疼不已的技术难题!
【8月更文挑战第15天】Nacos作为微服务注册与配置中心受到欢迎,但使用Dubbo+Nacos+Spring Boot 3进行GraalVM native打包后常遇运行异常。本文剖析此问题及其解决策略:确认GraalVM版本兼容性;配置反射列表以支持必要类和方法;采用静态代理替代动态代理;检查并调整配置文件;禁用不支持的功能;利用日志和GraalVM诊断工具定位问题;根据诊断结果调整GraalVM配置。通过系统排查方法,能有效解决此类问题,确保服务稳定运行。
52 0
|
4月前
|
SQL 监控 Java
nacos常见问题之dubbo+nacos+springboot3的native打包成功后运行出现异常如何解决
Nacos是阿里云开源的服务发现和配置管理平台,用于构建动态微服务应用架构;本汇总针对Nacos在实际应用中用户常遇到的问题进行了归纳和解答,旨在帮助开发者和运维人员高效解决使用Nacos时的各类疑难杂症。
223 2
|
4月前
|
Dubbo 应用服务中间件 Docker
阿里P8架构师谈微服务架构:Dubbo+Docker+SpringBoot+Cloud
什么是微服务架构呢?简单说就是将一个完整的应用(单体应用) 按照一定的拆分规则(后文讲述)拆分成多个不同的服务,每个服务都能独立地进行开发、部署、扩展。服务于服务之间通过注入RESTful api或其他方式调用。