这是个很尴尬的话题,为什么这么说呢?当我们在讨论卷和造轮子两个事情的时候,SpringBoot 的开发人员也正在做着同样的事情...回顾
之前在 微服务-分布式链路 这篇文章中我介绍了 DApper、Opentracing,并以蚂蚁分布式链路组件 SOFATracer 为例,较为详细的说明了分布式链路组件中的一些技术细节和实现方式,有兴趣的同学可以自行查看。
Micrometer Tracing
最近关注 SpringBoot3 的发布,在 Production-ready Features 中,首次将 tracing 作为一个单独的功能项写进官方文档中;在此之前 SpringBoot 仅提供了 Http Tracing 的能力,并且默认情况下,是在内存中存储 近 100 次请求的记录;在 2.7.x 的官方文档中,Http Tracing 只是建议在开发环境使用,对于生产环境,官方文档也明确的指出,建议使用 Zipkin 或 Spring Cloud Sleuth 这类比较成熟的可观测性解决方案。
从 Dapper 到 OpenTracing,解决了厂商无关和统一链路 API 的问题,从 OpenTracing 到 OpenTelemetry,解决统一可观测性 API 的问题,并且 OpenTelemetry 从 2019-5.7 被 CNCF Accepted 之后,也在不断地孵化和完善。如果说 SpringBoot 面向 OpenTelemetry 提供 Tracing,可能更便于接受,但是 SpringBoot 却使用了 Micrometer tracing,并且通过 Facade 进行了桥接 Brave 和 otel。
首先一点是,SpringBoot 将 Tracing 在 v3 系列提供出来比较容易理解,在可观测性上,tracing 一直都是 SpringBoot 缺失的,在 SpringCloud 中,它通过 Spring Cloud Slueth 整合了 Brave 补缺了这一环。
比较疑惑的是,SpringBoot 提供的 tracing 为什么会选择使用一个新的 facade Micrometer tracing 来实现,这一点我尝试从 issue 中去找答案,但也没有找到比较有说服力的,比如 Add auto-configuration for Micrometer 2.0 Observation API 和 Add support for Micrometer tracing。不过有意思的是,在 spring.io/projects/sp… 这里给出了一些信息,意思就是 Spring Cloud Slueth 将迁移到 Micrometer tracing。
那么关于为什么 SpringBoot 使用 Micrometer 而不是 OpenTelemetry,可能有以下几点原因(一家之言,欢迎指导):
下面就 SpringBoot3 Tracing 展开聊聊。
SpringBoot3 Tracing 剖析
SpringBoot3 在 Spring Boot Actuator 中为 Micrometer Tracing 的依赖性管理和自动配置。Micrometer Tracing 充当了类似日志领域内 slf4j 门面的角色。
Micrometer Tracing API
Micrometer Tracing 中的相关概念也是借用 Dapper 的,比如 Span,Trace 等,这里不做过多介绍。总体来说,Micrometer Tracing 包括以下几个部分:
功能划分和代码模块结构组织是一致的
在 Micrometer Tracing 中,一个完整的 tracing 大致如下图所示
bridge 桥接器
当前版本,Micrometer Tracing 支持两种 Tracers
在使用时,你只能选择一个 bridge 桥接实现,如果在你的 classpath 中包括两个,可能会有一些意想不到的问题,比如重复的 trace 或者 span。
Reporters
当前版本,Micrometer Tracing 支持两种 Reporters
不管是 brave 还是 otel,它们都是完整的分布式链路解决方案,包括 API 和 instrumentation;Micrometer Tracing 与 brave、otel 的集成是典型的 接口继承 + 委托 的形式实现的,以 span 为例:
import io.micrometer.tracing.Span; /** * Brave implementation of a {@link Span}. * * @author Marcin Grzejszczak * @since 1.0.0 */ public class BraveSpan implements Span { final brave.Span delegate; // 省略其它无关代码 ... } 复制代码
这种方式也是 skywalking、zipkin-brave、sofatracer1.0、jaeger 等组件在早期支持 opentrcing API 的实现方式。如何上报给 zipkin 的
我在 原理 | 分布式链路跟踪组件 SOFATracer 和 Zipkin 模型转换 这篇文章中介绍过 SOFATracer 是如何将 span 数据上报给 zipkin 的,它的做法是:在 span 结束的时候,通过预留的 reporter 扩展机制,使得用户可以通过自定义 reporter 来实现 span 数据的上报。两个关键点:
Micrometer Tracing 本身包括了对 span 完整生命周期管理的 API
/** * Starts this span. * @return this span */ Span start(); /** * Ends the span. The span gets stopped and recorded if not noop. */ void end(); /** * Ends the span. The span gets stopped and recorded if not noop. * @param time timestamp * @param timeUnit time unit of the timestamp */ void end(long time, TimeUnit timeUnit); 复制代码
因此上报时机都是一样的,在 span 结束时发生。上报方式,Brave 提供了一个 SpanHandler 扩展接口,对应的具体实现是 ZipkinSpanHandler,otel 中提供的是 SpanExporter 扩展接口,对应的实现是 ZipkinSpanExporter。下面用一张简单的图描述下
a simple guides for you
这里给一个小案例,主要是官方文档中并没有提供 step by step 的集成方式。以 Micrometer tacing + brave + zipkin 的方式为例。
依赖
org.springframework.boot spring-boot-starter-actuator io.micrometer micrometer-tracing io.micrometer micrometer-tracing-bridge-brave io.zipkin.reporter2 zipkin-reporter-brave io.micrometer micrometer-tracing-bom 1.0.0 pom import 复制代码
提供一个测试 Rest API @RequestMapping("api") @RestController() public class MyController { private static final Log logger = LogFactory.getLog(MyController.class); @RequestMapping("test") public String test() { // 配置了在日志中输出 traceId logger.info("this is test log ...."); return "SUCCESS"; } } 复制代码
基本配置 # 采样比率 management.tracing.sampling.probability=1.0 # 将 traceId 和 spanId 和 log 绑定 logging.pattern.level=%5p [${spring.application.name:test},%X{traceId:-},%X{spanId:-}]` 复制代码
测试
访问 curl http://localhost:8080/api/test,
2022-12-06T12:06:36.971+08:00 INFO [test,638ebfccd315f7022e7eee028343517f,2e7eee028343517f] 61043 --- [nio-8080- exec-1] c.g.bridge.boot.controller.MyController : this is test log .... 复制代码
PS:你可能没有看到任何关于 zipkin 的配置,因为默认情况下,zipkin 的上报地址是 127.0.0.1:9411,我在本地通过 Docker 启动了一个 zipkin 实例,所以我并不需要做额外的配置。总结
本篇对 SpringBoot3 tracing 做了一些介绍,通过本篇文章,希望你可以了解到 SpringBoot3 中提供 tracing 的初衷,以及在众多事实标准存在情况下选择 Micrometer tracing 作为 API 的原因。这篇文章并不会涉及到过多对于 tracing 基础概念的介绍,如果你有兴趣可以自行查阅。最后我给出了 Micrometer tacing + brave + zipkin 一个小案例,希望可以帮助到你。
作者:磊叔的技术博客 链接:https://juejin.cn/post/7173914390352101412