Spring Boot 3.x Observability体系:Micrometer、Tracing与Logging的融合
·
Spring Boot 2.x时代,我们靠Spring Cloud Sleuth做链路追踪,靠Micrometer做指标。到了3.x,Sleuth被废弃,取而代之的是Micrometer Tracing + OpenTelemetry的统一方案。这不是简单的"换名字"——而是从"各管各的"到"三位一体"(Metrics+Traces+Logs)的架构升级。这篇讲清楚3.x的可观测性体系怎么搭,以及那些踩过的坑。
一、为什么需要统一的可观测性?
在微服务架构下,一个请求可能经过:
Gateway → Order Service → Payment Service → Inventory Service
当用户说"支付失败"时,你需要回答:
- 哪个环节慢了?(Metrics)
- 请求经过了哪些服务?(Traces)
- 具体报了什么错?(Logs)
在传统架构下,这三者分散在不同的系统里——Prometheus看指标、Jaeger看链路、ELK看日志。Spring Boot 3.x的目标是让这三者在同一个上下文中关联起来。
二、核心组件演进
2.1 Micrometer:指标的抽象层
<!-- Spring Boot 3.x 默认依赖 -->
<dependency>
<groupId>io.micrometer</groupId>
<artifactId>micrometer-core</artifactId>
</dependency>
关键变化:
| 维度 | Spring Boot 2.x | Spring Boot 3.x |
|---|---|---|
| 指标注册 | MeterRegistry | MeterRegistry(不变) |
| 链路追踪 | Spring Cloud Sleuth | Micrometer Tracing |
| 导出后端 | 各自配置 | 统一通过ObservationRegistry |
2.2 Micrometer Tracing:替代Sleuth
<dependency>
<groupId>io.micrometer</groupId>
<artifactId>micrometer-tracing-bridge-otel</artifactId>
</dependency>
为什么选OpenTelemetry?
- Sleuth是Spring生态专属,OTel是CNCF标准
- OTel支持更多语言(Java/Go/Python/Node.js)
- 社区活跃度更高,云厂商原生支持
2.3 Observation API:统一的入口
// Spring Boot 3.x 新增的Observation API
Observation observation = Observation.start("order.process", registry);
try {
// 业务逻辑
orderService.create(order);
} finally {
observation.stop();
}
Observation的作用:它同时记录指标和链路信息,确保两者使用同一个traceId。
三、实战配置
3.1 基础配置
management:
endpoints:
web:
exposure:
include: health,info,prometheus
metrics:
export:
prometheus:
enabled: true
tracing:
sampling:
probability: 1.0 # 采样率(生产环境建议0.1)
propagation:
type: w3c # W3C Trace Context标准
3.2 自定义Observation
@Component
public class OrderService {
private final ObservationRegistry registry;
public OrderService(ObservationRegistry registry) {
this.registry = registry;
}
public Order createOrder(OrderRequest request) {
return Observation.createNotStarted("order.create", registry)
.contextualName("create-order")
.lowCardinalityKeyValue("order.type", request.getType())
.highCardinalityKeyValue("order.id", request.getId())
.observe(() -> {
// 业务逻辑
return orderRepository.save(request.toEntity());
});
}
}
关键点:
- lowCardinalityKeyValue:用于聚合的标签(如order.type),基数低
- highCardinalityKeyValue:用于调试的标签(如order.id),基数高,不会出现在Prometheus指标中
3.3 链路传播
// RestTemplate自动携带traceId
RestTemplate restTemplate = new RestTemplate();
// Spring Boot 3.x 自动配置了ObservationRestTemplateCustomizer
// WebClient同理
WebClient client = WebClient.builder()
.filter(new ObservationWebClientFilter(registry))
.build();
四、日志与链路的关联
4.1 Logback配置
<configuration>
<appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
<!-- 添加traceId和spanId -->
<pattern>%d{yyyy-MM-dd HH:mm:ss} [%thread] %X{traceId:-} %X{spanId:-} %-5level %logger{36} - %msg%n</pattern>
</encoder>
</appender>
</configuration>
输出示例:
2026-07-07 14:30:01 [http-nio-8080-exec-1] a1b2c3d4e5f6 g7h8i9j0 INFO c.e.OrderService - Order created: 10086
4.2 MDC自动填充
Spring Boot 3.x 自动将traceId/spanId放入MDC,无需手动设置:
// 不需要这样写了
MDC.put("traceId", traceId);
// 直接在logback pattern里用%X{traceId}即可
五、常见陷阱
5.1 采样率设置不当
# ❌ 生产环境设为1.0会导致存储爆炸
tracing:
sampling:
probability: 1.0
# ✅ 根据流量调整
tracing:
sampling:
probability: 0.1 # 10%的请求被采样
5.2 高基数标签污染Prometheus
// ❌ 错误:把orderId作为lowCardinalityKeyValue
Observation.createNotStarted("order.create", registry)
.lowCardinalityKeyValue("order.id", orderId) // 每个orderId都是新标签
.observe(...);
// ✅ 正确:orderId用highCardinalityKeyValue
Observation.createNotStarted("order.create", registry)
.highCardinalityKeyValue("order.id", orderId) // 只出现在链路中
.lowCardinalityKeyValue("order.type", "vip") // 出现在Prometheus
.observe(...);
5.3 异步线程丢失traceId
// ❌ 普通线程池不传播traceId
executor.submit(() -> {
log.info("async task"); // traceId为空
});
// ✅ 使用ObservationAwareExecutor
ObservationAwareExecutor executor = new ObservationAwareExecutor(
Executors.newFixedThreadPool(10), registry);
六、监控看板示例
6.1 Grafana面板
# HTTP请求延迟P99
histogram_quantile(0.99, sum(rate(http_server_requests_seconds_bucket[5m])) by (le, uri))
# 错误率
sum(rate(http_server_requests_seconds_count{status=~"5.."}[5m]))
/
sum(rate(http_server_requests_seconds_count[5m]))
6.2 Jaeger/Zipkin链路查看
访问 http://localhost:9411/zipkin/ 查看链路拓扑。
七、总结
- Spring Boot 3.x用Micrometer Tracing替代Sleuth,底层基于OpenTelemetry
- Observation API是统一的入口,同时记录指标和链路
- 低基数标签用于Prometheus聚合,高基数标签用于链路调试
- 日志自动关联traceId,无需手动设置MDC
- 异步场景要用ObservationAwareExecutor,否则traceId丢失
- 采样率在生产环境要调低(0.1或更低),避免存储爆炸
更多推荐



所有评论(0)