Micrometer+Zipkin
分布式链路追踪(Distributed Tracing)是一种用于监控和分析分布式系统性能的技术。它允许开发人员和运维人员追踪请求在分布式系统中的传播路径,包括跨服务调用、数据库访问、缓存查询等操作。通过分布式链路追踪,可以深入了解系统的运行状况,快速定位和解决问题,提高系统的稳定性和性能。
分布式链路追踪的关键概念
-
Trace:一次分布式请求的全链路调用过程被称为一个Trace。Trace是分布式链路追踪的基本单位,它包含了请求在分布式系统中经过的所有节点和服务的信息。
-
Span:Span是Trace的基本组成单元,代表一个逻辑工作单元,例如一次远程调用或一次数据库查询。每个Span都有一个唯一的标识符(Span ID),以及一个可选的父Span标识符(Parent Span ID),用于表示Span之间的父子关系。
-
Annotation:Annotation是对Span的补充说明,用于记录一些关键事件,如请求的开始和结束时间、异常信息等。
-
Tag:Tag是Span的键值对标签,用于添加一些额外的信息,如HTTP请求的URL、方法名、状态码等。
-
Baggage:Baggage是一种跨进程传递的上下文信息,通常用于传递一些需要在整个Trace过程中共享的数据,如用户ID、会话ID等。
分布式链路追踪的实现方式
实现分布式链路追踪通常有以下几种方式:
-
基于日志的追踪:通过在每个服务中记录详细的日志信息,包括请求的起始时间、结束时间、调用链信息等,然后通过日志分析工具进行聚合和分析。这种方式实现简单,但分析和查询效率较低。
-
基于代理的追踪:通过在服务之间插入代理(如Nginx、HAProxy等),代理会记录并转发请求,并在请求头中添加Trace信息。这种方式不需要修改服务代码,但会增加系统复杂度。
-
基于字节码的追踪:通过修改服务代码,在方法调用前后插入字节码,以记录Trace信息。这种方式需要修改服务代码,但可以实现更细粒度的追踪。
-
基于API的追踪:服务提供API接口,允许外部系统通过API获取Trace信息。这种方式需要服务支持相应的API接口,但灵活性较高。
常见的分布式链路追踪系统
-
Zipkin
Zipkin 是 Twitter 开源的一个分布式链路追踪系统,能够帮助用户收集和分析系统中的跟踪数据。Zipkin 的核心组件包括 Zipkin Collector、Zipkin Query 和 Zipkin Web UI。
-
Jaeger
Jaeger 是 Uber 开源的分布式链路追踪系统,设计初衷是解决微服务架构中的监控和故障排除问题。Jaeger 提供了与 Zipkin 类似的功能,并在可扩展性和性能上进行了优化。
-
OpenTelemetry
OpenTelemetry 是一个联合的开源项目,由 OpenTracing 和 OpenCensus 项目合并而来,旨在为分布式系统提供统一的监控、跟踪和日志收集工具。OpenTelemetry 提供了 SDK 和 API,支持多种编程语言,并与多种后端系统兼容。
Trace ID:
Trace ID 是一个全局唯一的标识符,用于标识一个完整的请求链路。在一个分布式系统中,当一个请求从客户端发起,经过多个服务节点处理后,最终返回给客户端,这个过程中涉及的所有服务节点上的操作都会被记录在一个 Trace 中。而 Trace ID 就是用来唯一标识这个 Trace 的。(通常在请求进入系统时生成,可以使用 UUID、雪花算法等方式来确保全局唯一性。)
Span ID:
Span ID 是一个局部唯一的标识符,用于标识 Trace 中的一个单独的操作单元(Span)。在一个 Trace 中,可能会有多个 Span,每个 Span 代表了一个具体的操作,如一次数据库查询、一次远程调用等。(在每个操作开始时生成,同样需要保证在局部范围内的唯一性。)
Trace ID 和 Span ID 的关系
-
包含关系:一个 Trace 包含多个 Span,每个 Span 都有一个唯一的 Span ID,而所有 Span 共享同一个 Trace ID。
-
层次结构:通过 Trace ID 和 Span ID,系统可以构建一个清晰的请求链路层次结构。每个 Span 可以有子 Span,形成一个树状结构,而 Trace ID 就是这棵树的根节点。
-
联合作用:Trace ID 和 Span ID 联合作用,使得系统能够完整地记录和展示一个分布式请求链路中的所有操作及其相互关系。
Zipkin
Zipkin是一种分布式链路跟踪系统图形化的工具,Zipkin 是 Twitter 开源的分布式跟踪系统,能够收集微服务运行过程中的实时调用链路信息,并能够将这些调用链路信息展示到Web图形化界面上供开发人员分析,开发人员能够从ZipKin中分析出调用链路中的性能瓶颈,识别出存在问题的应用程序,进而定位问题和解决问题。
下载主页:Quickstart · OpenZipkin https://zipkin.io/pages/quickstart
Zipkin 的核心组件
Zipkin 的核心组件主要包括:
-
Zipkin Collector:负责收集来自各个服务节点的追踪数据。这些数据通常包括 Trace ID、Span ID、操作名称、开始时间、结束时间、标签等信息。
-
Zipkin Storage:负责存储收集到的追踪数据。Zipkin 支持多种存储后端,如内存、MySQL、Cassandra、Elasticsearch 等,用户可以根据实际需求选择合适的存储方案。
-
Zipkin Query:提供 API 接口,允许用户通过 Trace ID、Span ID 等条件查询追踪数据。
-
Zipkin Web UI:提供可视化界面,用户可以通过该界面查看和分析追踪数据,包括请求链路图、服务依赖关系图、性能指标等。
操作流程:
====================改pom闻文件,添加相关依赖(在父工程中声明)=======================
<!--micrometer-tracing-bom导入链路追踪版本中心 1-->
<dependency>
<groupId>io.micrometer</groupId>
<artifactId>micrometer-tracing-bom</artifactId>
<version>1.2.0</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<!--micrometer-tracing指标追踪 2-->
<dependency>
<groupId>io.micrometer</groupId>
<artifactId>micrometer-tracing</artifactId>
<version>1.2.0</version>
</dependency>
<!--micrometer-tracing-bridge-brave适配zipkin的桥接包 3-->
<dependency>
<groupId>io.micrometer</groupId>
<artifactId>micrometer-tracing-bridge-brave</artifactId>
<version>1.2.0</version>
</dependency>
<!--micrometer-observation 4-->
<dependency>
<groupId>io.micrometer</groupId>
<artifactId>micrometer-observation</artifactId>
<version>1.12.0</version>
</dependency>
<!--feign-micrometer 5-->
<dependency>
<groupId>io.github.openfeign</groupId>
<artifactId>feign-micrometer</artifactId>
<version>12.5</version>
</dependency>
<!--zipkin-reporter-brave 6-->
<dependency>
<groupId>io.zipkin.reporter2</groupId>
<artifactId>zipkin-reporter-brave</artifactId>
<version>2.17.0</version>
</dependency>
==========================写yml文件,配置相关信息==================================
management:
zipkin:
tracing:
endpoint: http://localhost:9411/api/v2/spans
tracing:
sampling:
probability: 1.0 #采样率默认为0.1(0.1就是10次只能有一次被记录下来),值越大收集越及时。
========================业务类,接口方法声明=======================================
@RestController
public class PayMicrometerController
{
/**
* Micrometer(Sleuth)进行链路监控的例子
* @param id
* @return
*/
@GetMapping(value = "/pay/micrometer/{id}")
public String myMicrometer(@PathVariable("id") Integer id)
{
return "Hello, 欢迎到来myMicrometer inputId: "+id+" \t 服务返回:" + IdUtil.simpleUUID();
}
}
@RestController
@Slf4j
public class OrderMicrometerController
{
@Resource
private PayFeignApi payFeignApi;
@GetMapping(value = "/feign/micrometer/{id}")
public String myMicrometer(@PathVariable("id") Integer id)
{
return payFeignApi.myMicrometer(id);
}
}