Sleuth + Zipkin:微服务监控之分布式链路追踪技术
目录
一、概念
1.1 问题背景
1.2 概念
1.3 核心价值
1.4 功能边界
1.5 应用场景
1.6 主流分布式追踪工具对比
二、架构与原理
2.1 架构与角色分工
2.2 核心原理与概念
2.3 工作流程与数据流
三、使用
3.1 集成与使用
3.1.1 Zipkin Server 安装
3.1.2 微服务客户端集成
3.1.3 测试与查看追踪数据
3.2 高级配置与优化
3.2.1 数据持久化
3.2.2 使用消息队列提高可靠性
3.2.3 采样策略调整
3.2.4 自定义Span
3.2.5 添加自定义标签(Tags)和 baggage
3.2.6 与其他技术整合
3.3 配置项详解
一、概念
1.1 问题背景
在单体应用中,一个请求的完整处理流程都在一个进程中,通过日志和线程栈就能清晰地追踪问题。但在微服务架构中,一个用户请求(如下单)可能会被拆分成多个子请求,由数十个甚至上百个不同的微服务协同处理(如:订单服务、库存服务、支付服务、用户服务等)。
微服务架构的挑战:
-
问题定位困难:一个外部请求(如下单)需要依次调用 A -> B -> C -> D 多个服务。如果请求失败或变慢,如何快速确定是哪个服务出了问题?
-
性能分析复杂:整个请求的延迟是 2 秒,但这 2 秒具体花费在哪个服务、哪个数据库查询或哪个外部调用上?没有全局视图,根本无法分析。
-
依赖关系模糊:服务之间的调用关系是动态的、复杂的。光靠文档和配置很难理清真实的、运行时的服务依赖图谱。
-
日志分散:每个服务都有自己的日志文件,分散在不同的机器上。要拼接一个完整请求的轨迹,需要人工从海量日志中筛选、串联,效率极低。
1.2 概念
分布式链路追踪 就是一种技术,它能够唯一地标识并记录一个外部请求在系统内部多个服务间的调用路径、耗时、状态等信息,从而将分散的、独立的服务日志串联成一幅完整的“调用链”全景图。
核心思想:给一个外部请求分配一个全局唯一的追踪ID(Trace ID),然后在请求流经的每一个服务、每一个节点时,都记录下它的足迹(Span),并将这些信息集中收集、存储和可视化展示,从而重现一个请求的完整调用链路。
关系:Sleuth (Client) -> (通过网络) -> Zipkin (Server)。
-
Spring Cloud Sleuth:是一个客户端工具,集成在每个微服务中。职责:为系统间的调用自动生成并传递追踪数据。它在日志中打上标记(TraceId, SpanId),并将这些数据发送给收集器(如Zipkin)。Sleuth是数据的生产者和搬运工。
-
Zipkin:是一个独立的服务端系统,负责接收、存储、展示由Sleuth等客户端发送过来的追踪数据。职责:收集链路数据,提供友好的UI界面进行可视化展示,包括依赖分析、调用链查询、耗时统计等。Zipkin是数据的收集器和展示台。
简单比喻:
-
Sleuth 就像是在每个路口、每个商店里安装的摄像头和记录员,负责记录车辆(请求)的进出时间和车牌号(TraceID/SpanID)。
-
Zipkin 就像是交通指挥中心,接收所有记录员发来的数据,然后拼接出这辆车在整个城市中的完整行驶路线图。
Sleuth会自动为以下常见的交互提供追踪:
-
HTTP请求:通过RestTemplate、WebClient、FeignClient发出的请求。
-
消息中间件:如通过Spring Cloud Stream与Kafka/RabbitMQ的交互。
-
数据库调用:但通常不包含SQL语句细节,需要结合其他工具(如P6Spy)。
-
异步任务:
@Async
注解的方法。
1.3 核心价值
-
全链路问题定位与故障排查:
-
价值: 这是最核心的价值。当线上请求失败或变慢时,运维和开发人员不再需要像“侦探”一样去各个服务节点翻查日志,然后人工拼接线索。只需在Zipkin UI中通过一个Trace ID,即可一键获取整个请求的完整路径,快速定位到是哪个服务、哪个环节出现了错误或性能瓶颈。
-
-
性能分析与优化:
-
价值: 通过可视化的耗时瀑布图,可以清晰地看到一次请求的总耗时以及每个微服务处理的耗时。可以很容易地发现慢服务,或者分析串行调用是否可以被优化为并行调用,从而有针对性地进行性能调优。
-
-
服务依赖分析:
-
价值: 长期收集的链路数据可以绘制出系统的服务依赖拓扑图。这对于理解复杂的微服务架构、识别不合理的依赖、进行系统架构演进和治理至关重要。
-
-
分布式事务的可见性:
-
价值: 对于涉及多个服务的业务操作,链路追踪提供了其执行过程的可视化视图,虽然不是事务解决方案,但极大地辅助了理解和调试分布式事务。
-
1.4 功能边界
能做什么(Sleuth+Zipkin的核心能力) | 不能做什么(需要其他工具互补) |
---|---|
追踪请求的完整调用路径,展示服务间的调用关系。 | 不是APM(应用性能管理)工具:不能深入监控JVM内存、GC次数、CPU使用率、线程池状态等系统级指标。这类需求需使用Prometheus + Grafana, SkyWalking, Pinpoint等。 |
记录每个Span的耗时,帮助定位延迟问题。 | 不是日志管理系统:虽然Span可以携带Logs,但其主要目的是标记事件点(如“收到请求”、“发生错误”),不能替代ELK(Elasticsearch, Logstash, Kibana)或Loki这种用于海量日志聚合、检索和分析的专业系统。 |
通过Tag和Log记录业务的上下文信息(如:用户ID、订单号、错误信息)。 | 不是告警系统:Zipkin UI本身不提供强大的主动告警功能(虽然可以通过API二次开发)。告警通常由监控指标系统(如Prometheus Alertmanager)负责。 |
可视化服务依赖图。 | 不是代码级剖析工具:它能告诉你userservice 的GET /users/{id} 接口慢了,但不能告诉你是因为哪一行SQL查询或者哪段业务逻辑代码导致的。这需要结合Profiler工具。 |
基于TraceID串联所有相关日志(需与日志系统整合,将TraceID输出到日志中)。 |
最佳实践:一个成熟的微服务监控体系通常由 “指标(Metrics) + 日志(Logging) + 链路追踪(Tracing)” 三大支柱构成,三者协同工作。Sleuth+Zipkin 强项在 Tracing。
1.5 应用场景
-
场景一:快速故障排查
-
情景: 用户反馈“下单失败”。错误信息仅显示“系统异常,请重试”。
-
应用: 从网关或前端日志中找到这次失败请求的 Trace ID,输入Zipkin。界面立刻显示出请求经过了订单服务 -> 库存服务 -> 支付服务,并在支付服务上标记了一个红色错误,显示调用超时。问题瞬间定位,无需登录服务器查看支付服务的日志。
-
-
场景二:性能瓶颈分析
-
情景: 用户投诉“查询订单列表非常慢”。
-
应用: 在Zipkin中筛选出
/orders
路径的慢查询(例如耗时大于2秒的Trace)。查看一个具体链路,发现:订单服务本身处理只用了50ms,但它调用的用户服务获取用户信息用了1900ms。结论:性能瓶颈在用户服务,需要重点优化。
-
-
场景三:梳理服务依赖与架构验证
-
情景: 团队计划下线一个老旧的服务(如A服务),但不确定哪些上游服务还在调用它。
-
应用: 在Zipkin中查看A服务的依赖分析图,或者查询近期所有调用了A服务的Trace,即可清晰地看到所有调用它的上游服务,从而安全地进行架构演进。
-
-
场景四:容量规划与压测分析
-
情景: 进行全链路压测,评估系统瓶颈。
-
应用: 在压测过程中,通过Zipkin观察整个链路的耗时变化。可以发现,当压力达到一定阈值时,某个特定的服务(如商品详情服务)首先成为瓶颈,其响应时间急剧上升。这为扩容和优化提供了明确依据。
-
1.6 主流分布式追踪工具对比
维度 | Spring Cloud Sleuth + Zipkin | Apache SkyWalking | Jaeger | Pinpoint |
---|---|---|---|---|
出身/生态 | Spring Cloud 官方组件,Java 生态,尤其是 Spring Boot/Cloud 应用集成体验最佳。 | Apache 顶级项目,起源于国内。对多种语言和框架支持良好,对 Java 生态支持极深。 | CNCF 毕业项目,源自 Uber,云原生领域的事实标准之一。设计上更偏向 Go 和云原生生态。 | 韩国 Naver 公司开源。以无侵入性和强大的调用栈深度追踪著称。 |
接入方式 | 低侵入性。通过依赖和配置即可接入(@Autowired 等注入方式可能需微调)。需要配合 spring-cloud-starter-zipkin 。 | 无侵入性 是其最大亮点。主要通过 Java Agent 方式字节码增强,无需修改任何业务代码。也支持 SDK 方式。 | 低侵入性。通常通过 Client SDK 集成到应用中,需要引入依赖和少量配置。 | 无侵入性。与 SkyWalking 类似,通过 Java Agent 方式实现,无需修改代码。 |
数据收集 | 通常使用 HTTP 或 Kafka 将数据(默认是 JSON)上报给 Zipkin Collector。 | 使用 gRPC 协议上报,性能更高。也支持 HTTP、Kafka。Agent 直接汇集数据,效率高。 | 默认使用 UDP 传输 Thrift 协议数据,对应用性能影响极小。也支持 HTTP、gRPC。 | 使用 Thrift UDP 协议传输,性能开销控制得很好。 |
性能开销 | 中等。在高吞吐量下,HTTP 同步上报可能成为瓶颈(但可用 Kafka 异步化解)。Sleuth 本身开销可控。 | 低。gRPC 传输高效,Agent 优化得很好。社区公认其性能开销较低。 | 很低。UDP 传输是非阻塞和异步的,避免了追踪系统本身的问题(如网络拥堵)影响业务应用。 | 相对较高。这是其强大功能的代价。它收集了极其详尽的方法级调用栈信息,会带来更高的内存和CPU开销。 |
功能特性 | 核心聚焦于链路追踪。功能纯粹,依赖分析、拓扑图需要借助第三方工具(如 Zipkin 的 Elasticsearch 依赖)。 | 功能极其丰富。不仅是追踪,更是APM。提供: - 服务、实例、端点指标监控(JVM, CPU, GC) - 拓扑图 - 性能剖析 - 日志集成 - 告警 | 核心聚焦于链路追踪。遵循 OpenTracing 标准(现已成为 OpenTelemetry 的一部分)。设计简洁,适合做分布式追踪的标准化方案。 | 功能非常强大。APM级。提供: - 超详细代码级别调用链(能看到调用到哪个方法) - 实时活跃线程监控 - 拓扑图 - 非常细致的应用指标 |
UI 易用性 | Zipkin UI 简洁直观,专注于链路查询和可视化,易于上手。但功能相对单一。 | 功能全面,UI 现代化。将链路、指标、拓扑、日志等功能整合在同一个UI中,用户体验非常好。 | 简洁清晰。UI 符合云原生工具的审美,专注于追踪链路的展示和分析,过滤功能强大。 | 功能强大但UI略显陈旧。提供了大量信息,但界面交互和美观度不如 SkyWalking。 |
存储支持 | MySQL, Cassandra, Elasticsearch, 内存 | Elasticsearch, H2, MySQL, TiDB, InfluxDB(社区支持) | Cassandra, Elasticsearch, Kafka(自身存储), Badger(本地存储) | HBase, MySQL, Derby |
选型建议:
-
Sleuth + Zipkin 是 Spring Cloud 生态的“原住民”,简单够用,是经典的入门和中等规模方案。
-
Apache SkyWalking 是 功能全面的“瑞士军刀”,无侵入接入和APM能力是其最大杀手锏,是目前Java领域的强势首选。
-
Jaeger 是 云原生领域的“标准件”,设计现代,性能卓越,是混合语言和云原生环境下的绝佳选择。与K8s、Istio等服务网格工具集成得天衣无缝。
-
Pinpoint 是 细节追踪的“显微镜”,提供了无与伦比的代码级细节,但需要权衡其资源消耗。
二、架构与原理
2.1 架构与角色分工
组件 | 角色 | 职责 |
---|---|---|
Spring Cloud Sleuth | 客户端 instrumentation (埋点与采集) | 1. 生成追踪数据:为微服务中的请求自动生成 TraceId 和 SpanId。 2. 传递追踪上下文:Sleuth 通过将 Trace ID 和 Span ID 注入到请求头(HTTP)或消息(MQ)中,确保当下一个服务被调用时,上下文能够继续向下传递。 3. 增强日志:将 TraceId/SpanId 自动打入日志中,方便与日志系统关联。记录每个工作单元的开始时间、结束时间、标签(Tags)、日志事件(Logs)以及因果关系(父子Span关系)。 4. 收集与发送数据:将生成的链路追踪数据(Span信息)发送给Zipkin等服务端进行收集和展示。 |
Zipkin | 服务端 (收集、存储与展示) | 1. 数据收集:接收 Sleuth 或其他客户端通过 HTTP 或消息队列发送来的Span追踪数据。 2. 数据存储:默认将数据存储在内存中,但支持持久化到多种数据库(如Elasticsearch, Cassandra, MySQL)。 3. API 查询:提供查询接口,供UI调用。 4. 图形化展示:提供 Web UI 界面,用于可视化地查看调用链、依赖关系图,以及每个服务的耗时和依赖关系。 |
- Trace ID: 整个分布式请求链路的唯一标识。所有属于同一次请求的span都共享同一个Trace ID。
- Span ID: 单个服务内部工作单元(如一次RPC调用)的唯一标识。
2.2 核心原理与概念
要理解其原理,必须先掌握两个最核心的概念:Trace 和 Span。这是 OpenTracing 标准(现已成为 OpenTelemetry 的一部分)定义的基础模型。
1. Span (跨度)
Span 是链路追踪中最基本的工作单元。它代表系统中一个具有开始时间和持续时间的逻辑操作单元。例如,一个 HTTP 请求、一个数据库调用或一个方法执行都可以是一个 Span。
一个 Span 包含以下关键数据:
-
Span ID: 当前操作单元的唯一标识。
-
Trace ID: 整个调用链的唯一标识,所有属于同一条链路的 Span 共享同一个 Trace ID。
-
Parent Span ID: 父跨度 ID。用于明确 Span 在调用链中的层级关系。如果一个 Span 没有 Parent,则它是根 Span(Root Span)。
-
Name: 操作名称,例如 HTTP 方法、RPC 方法名。
-
Timestamp: 开始时间戳。
-
Duration: 持续时间(耗时)。
-
Tags: 自定义键值对标签,用于记录附加信息,如
http.method=GET
,http.status_code=200
。 -
Annotations: 时间戳事件日志,用于记录特定时刻发生的事件,如
cs
(Client Send),sr
(Server Receive),ss
(Server Send),cr
(Client Receive)。
Annotation 主要包括以下关键事件:
cs (Client Sent): 客户端发送请求,开始一个 Span
sr (Server Received): 服务端接收到请求并开始处理
ss (Server Sent): 服务端完成处理并发送响应
cr (Client Received): 客户端接收到响应,结束 Span
通过计算这些时间点之间的差值(如
sr - cs
得到网络传输时间,ss - sr
得到服务器处理时间),可以精确分析请求在各个阶段的性能表现。
2. Trace (追踪)
一个 Trace 代表一次完整的分布式请求跟踪。它本质上是由一系列具有相同 Trace ID
的 Span
构成的一个有向无环图(DAG),描绘了一次请求的生命周期和路径。
一次请求的 Trace 示例:
假设用户请求 GET /api/order/123
,这个请求需要依次调用 订单服务
-> 用户服务
-> 商品服务
。那么整个过程会生成一个 Trace,包含多个 Span,其结构可能如下所示:
Trace ID: 5f9bbc4b9dce6c14c753c8a654a6c252
|
├── Span (Root): Name=`/api/order/123`, SpanId=A, ParentId=null
│ └── (服务端处理: sr, ss)
│
├── Span: Name=`getUser`, SpanId=B, ParentId=A
│ └── (客户端调用: cs, cr) -> (服务端处理: sr, ss @用户服务)
│
└── Span: Name=`getProduct`, SpanId=C, ParentId=A└── (客户端调用: cs, cr) -> (服务端处理: sr, ss @商品服务)
3. 上下文传播 (Context Propagation)
这是保证链路不断的关键。Sleuth 使用 Brave 库来实现上下文信息的跨进程传递。
-
过程:
-
注入 (Inject):当服务 A(客户端)调用服务 B 时,Sleuth 会将当前的
TraceId
、ParentSpanId
(即当前 Span 的 ID)等信息注入到本次调用的 HTTP Headers 中(通常使用 B3 格式,如X-B3-TraceId
,X-B3-ParentSpanId
)。 -
提取 (Extract):服务 B(服务端)接收到请求后,Sleuth 会从 HTTP Headers 中提取这些追踪信息。
-
创建新 Span:服务 B 基于提取到的
TraceId
和ParentSpanId
创建一个新的子 Span,从而将两个服务的 Span 关联到同一个 Trace 下。
-
这种传播机制支持各种通信方式,如 HTTP(RestTemplate, Feign, WebClient)、消息队列(RabbitMQ, Kafka)、RPC(gRPC)等。
2.3 工作流程与数据流
一个完整的追踪数据生命周期如下:
-
生成 (Generate):
-
请求进入微服务 A,Sleuth 生成一个 TraceId 和一个 Root Span(如果 Header 中没有追踪信息),或者从 Header 中提取信息并创建相应的子 Span。
-
在服务处理过程中,Sleuth 会记录数据库调用、外部请求等作为新的子 Span。
-
-
传播 (Propagate):
-
微服务 A 通过 HTTP 调用微服务 B 时,Sleuth 自动将
TraceId
,SpanId
等信息注入到请求头中。
-
-
收集 (Collect):
-
每个服务在处理完请求后,Sleuth 会将本地的 Span 数据(通常是异步地)批量发送到 Zipkin Server。
-
发送方式主要有两种:
-
HTTP 直接上报:Sleuth 客户端通过 POST 请求将 JSON 数据直接发送到 Zipkin 的
/api/v2/spans
接口。 -
消息队列缓冲(推荐用于生产环境):Sleuth 客户端先将数据发送到 Kafka 或 RabbitMQ,Zipkin Server 再从消息队列中消费。这种方式提高了可靠性和解耦能力。
-
-
-
存储 (Store):
-
Zipkin Server 接收到 Span 数据后,会将其存储到配置的后端存储中,如:
-
内存:仅用于测试,重启数据丢失。
-
MySQL/PostgreSQL:适合小规模部署。
-
Elasticsearch/Cassandra:生产环境推荐,可扩展性强,能处理海量追踪数据。
-
-
-
展示 (Visualize):
-
用户通过 Zipkin 的 Web UI 界面,根据 TraceId、服务名、时间等条件查询追踪数据。
-
Zipkin 会将从存储中查询到的多个 Span 重新组装成完整的调用链 Trace,并以时间线的形式直观展示,清晰标出每个服务的耗时和层级关系。
-
三、使用
3.1 集成与使用
3.1.1 Zipkin Server 安装
Zipkin Server 的安装有多种方式,以下是两种常用方法:
方法一:使用独立 Jar 包(适合本地开发)
# 下载 Zipkin Server(版本可能更新,请以官网为准)
curl -sSL https://zipkin.io/quickstart.sh | bash -s
# 运行 Zipkin Server(使用内存存储,默认端口9411)
java -jar zipkin-server-*.jar
方法二:使用 Docker(适合测试和生产环境)
# 拉取并运行 Zipkin 容器
docker run -d -p 9411:9411 --name zipkin openzipkin/zipkin
安装完成后,通过浏览器访问 `http://localhost:9411` 即可打开 Zipkin 的可视化界面。
对于生产环境,建议使用 Docker Compose 或 Kubernetes 部署,并配置 Elasticsearch 作为存储。
# docker-compose.yml 示例
version: '3.8'
services:zipkin:image: openzipkin/zipkin:2.23environment:- STORAGE_TYPE=elasticsearch- ES_HOSTS=elasticsearch:9200ports:- "9411:9411"elasticsearch:image: docker.elastic.co/elasticsearch/elasticsearch:7.14.0environment:- discovery.type=single-node
3.1.2 微服务客户端集成
添加Maven依赖:在需要追踪的每个微服务项目的 `pom.xml` 中添加 Sleuth 和 Zipkin 依赖
<dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-zipkin</artifactId>
</dependency>
注意:这个依赖已经包含了 `spring-cloud-starter-sleuth`,无需单独引入 Sleuth
配置应用程序属性:在项目的 `application.yml` 或 `application.properties` 中添加配置
spring:application:name: my-order-service # 服务名,会在Zipkin中显示zipkin:base-url: http://localhost:9411 # Zipkin Server 地址sender:type: web # 传输方式(web 表示 HTTP)sleuth:sampler:probability: 1.0 # 采样率(0.1 表示 10%,1.0 表示 100%)
采样率说明:生产环境中不建议设置为 1.0(即 100% 采样),因为在高流量下会产生大量追踪数据,可能影响系统性能。通常根据系统负载设置为 0.1 到 0.5 之间
假设有两个微服务:`order-service`(订单服务)和 `payment-service`(支付服务),订单服务需要调用支付服务完成支付操作。
支付服务(payment-service)中添加接口:
@RestController
public class PaymentController {@GetMapping("/payment/{id}")public String getPayment(@PathVariable String id) {return "Payment details for order: " + id;}
}
订单服务(order-service)中调用支付服务:
@RestController
public class OrderController {private final RestTemplate restTemplate;public OrderController(RestTemplate restTemplate) {this.restTemplate = restTemplate;}@GetMapping("/order/{id}")public String getOrder(@PathVariable String id) {// 调用支付服务String paymentInfo = restTemplate.getForObject("http://localhost:8001/payment/" + id, String.class);return "Order: " + id + ", " + paymentInfo;}
}
3.1.3 测试与查看追踪数据
1. 依次启动服务注册中心、支付服务和订单服务
2. 访问订单接口:`http://localhost:8080/order/123`
3. 多次调用该接口(确保生成追踪数据)
4. 打开 Zipkin 控制台(`http://localhost:9411`)
5. 选择相关服务,查看追踪数据
在 Zipkin 界面中,可以:
-
Find Traces:根据服务名、操作名、耗时、时间范围等条件搜索调用链。
-
查看Trace详情:点击一条Trace,会展示出一个时间轴视图,清晰看到每个服务的耗时,快速定位瓶颈(是网关慢?还是某个数据库查询慢?)。
-
查看Span详情:点击某个Span,可以查看其详细数据,包括标签(Tags)、时间点(Annotations)以及自定义的 baggage 信息。
-
依赖分析:点击“Dependencies”标签,可以查看整个微服务集群的服务依赖拓扑图。
3.2 高级配置与优化
3.2.1 数据持久化
默认情况下,Zipkin 将数据存储在内存中,服务重启后数据会丢失。在生产环境中,建议配置持久化存储。
持久化到 MySQL:
# 创建 Zipkin 数据库(需要先创建数据库和表,表结构参考 Zipkin 官方文档)
java -jar zipkin-server-<version>.jar \--STORAGE_TYPE=mysql \--MYSQL_HOST=localhost \--MYSQL_TCP_PORT=3306 \--MYSQL_DB=zipkin \--MYSQL_USER=root \--MYSQL_PASS=password
使用 Elasticsearch 存储:
# 使用 Elasticsearch 作为存储后端
java -jar zipkin-server-<version>.jar \--STORAGE_TYPE=elasticsearch \--ES_HOST=localhost:9200
存储选择:
-
开发/测试:使用内存。
-
中小型生产:使用 Elasticsearch,易于部署和查询。
-
大型、高流量生产:使用 Cassandra,为写密集型场景设计,扩展性更好。
3.2.2 使用消息队列提高可靠性
在高并发场景下,可以使用消息队列(如 RabbitMQ 或 Kafka)来缓冲追踪数据,提高系统可靠性:
spring:zipkin:base-url: http://localhost:9411sender:type: rabbit # 或 kafkarabbitmq:host: localhostport: 5672username: guestpassword: guest
同时启动 Zipkin Server 时需要配置相应的消息中间件:
java -jar zipkin-server-<version>.jar \--RABBIT_ADDRESSES=localhost:5672
3.2.3 采样策略调整
根据系统负载调整采样率,平衡数据收集和系统性能:
spring:sleuth:sampler:probability: 0.1 # 概率采样策略,采集10%的请求# rate: 10 # 限速采样策略,每秒最多10条Trace。若启用此项,probability配置失效uri-patterns:- pattern: "^/api/important/.*" # 重要接口,采样率100%probability: 1.0- pattern: "^/api/health" # 健康检查,不采样probability: 0.0- pattern: "^/api/admin/.*" # 管理接口,采样率80%probability: 0.8
对于更复杂的场景,可以实现自定义采样器:
@Bean
public Sampler customSampler() {return new Sampler() {@Overridepublic boolean isSampled(Span span) {// 实现自定义采样逻辑return Math.random() < 0.5; // 50% 采样率}};
}
主要步骤
-
实现
Sampler
接口:创建自定义采样器类,实现isSampled
方法,在其中定义采样逻辑。 -
注册为Bean:将自定义采样器注入Spring容器,覆盖默认的采样器配置。
3.2.4 自定义Span
-
除了自动追踪,你可以在业务代码中手动创建Span来追踪重要业务逻辑。
-
使用
@NewSpan
注解或Tracer
bean手动创建。
@Autowired
private Tracer tracer;public void myBusinessMethod() {Span newSpan = tracer.nextSpan().name("myCustomSpan").start();try (Tracer.SpanInScope ws = tracer.withSpanInScope(newSpan.start())) {// ... 你的业务逻辑} finally {newSpan.finish();}
}
3.2.5 添加自定义标签(Tags)和 baggage
-
Tags:是以K-V形式存储的上下文信息,用于查询过滤。例如,可以添加
user.id=12345
,之后可以在Zipkin中搜索所有user.id=12345
的请求。Tags会被发送到Zipkin。 -
Baggage:也是K-V形式,用于在全链路中传递一些业务数据(如用户信息)。Baggage信息默认不会被发送到Zipkin,以保证敏感数据安全且减少网络开销。它存在于调用上下文中。
span.tag("user.id", userId);
span.event("订单创建成功");
3.2.6 与其他技术整合
-
与日志系统(如ELK)整合:将TraceId、SpanId添加到日志模式中。这样在Kibana中查日志时,可以直接用TraceId搜到该请求在所有微服务中的全部相关日志,这是最实用的功能之一。
-
与Metrics系统(如Prometheus)整合。
3.3 配置项详解
Spring Cloud Sleuth 主要配置项
配置项 | 类型 | 默认值 | 说明 | 推荐设置 |
---|---|---|---|---|
spring.sleuth.sampler.probability | float | 0.1 | 采样率 ,0.0到1.0,1.0表示100%采样 | 生产环境可根据流量调低 (如0.1) |
spring.sleuth.trace-id128 | boolean | false | 是否生成128位Trace ID (64位默认) | false (除非需要更大ID空间) |
spring.sleuth.propagation.type | string | "B3" | 传播类型,如 B3 (Zipkin原生)、W3C (Trace Context标准) | B3 (默认) 或 W3C (需要跨系统互操作) |
spring.sleuth.web.client.enabled | boolean | true | 是否对 WebClient /RestTemplate 调用进行追踪 | true |
spring.sleuth.async.enabled | boolean | true | 是否对异步操作 (如@Async , CompletableFuture ) 进行追踪 | true |
spring.sleuth.rpc.grpc.enabled | boolean | - | 是否对gRPC调用进行追踪 | 如使用gRPC则开启 |
spring.sleuth.log.slf4j.whitelisted-mdc-keys | string | - | 除Trace ID和Span ID外,添加到SLF4J MDC的键 | 根据需要添加自定义键 |
Zipkin 客户端与服务器配置项
配置项 | 类型 | 默认值 | 说明 | 推荐设置 |
---|---|---|---|---|
spring.zipkin.base-url | string | - | Zipkin服务器地址 (如 http://localhost:9411 ) | 必需配置 |
spring.zipkin.service.name | string | - | 通过服务名发现Zipkin (当Zipkin注册到Eureka等注册中心时) | 通常使用base-url 明确指定 |
spring.sleuth.zipkin.base-url | string | - | Zipkin收集器端点 (同上) | 必需配置 |
spring.sleuth.zipkin.sender.type | string | "web" | 发送Span数据的方式,如 "web" (同步HTTP), "rabbit", "kafka" | "web" (低流量), "kafka"/"rabbit" (高吞吐) |
spring.zipkin.discovery-client-enabled | boolean | false | 是否使用服务发现定位Zipkin服务器 | 如果Zipkin注册到注册中心则设为true |
management.zipkin.tracing.endpoint | string | /api/v2/spans | Zipkin API端点 | 通常使用默认值 |
spring.zipkin.compression.enabled | boolean | true | 上报数据是否使用gzip压缩 | true (节省带宽) |
Zipkin 服务器配置 (如使用Docker)
环境变量 | 说明 | 示例值 |
---|---|---|
STORAGE_TYPE | 存储类型,如 mem (内存), mysql , elasticsearch | elasticsearch |
ES_HOSTS | Elasticsearch主机地址 (逗号分隔) | http://es-host:9200 |
MYSQL_HOST | MySQL主机地址 | localhost |
MYSQL_USER /MYSQL_PASS | MySQL用户名/密码 | root /your_password |
JAVA_OPTS | JVM参数 (如堆内存) | -Xms512m -Xmx512m |