这是个很尴尬的专题,为何这么说呢?当咱们在讨论卷和造轮子两个事情的时候,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,可能有以下几点原由(一家之言,欢迎指点): 1、在之前的有些版本中,Micrometer 关注更大都是 metrics,而 OpenTelemetry 则更加多关注 tracing,然则随着版本的迭代完善,Micrometer 和 OpenTelemetry 在 metrics 和 tracing API 上基本都具备了。重要的是,这里之前,SpringBoot 已然对 Micrometer Metrics 进行了支持,所说近水楼台先得月。2、OpenTelemetry 的目的是厂商无关,语言无关,penTelemetry 更适合在异构技术栈中发挥功效;而 Micrometer 始终败兴都是基于 Java 语言,这与 Spring 体系从根上是一致的。3、Micrometer API 进行海量更改。最重要的变化是引入了一个新的 API:Observation API,这般便于运用者能够运用统一的 API 来观测业务代码,包含 metrics, tracing 以及 logging。下面就 SpringBoot3 Tracing 展开聊聊。
SpringBoot3 Tracing 剖析
SpringBoot3 在 Spring Boot Actuator 中为 Micrometer Tracing 的依赖性管理和自动配置。Micrometer Tracing 充当了类似日志行业内 slf4j 门面的角色。
Micrometer Tracing API
Micrometer Tracing 中的关联概念亦是借用 Dapper 的,例如 Span,Trace 等,这儿不做太多介绍。总体来讲,Micrometer Tracing 包含以下几个部分: 核心模块重点包括 instrumentation SPI用于适配其它 tracing 实现的 bridge 桥接器用于上报 span 数据的 reportor 扩展机制测试模块功能划分和代码模块结构组织是一致的
在 Micrometer Tracing 中,一个完整的 tracing 大致如下图所示
bridge 桥接器
当前版本,Micrometer Tracing 支持两种 Tracers OpenZipkin BraveOpenTelemetry
在运用时,你只能选取一个 bridge 桥接实现,倘若在你的 classpath 中包含两个,可能会有有些意想不到的问题,例如重复的 trace 或 span。
Reporters
当前版本,Micrometer Tracing 支持两种 Reporters Tanzu Observability by WavefrontOpenZipkin Zipkin
怎样和 Brave 集成的
不管是 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 数据的上报。两个关键点: 上报机会:span 结束时上报方式:经过自定义 reporter 上报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 的方式为例。
依赖增多依赖,下面给出的依赖均为必须供给的<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId> spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>io.micrometer</groupId>
<artifactId>micrometer-tracing</artifactId>
</dependency>
<dependency>
<groupId>io.micrometer</groupId>
<artifactId>micrometer-tracing-bridge-brave</artifactId>
</dependency>
<dependency>
<groupId>io.zipkin.reporter2</groupId>
<artifactId>zipkin-reporter-brave</artifactId>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>io.micrometer</groupId>
<artifactId>micrometer-tracing-bom</artifactId>
<version>1.0.0</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
复制代码供给一个测试 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 ....
复制代码zipkin 界面
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
|