跳转到内容

Zipkin 面试题

10 道题
分类
可观测性
子分类
trace
题目数
10 道
已阅读 0 / 10 题
1 Zipkin 的核心架构由哪些组件组成?各组件的职责是什么?

答案:

Zipkin 是 Twitter 开源的分布式追踪系统(受 Google Dapper 论文启发),用于收集微服务架构中的时序数据,解决服务依赖分析与延迟问题。

核心组件:

组件职责部署形态
Reporter客户端埋点库集成在应用中(brave / zipkin-js)
Collector数据收集与校验无状态服务,可水平扩展
Storage后端存储In-Memory / MySQL / Cassandra / Elasticsearch
Query Service查询 API提供 JSON API 给 UI
Web UI可视化界面依赖图、Trace 时间线、Span 详情

数据流:

应用 (Instrumentation)
    ├── Reporter.send(span) ── HTTP POST /api/v2/spans
Zipkin Collector
    ├── 校验 traceId / spanId 格式
    ├── 写入 SpanStore
Storage (Cassandra / ES / MySQL)
Query Service ◄── Web UI (GET /api/v2/trace/{id})

All-in-One 启动(开发模式):

docker run -d --name zipkin \
  -p 9411:9411 \
  openzipkin/zipkin

Web UI 默认端口 9411,API 端点 /api/v2/spans(v2 协议)。

2 Zipkin 的数据模型:Span、Trace、Annotation 和 Tag 的关系是什么?

答案:

Zipkin 数据模型受 Google Dapper 启发,与 OpenTracing / OpenTelemetry 兼容,核心实体为 Span,通过共享 traceId 构成完整 Trace。

数据模型层次:

flowchart TB
    T["Trace
traceId=0af7651916cd43dd"] T --> SA["Span A
Root: HTTP GET /api/orders
id: b7ad6b7169203331
kind: SERVER"] SA --> SA_T["Tags: http.method=GET
duration: 250000μs"] SA --> SB["Span B
Child: SELECT FROM orders
parentId: b7ad6b7169203331
kind: CLIENT"] SB --> SB_T["Tags: db.statement: SELECT..."] SA --> SC["Span C
Child: HTTP call to payment
parentId: b7ad6b7169203331
kind: CLIENT"] SC --> SC_T["remoteEndpoint: payment-service"]

Span 关键字段:

字段含义示例
traceIdTrace 全局唯一 ID(16 或 32 字节十六进制)0af7651916cd43dd
idSpan 唯一 IDb7ad6b7169203331
parentId父 Span ID(Root Span 为 null)b7ad6b7169203331
kindSpan 类型枚举CLIENT / SERVER / PRODUCER / CONSUMER
name操作名GET /api/orders
timestamp起始时间(微秒)1716700000000000
duration持续时长(微秒)250000
localEndpoint本地服务标识{serviceName: "api-gateway"}
remoteEndpoint远端服务标识{serviceName: "payment-service"}
tags键值对标签(可搜索)http.method=GET
annotations时间戳事件sr / ss / cs / cr

Annotation 类型:

含义角色
csClient Send客户端发起请求
crClient Receive客户端收到响应
ssServer Send服务端发送响应
srServer Receive服务端收到请求
msMessage SendMQ 生产者
mrMessage ReceiveMQ 消费者
ws / wrWire Send / Receive网络边界事件
3 Zipkin 支持哪些采样策略?如何选择与配置?

答案:

Zipkin 默认 100% 上报,生产环境为降低存储与网络开销,需要在 Reporter 层配置采样器(Tracing.Builder.sampler(...))。

采样策略对比:

采样器原理适用场景缺点
AlwaysSampler100% 全量采集开发、测试、压测生产成本爆炸
NeverSampler完全不采集临时关闭追踪无法排查问题
PercentageBasedSampler概率采样(0.0~1.0)通用生产环境突发流量统计偏差
RateLimitingSampler令牌桶限速(每秒 N 条)流量稳定的关键链路突发流量易丢采样
BoundarySampler首个 Span 概率决定整条 Trace保持 Trace 完整性长尾 Trace 部分缺失

Brave(Brave 5.x,Java 客户端)配置:

@Bean
public Brave brave() {
    return new Brave.Builder("order-service")
        .traceSampler(Sampler.ALWAYS_SAMPLE)  // 全量
        // 或
        .traceSampler(Sampler.NEVER_SAMPLE)
        // 或自定义
        .traceSampler(rateLimitingSampler(10))  // 10 req/s
        .build();
}

Spring Boot Sleuth 集成配置(application.yml):

spring:
  sleuth:
    sampler:
      probability: 0.1   # 10% 概率采样
    propagation:
      type: B3          # B3 协议(默认)

BoundarySampler 实现 Trace 完整性:

public class BoundarySampler extends Sampler {
    private final Sampler delegate;
    
    @Override
    public boolean isSampled(TraceContext traceContext) {
        // 根 Span 决策,整条 Trace 保持一致
        if (traceContext.parentId() == null) {
            return delegate.isSampled(traceContext);
        }
        return traceContext.sampled() != null && traceContext.sampled();
    }
}

最佳实践:

  • 核心交易链路使用 100% 或高概率(>=10%),次要链路 1% ~ 5%。
  • 高 QPS 场景使用 RateLimitingSampler,避免 Collector 过载。
  • 多服务调用链使用 BoundarySampler,确保 Trace ID 一致且决策统一。
4 Zipkin 与 Jaeger 的核心差异是什么?如何在生产环境中选型?

答案:

Zipkin 与 Jaeger 同源(Dapper 思想),但由不同组织演进,二者在架构、协议、存储与生态上差异显著。

核心对比:

维度ZipkinJaeger
起源Twitter(2012)Uber(2015),CNCF 毕业
架构直接上报 CollectorClient SDK → Agent(UDP)→ Collector
传输HTTP/JSON、Kafka、gRPCUDP(Thrift)、HTTP、gRPC
采样客户端决策客户端 + Agent 集中决策
存储MySQL / Cassandra / ESCassandra / ES / Kafka + Badger
依赖分析仅 UI 展示内置 sparkline + Graph 拓扑
协议B3(Zipkin 原生)、W3C TraceContextJaeger Thrift、W3C TraceContext
UI 体验简洁、Trace 时间线清晰依赖图、Service 拓扑、Metrics 集成
语言生态Java/Go/Node/Python/Go 官方库Go/Node/Python/Java/.NET 官方库
生产成熟度Twitter 规模验证Uber 规模验证,CNCF 标杆
运维成本低(All-in-One 单 jar)中(多组件 + Kafka 缓冲)

架构差异示意:

Zipkin:
  App → Reporter (HTTP POST) → Collector → Storage → UI

Jaeger (生产级):
  App → Jaeger Client → Agent (UDP **6831/6832**) → Collector → Kafka → Ingester → Storage → UI
                                                ↑                                    ↑
                                            缓冲削峰                            异步消费

选型决策:

场景选型理由
Spring Cloud 微服务ZipkinSleuth 原生集成,零侵入
Kubernetes + gRPCJaegerAgent UDP 模式低开销,OTel 标准
需要依赖拓扑分析Jaeger内置 Service Graph 视图
极简部署、低运维Zipkin单 jar 启动,All-in-One
多语言(Go/Node/Py)Jaeger各语言官方 Client 更完善
未来迁移 OTel两者皆可都已适配 OpenTelemetry 协议
超大规模(> 10w QPS)Jaeger + KafkaAgent + Kafka 削峰能力强

共同趋势:

  • 两者都向 OpenTelemetry 收敛,OTel 成为数据采集标准。
  • Jaeger 后端已支持接收 OTel 协议,Zipkin 同样可桥接。
  • 新项目推荐 OTel SDK + Jaeger / Tempo 后端,Zipkin 适合存量 Spring Cloud 体系。
5 Zipkin 的存储后端有哪些?各自适用什么场景?

答案:

Zipkin 通过 SpanStore 接口抽象存储层,支持多种后端实现,生产环境选型需结合数据量、查询性能与运维成本。

存储后端对比:

存储数据规模查询性能写入吞吐运维成本适用场景
In-Memory小(< 10万 Span)极快极快开发测试
MySQL中(百万级)中小规模、已有 MySQL 集群
PostgreSQL中(百万级)已有 PG 集群
Cassandra大(亿级)极高中高大规模生产、Twitter 原始选择
Elasticsearch大(亿级)高(全文检索)复杂查询、已有 ES 集群

MySQL Schema(V2):

CREATE TABLE zipkin_spans (
  trace_id_high BIGINT NOT NULL,
  trace_id      BIGINT NOT NULL,
  id            BIGINT NOT NULL,
  parent_id     BIGINT,
  name          VARCHAR(255),
  kind          VARCHAR(10),
  timestamp     BIGINT,
  duration      BIGINT,
  PRIMARY KEY (trace_id_high, trace_id, id, kind)
);

CREATE TABLE zipkin_annotations (
  trace_id_high BIGINT NOT NULL,
  trace_id      BIGINT NOT NULL,
  span_id       BIGINT NOT NULL,
  a_key         VARCHAR(255) NOT NULL,
  a_value       TEXT,
  a_type        INT,
  endpoint_service_name VARCHAR(255),
  PRIMARY KEY (trace_id_high, trace_id, span_id, a_key, timestamp)
);

CREATE INDEX idx_zipkin_annotations_ts
  ON zipkin_annotations (endpoint_service_name, a_type, trace_id_high, trace_id, span_id);

Elasticsearch 索引模板:

# 启动 Zipkin + ES
docker run -d --name zipkin \
  -e STORAGE_TYPE=elasticsearch \
  -e ES_HOSTS=http://es:9200 \
  -p 9411:9411 \
  openzipkin/zipkin

ES 自动按天创建索引 zipkin:span-2026-06-06,支持按 serviceNametags.http.method 等检索。

Cassandra 适用场景:

  • Twitter 内部使用,Cassandra 是 Zipkin 最初的"原生"存储。
  • 写入吞吐量高(百万级 Span/s),适合大流量生产。
  • 缺点:Schema 设计宽列,二次查询需建二级索引。

选型决策:

业务量级推荐存储
< 1k TPSIn-Memory / MySQL
1k ~ 10k TPSMySQL / PostgreSQL
10k ~ 100k TPSElasticsearch
> 100k TPSCassandra + Kafka 缓冲
6 如何在 Spring Cloud 微服务中集成 Zipkin?关键配置有哪些?

答案:

Spring Cloud Sleuth(已合并至 Micrometer Tracing)是 Spring 生态与 Zipkin 的官方集成方案,通过自动埋点 + 少量配置即可接入。

核心依赖(Spring Boot 2.x + Sleuth):

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-zipkin</artifactId>
</dependency>
<!-- Web 组件自动埋点 -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>

Spring Boot 3.x + Micrometer Tracing:

<dependency>
    <groupId>io.micrometer</groupId>
    <artifactId>micrometer-tracing-bridge-brave</artifactId>
</dependency>
<dependency>
    <groupId>io.zipkin.reporter2</groupId>
    <artifactId>zipkin-reporter-brave</artifactId>
</dependency>

配置文件(application.yml):

spring:
  application:
    name: order-service          # 必填,对应 Zipkin localEndpoint.serviceName
  zipkin:
    base-url: http://zipkin:9411
    sender:
      type: web                  # web / kafka / rabbit
    compression-enabled: true     # gzip 压缩,减少网络带宽
  sleuth:
    sampler:
      probability: 0.1           # 10% 采样
    propagation:
      type: B3                   # 跨服务传递协议
    enabled: true

自动埋点覆盖范围:

组件是否埋点备注
Spring MVC每次 HTTP 调用生成 Span
RestTemplate通过 RestTemplateInterceptor
OpenFeign自动传递 Header
WebClient响应式链路追踪
Spring Scheduling定时任务 Span
Spring MessagingMQ 消费 Span
JdbcTemplate是(需开启)慢 SQL 检测
Kafka消费者 Producer Span
RabbitMQProducer/Consumer 双向

自定义 Span:

@Autowired
private Tracer tracer;

public void processOrder(Order order) {
    Span newSpan = tracer.nextSpan().name("validate-inventory").start();
    try (Tracer.SpanInScope ws = tracer.withSpan(newSpan)) {
        // 业务逻辑
        newSpan.tag("order.id", order.getId());
        inventoryService.check(order);
    } catch (Exception e) {
        newSpan.error(e);
    } finally {
        newSpan.end();
    }
}

自定义 Tag 与 Log:

span.tag("user.id", userId);          // 搜索时可按 user.id 过滤
span.event("cache.miss");              // 事件记录
span.error(exception);                 // 自动记录异常堆栈

生产最佳实践:

  • 统一 spring.application.name,确保 Zipkin UI 区分服务。
  • 使用 probability: 0.1 起步,根据存储成本调整。
  • 高吞吐场景切换 sender.type: kafka,避免同步 HTTP 阻塞业务线程。
  • 开启 compression-enabled: true,Span 数据 gzip 后带宽下降 60%+。
7 什么是 B3 协议?B3 与 W3C TraceContext 的核心区别是什么?

答案:

B3(BigBrotherBird)是 Zipkin 定义的跨服务追踪上下文传播协议,规定了 HTTP Headers 在服务间如何传递 traceId、spanId、采样决策等字段。

B3 Header 完整字段:

Header含义示例
X-B3-TraceIdTrace 全局 ID(Hex,16 或 32 字节)0af7651916cd43dd8448eb211c80319
X-B3-SpanId当前 Span IDb7ad6b7169203331
X-B3-ParentSpanId父 Span ID(Root 时不传递)00f067aa0ba902b7
X-B3-Sampled采样决策1(采样) / 0(不采样)
X-B3-Flags调试标志1(强制采样) / 0
b3复合 Header(单 Header 模式)0af7651916cd43dd-b7ad6b7169203331-1

B3 单 Header 模式(b3):

b3: 0af7651916cd43dd-b7ad6b7169203331-8448eb211c80319-1
     │                │                │                │
     │                │                │                └─ Sampled (0/1/d)
     │                │                └─ Parent Span ID (可选)
     │                └─ Span ID
     └─ Trace ID

W3C TraceContext 协议:

Header含义示例
traceparentTrace + Span + Flags00-0af7651916cd43dd8448eb211c80319-b7ad6b7169203331-01
tracestate厂商扩展字段congo=t61rcWkgMzE,rojo=00f067aa0ba902b7
tracestate: 格式vendor=value多个 vendor 用逗号分隔

核心对比:

维度B3W3C TraceContext
标准方Zipkin / TwitterW3C(行业标准)
版本Zipkin 1.x 起2020 年正式发布
多 Vendor 协作不支持tracestate 支持多厂商上下文
Header 数量最多 5 个 B3 Header 或 1 个 b3固定 1 个 traceparent + tracestate
TraceID 长度16 / 32 字节可选固定 32 字节(128 bit)
SpanID 长度8 字节(64 bit)8 字节(64 bit)
兼容性主流框架均支持新框架默认采用
OpenTelemetry支持默认协议

B3 与 W3C 共存方案:

# Spring Boot 同时启用 B3 与 W3C
spring:
  sleuth:
    propagation:
      type: B3,W3C    # 双协议注入,按 Header 优先级解析

跨协议桥接(OpenTelemetry Collector):

# otel-collector-config.yaml
receivers:
  zipkin:
    endpoint: 0.0.0.0:9411

exporters:
  otlp:
    endpoint: jaeger:4317

service:
  pipelines:
    traces:
      receivers: [zipkin]
      exporters: [otlp]

通过 Collector 将 B3 上报转换为 W3C 协议,写入 Jaeger / Tempo 后端,实现协议统一。

8 Zipkin 如何与 OpenTelemetry 集成?迁移路径如何设计?

答案:

OpenTelemetry(OTel)是 CNCF 主导的可观测性数据采集统一标准,Zipkin 既是 OTel 的协议实现之一,也是 OTel 可桥接的目标后端。

集成方式一:Zipkin 作为 OTel Exporter

<dependency>
    <groupId>io.opentelemetry</groupId>
    <artifactId>opentelemetry-exporter-zipkin</artifactId>
</dependency>
SpanExporter zipkinExporter = ZipkinSpanExporter.builder()
    .setEndpoint("http://zipkin:9411/api/v2/spans")
    .build();

SdkTracerProvider tracerProvider = SdkTracerProvider.builder()
    .addSpanProcessor(SimpleSpanProcessor.create(zipkinExporter))
    .build();

集成方式二:OTel Collector 桥接 Zipkin(生产推荐)

# otel-collector 配置
receivers:
  otlp:
    protocols:
      grpc:
        endpoint: 0.0.0.0:4317
      http:
        endpoint: 0.0.0.0:4318

exporters:
  zipkin:
    endpoint: http://zipkin:9411/api/v2/spans
    format: json

service:
  pipelines:
    traces:
      receivers: [otlp]
      exporters: [zipkin]

应用使用 OTel SDK 上报到 Collector,Collector 转换为 Zipkin JSON 协议后写入 Zipkin 后端。

集成方式三:Zipkin Bridge 反向接收 OTel 数据

// 使用 zipkin-reporter-otel
@Bean
public Reporter<Span> zipkinReporter() {
    return OpenTelemetrySpanExporter.create("http://zipkin:9411/api/v2/spans");
}

迁移路径设计:

阶段 1: 现状评估
  ├── 列出所有使用 Zipkin 客户端的服务
  ├── 统计 SDK 版本、协议类型(B3 / Thrift)
  └── 评估存储后端类型与数据量

阶段 2: 引入 OTel SDK(双写过渡)
  ├── 应用层 OTel SDK 初始化
  ├── 保留 zipkin-reporter 兼容旧版
  ├── 部署 OTel Collector 接收 OTLP
  └── 灰度 10% 流量验证数据一致性

阶段 3: 协议统一
  ├── 全量切流 OTel SDK
  ├── 通过 Collector 桥接至 Zipkin
  ├── 验证 traceId / spanId / parentId 一致
  └── 关闭 zipkin-reporter 直连

阶段 4: 后端演进
  ├── 保留 Zipkin(成本低、UI 简洁)
  ├── 或迁移至 Jaeger / Tempo(OTel 原生)
  └── 长期方案:OTel SDK + Tempo + Grafana

关键注意事项:

  • B3 与 W3C TraceContext 协议不同,迁移时需在 Header 注入层做兼容。
  • Zipkin 1.x 与 2.x 协议格式差异(/api/v1/spans vs /api/v2/spans),OTel Exporter 默认走 v2。
  • TraceId 长度变化:B3 16 字节 → W3C 32 字节,需确保存储后端 Schema 兼容。
  • 已使用 Spring Cloud Sleuth 的项目,建议直接升级到 Micrometer Tracing,避免重写埋点。
9 Zipkin 在生产环境中有哪些常见的性能瓶颈与优化手段?

答案:

Zipkin 架构简单,但生产高 QPS 场景下仍可能遇到 Collector 单点、存储写入慢、查询超时等问题,需要从采集、传输、存储、查询四个环节分别优化。

生产瓶颈与解决方案:

瓶颈现象根因解决方案
Collector 过载业务线程阻塞,HTTP 503同步阻塞式入库引入 Kafka / RabbitMQ 缓冲
存储写入慢Collector 队列堆积MySQL 单库写入瓶颈切换 ES / Cassandra,或水平分库
采样率过高存储成本爆炸100% 全量采集概率采样 1% ~ 10%
网络带宽跨机房带宽打满Span 体积大gzip 压缩 + 精简 Tags
查询慢UI 加载超时全表扫描、索引缺失存储后端加索引(serviceName + time)
Span 风暴突发流量击穿错误重试循环RateLimiting + 熔断
依赖图加载慢UI 卡顿Trace 数量过多按 Service + Time 范围限制

Kafka 缓冲架构(生产推荐):

# Zipkin Server 启动配置
STORAGE_TYPE=elasticsearch
ES_HOSTS=http://es:9200

# Collector 端通过 Kafka 异步上报
KAFKA_BOOTSTRAP_SERVERS=kafka:9092
KAFKA_TOPIC=zipkin-spans
ZIPKIN_COLLECTOR_KAFKA_ENABLED=true
// 应用端配置(Spring Boot)
spring:
  zipkin:
    sender:
      type: kafka
    kafka:
      bootstrap-servers: kafka:9092
      topic: zipkin-spans

采样与埋点优化:

// 1. 自适应采样:核心接口高概率,非核心低概率
@Bean
public Sampler customSampler() {
    return new CompositeSampler()
        .add("/api/payment/**", 1.0)        // 支付链路 100%
        .add("/api/health", 0.0)            // 健康检查 0%
        .defaultRate(0.05);                 // 其他 5%
}

// 2. 精简 Tags,避免记录敏感与冗余信息
span.tag("order.id", order.getId());
// 不要做:
// span.tag("request.body", jsonString);  // 体积大、可能含敏感数据

存储后端优化(Elasticsearch 为例):

// 索引模板
{
  "index_patterns": ["zipkin:span-*"],
  "settings": {
    "number_of_shards": 6,
    "number_of_replicas": 1,
    "refresh_interval": "10s"
  },
  "mappings": {
    "properties": {
      "traceId": { "type": "keyword" },
      "name": { "type": "keyword" },
      "timestamp_millis": { "type": "long", "index": false },
      "tags": { "type": "object", "dynamic": true }
    }
  }
}
  • 按天滚动索引,避免单索引过大。
  • traceIdnamekeyword 不分词,节省空间。
  • 配置 ILM 自动删除 7 天前数据。

Collector 水平扩展:

# 部署多个 Zipkin Collector 实例
apiVersion: apps/v1
kind: Deployment
metadata:
  name: zipkin-collector
spec:
  replicas: 3
  template:
    spec:
      containers:
      - name: zipkin
        image: openzipkin/zipkin
        env:
        - name: STORAGE_TYPE
          value: elasticsearch
        - name: ES_HOSTS
          value: http://es:9200

通过 K8s Service 对外暴露,应用通过 DNS 负载均衡到多个 Collector 实例。

容量规划参考:

QPS采样率日均 Span存储(30d)推荐后端
1,00010%8.6 亿~500 GBMySQL / PG
10,0005%4.3 亿~300 GBES(3 节点)
100,0001%8.6 亿~600 GBES(6 节点)/ Cassandra
1,000,0000.5%43 亿~3 TBCassandra + Kafka
10 Zipkin 在生产中的典型故障排查案例有哪些?

答案:

Zipkin 在微服务架构中的核心价值是快速定位跨服务调用链路的延迟、错误与瓶颈,以下是常见生产案例与排查方法。

案例一:某接口 P99 延迟突增,从 200ms 升至 5s

排查步骤:
1. Zipkin UI 搜索 serviceName=order-service,按 duration 降序
2. 发现 span "GET /api/inventory" 耗时 4.8s,占比 95%
3. 展开 span 查看 tags:http.status_code=200 但 db.statement 显示
4. 继续下钻 "SELECT * FROM inventory WHERE sku=?" 耗时 4.5s
5. 查看对应 service=inventory-service 的其他 Trace
6. 发现同一时间窗口存在慢 SQL + 连接池等待

根因:inventory-service 数据库缺失 sku 联合索引,全表扫描导致
解决:CREATE INDEX idx_inventory_sku ON inventory(sku)
验证:修复后 P99 下降至 180ms

案例二:下单接口随机报错 5%,错误源不明

排查步骤:
1. Zipkin UI 搜索 tags.error=true,serviceName=order-service
2. 错误 Trace 中定位到 span "POST payment-service" 抛异常
3. 查看 annotation:cs 存在但缺失 cr,duration 异常短
4. 推断为客户端超时(connectTimeout=500ms, readTimeout=2s)
5. 继续下钻:payment-service 在该时间窗口 CPU 100%
6. 查看 payment-service 自身 Trace,发现大量 Span "fegin-retry"

根因:payment-service 因 GC 频繁(Young GC 200ms+)处理变慢,
     触发客户端超时与重试,雪崩效应
解决:
  - 调整 JVM 堆内存(-Xmx 4g → 8g)
  - payment-service 接口降级(非关键查询走缓存)
  - 客户端禁用自动重试(feign.client.config.default.connectTimeout=2000,readTimeout=5000)

案例三:Zipkin UI 无法显示依赖图

现象:UI 页面打开后无响应,依赖图加载失败
排查:
1. 浏览器 Network 查看 /api/v2/dependencies 请求超时 30s
2. Zipkin Server 日志显示:QueryService 慢查询
3. 后端 MySQL 慢日志:SELECT COUNT(*) FROM zipkin_spans_dependencies 全表扫描
4. 存储后端存储了 90 天历史数据,依赖计算范围过大

根因:Zipkin 默认按 serviceName 全量计算依赖,数据膨胀导致超时
解决:
  - 缩短依赖分析时间窗口(UI 限定 24h)
  - MySQL 改 ES,利用 ES 聚合计算能力
  - 配置数据保留策略:7d 后自动清理(zipkin.storage.strict-trace-id-ttl=true)

案例四:跨机房调用 Trace 断裂,部分服务无 Span

现象:调用链 order-service → payment-service(跨机房),
     UI 上 payment-service Span 缺失
排查:
1. 抓取 order-service 出站请求 Header
2. 发现 X-B3-TraceId 存在,但 X-B3-SpanId 为空
3. 检查 order-service 网关(Spring Cloud Gateway)配置
4. 网关未开启 trace propagation,未透传 B3 Header

根因:Spring Cloud Gateway 与下游服务使用 Sleuth 时,需在 Gateway
     Filter 中显式传递 Header
解决:

spring: cloud: gateway: default-filters: - DedupeResponseHeader=Access-Control-Allow-Origin Access-Control-Allow-Credentials, RETAIN_UNIQUE sleuth: propagation: type: B3 factory-class-name: org.springframework.cloud.sleuth.brave.propagation.B3Propagation


**案例五:高 QPS 场景下应用线程阻塞**

现象:业务线程池排队,响应延迟上升 排查:

  1. 业务线程 Dump 显示大量线程阻塞在 Brave 的 httpClient.send
  2. Zipkin Server 端无响应,Collector 队列积压
  3. 监控显示 Zipkin Receiver QPS=0.3k,应用实际产生 5k Span/s

根因:同步 HTTP 上报,Collector 慢时阻塞业务线程 解决:

  • 切换 sender.type: kafka
  • 应用线程不再等待 Zipkin ACK
  • 引入 OTel Collector 作为旁路,缓解 Zipkin 写入压力

**生产排查工具链:**

| 工具 | 用途 |
|------|------|
| **Zipkin UI** | Trace 时间线、Span 详情、依赖图 |
| **Zipkin API** | `GET /api/v2/trace/{traceId}` 编程化查询 |
| **TraceID 关联日志** | Sleuth 自动注入 MDC,ELK / Loki 可按 traceId 聚合 |
| **Metrics 联动** | Prometheus + Zipkin Tag serviceName 关联指标 |
| **火焰图** | SkyWalking / Jaeger 支持,与 Zipkin 数据互通 |

**核心原则:**

- 跨服务问题优先看 Trace,单服务问题优先看 Metrics。
- 关注 Span duration 占比,找到长尾 Span 即找到瓶颈。
- 生产环境开启 `tags.error=true` 与 `duration > 阈值` 告警。
- 始终为每个服务注入 `serviceName` + `host` + `env` 标签,便于多环境隔离。