微服务可观测性为什么需要链路追踪
微服务架构下,一个业务请求可能横跨5-10个服务实例,延迟毛刺和错误排查变得困难。链路追踪(Distributed Tracing)通过为每个请求分配全局唯一的Trace ID,并在服务间透传,将散落在各服务日志中的调用关系串联成完整的调用链。Spring Boot 3.x已将Micrometer Tracing作为官方观测性方案,替代了Spring Cloud Sleuth。
没有链路追踪的排查流程:用户报500错误 → 查网关日志 → 找到下游服务名 → 登录该服务实例查日志 → 发现调了另一个服务 → 继续查…至少30分钟。有链路追踪后:Trace ID一搜,全链路耗时、错误点、调用参数一目了然。
Micrometer Tracing集成配置
Spring Boot 3.2+使用Micrometer Tracing + Zipkin/Jaeger作为链路追踪方案:
<!-- pom.xml -->
<dependency>
<groupId>io.micrometer</groupId>
<artifactId>micrometer-tracing-bridge-brave</artifactId>
</dependency>
<dependency>
<groupId>io.zipkin.reporter2</groupId>
<artifactId>zipkin-reporter-brave</artifactId>
</dependency>
<dependency>
<groupId>io.micrometer</groupId>
<artifactId>micrometer-observation-test</artifactId>
<scope>test</scope>
</dependency>
application.yml配置:
management:
tracing:
sampling:
probability: 1.0 # 采样率,生产环境建议0.1-0.3
propagation:
type: w3c # 使用W3C标准传播格式
zipkin:
tracing:
endpoint: http://zipkin:9411/api/v2/spans
endpoints:
web:
exposure:
include: health,info,prometheus
metrics:
distribution:
percentiles-histogram:
http.server.requests: true
slo:
http.server.requests: 50ms,100ms,200ms,500ms,1s
采样率说明:probability: 1.0表示100%采样,适合开发测试环境。生产环境建议0.1-0.3,每10个请求追踪1个,兼顾可观测性和存储成本。关键业务接口(支付、下单)可通过自定义采样策略强制100%采样。
跨服务Trace ID透传
微服务间调用需要透传Trace ID,Spring Boot 3.x通过Micrometer自动处理HTTP和gRPC调用的传播。但以下场景需要手动处理:
1. 使用RestTemplate或WebClient调用外部服务
2. 通过消息队列(Kafka/RabbitMQ)异步调用
3. 使用@Async注解的异步方法
RestTemplate自动传播配置:
@Configuration
public class TracingConfig {
@Bean
public RestTemplate restTemplate(RestTemplateBuilder builder) {
// Micrometer自动注入TracingObservationHandler,
// RestTemplate经过builder构建即可自动传播Trace ID
return builder.build();
}
}
WebClient自动传播配置:
@Bean
public WebClient webClient(WebClientBuilder builder) {
return builder.build();
}
Kafka消息传播需要在生产者和消费者端分别配置:
# 生产者端:Spring Boot 3.x自动将Trace ID写入Kafka消息头
# 消费者端:启用Kafka Observation
spring.kafka.listener.observation-enabled=true
@Async方法的传播需要使用Observation包装:
@Service
public class OrderService {
private final Tracer tracer;
public OrderService(Tracer tracer) {
this.tracer = tracer;
}
@Async
public void processOrderAsync(Order order) {
// @Async会丢失父线程的Trace上下文
// 需要在调用方手动传播
Span span = tracer.nextSpan().name("process-order-async").start();
try (Tracer.SpanInScope scope = tracer.withSpan(span)) {
// 异步业务逻辑
doProcess(order);
} finally {
span.end();
}
}
}
Resilience4j熔断器配置与状态机
熔断器(Circuit Breaker)是微服务降级的核心组件。当下游服务故障率超过阈值,熔断器打开,后续请求直接走降级逻辑,避免级联故障。
Resilience4j熔断器状态机:
– CLOSED:正常状态,请求正常通过
– OPEN:熔断状态,请求直接拒绝走降级
– HALF_OPEN:半开状态,允许少量请求探测下游是否恢复
// application.yml
resilience4j:
circuitbreaker:
configs:
default:
sliding-window-size: 100 # 滑动窗口大小
failure-rate-threshold: 50 # 失败率阈值50%
slow-call-duration-threshold: 3s # 慢调用阈值3秒
slow-call-rate-threshold: 60 # 慢调用率阈值60%
permitted-number-of-calls-in-half-open-state: 5
wait-duration-in-open-state: 30s # 熔断后等待30秒进入半开
automatic-transition-from-open-to-half-open-enabled: true
instances:
orderService:
base-config: default
failure-rate-threshold: 40 # 订单服务更敏感
paymentService:
base-config: default
failure-rate-threshold: 30 # 支付服务极度敏感
wait-duration-in-open-state: 60s # 支付熔断后等待更久
代码中使用熔断器:
@Service
public class PaymentGateway {
@CircuitBreaker(name = "paymentService", fallbackMethod = "paymentFallback")
public PaymentResult charge(PaymentRequest request) {
return paymentClient.doCharge(request);
}
private PaymentResult paymentFallback(PaymentRequest request, Exception e) {
// 降级逻辑:记录待处理支付,后续补偿
log.warn("Payment service circuit open, fallback triggered", e);
return PaymentResult.pending(request.getOrderId());
}
}
限流器与重试策略配置
熔断器解决的是下游故障场景,限流器(Rate Limiter)解决的是自我保护场景——防止突发流量压垮自身服务。重试策略(Retry)解决的是瞬态故障——网络抖动导致的偶发失败。
resilience4j:
ratelimiter:
configs:
default:
limit-for-period: 100 # 每个周期允许100次
limit-refresh-period: 1s # 1秒一个周期
timeout-duration: 5s # 等待获取许可的超时时间
instances:
orderApi:
base-config: default
limit-for-period: 200 # 订单API更高并发
retry:
configs:
default:
max-attempts: 3 # 最多重试3次
wait-duration: 500ms # 重试间隔500ms
retry-exceptions:
- java.io.IOException
- java.util.concurrent.TimeoutException
instances:
paymentRetry:
base-config: default
max-attempts: 5 # 支付场景多重试几次
wait-duration: 1s
exponential-backoff-multiplier: 2 # 指数退避
组合使用熔断器+限流器+重试:
@Service
public class OrderService {
@RateLimiter(name = "orderApi")
@CircuitBreaker(name = "orderService", fallbackMethod = "createOrderFallback")
@Retry(name = "paymentRetry")
public OrderResult createOrder(OrderRequest request) {
return orderClient.submit(request);
}
private OrderResult createOrderFallback(OrderRequest request, Exception e) {
log.error("Order creation failed, fallback", e);
return OrderResult.fail("系统繁忙,请稍后重试");
}
}
注意注解顺序:@RateLimiter在外层限流,@CircuitBreaker中间层熔断,@Retry最内层重试。顺序反了会导致重试请求绕过限流器。
熔断器监控与健康检查
Resilience4j内置Micrometer指标导出,可直接接入Prometheus:
management:
endpoints:
web:
exposure:
include: health,prometheus
# Prometheus采集到的关键指标
# resilience4j_circuitbreaker_state - 熔断器状态(0=closed,1=open,2=half_open)
# resilience4j_circuitbreaker_calls_total - 调用总数
# resilience4j_circuitbreaker_failure_rate - 失败率
# resilience4j_circuitbreaker_slow_call_rate - 慢调用率
# resilience4j_ratelimiter_available_permissions - 限流器剩余许可
# resilience4j_retry_calls_total - 重试调用总数
Grafana告警规则——熔断器打开时告警:
groups:
- name: resilience4j_alerts
rules:
- alert: CircuitBreakerOpen
expr: resilience4j_circuitbreaker_state{state="open"} == 1
for: 1m
labels:
severity: critical
annotations:
summary: "熔断器 {{ $labels.name }} 已打开"
description: "服务 {{ $labels.instance }} 的 {{ $labels.name }} 熔断器处于OPEN状态"
- alert: HighFailureRate
expr: resilience4j_circuitbreaker_failure_rate > 0.3
for: 5m
labels:
severity: warning
annotations:
summary: "{{ $labels.name }} 失败率超过30%"
健康检查端点集成:
@Configuration
public class Resilience4jHealthConfig {
@Bean
public CircuitBreaker circuitBreakerOrder(
CircuitBreakerRegistry registry) {
return registry.circuitBreaker("orderService", () -> {
CircuitBreakerConfig config = CircuitBreakerConfig.custom()
.failureRateThreshold(50)
.slidingWindowSize(100)
.waitDurationInOpenState(Duration.ofSeconds(30))
.build();
return config;
});
}
}
// /actuator/health端点会自动包含熔断器状态
// 当任意熔断器OPEN时,健康检查状态变为DOWN
实战案例:支付服务故障的全链路降级
某电商平台的支付服务因第三方网关故障导致50%请求超时。链路追踪定位耗时分布:
# Zipkin中某条Trace的Span详情
# [gateway] 10:00:00.000 - 10:00:00.050 (50ms)
# [order-svc] 10:00:00.050 - 10:00:00.100 (50ms)
# [pay-svc] 10:00:00.100 - 10:00:05.100 (5000ms, TIMEOUT!)
# 整条链路耗时5050ms,支付服务占99%
处理流程:
1. Resilience4j熔断器检测到paymentService失败率超过40%,30秒内自动打开熔断
2. 后续支付请求走fallback,返回pending状态,订单标记为待支付
3. 订单服务通过定时任务补偿未完成的支付
4. 熔断器30秒后进入HALF_OPEN,允许5个请求探测
5. 支付网关恢复后,5个探测请求成功,失败率降到阈值以下,熔断器关闭
// 补偿定时任务
@Scheduled(fixedDelay = 60000) // 每分钟扫描一次
public void compensatePendingPayments() {
List<Order> pendingOrders = orderRepository
.findByStatusAndCreatedAtBefore(OrderStatus.PENDING_PAYMENT,
LocalDateTime.now().minusMinutes(5));
for (Order order : pendingOrders) {
try {
PaymentResult result = paymentGateway.charge(
new PaymentRequest(order));
if (result.isSuccess()) {
order.complete();
}
} catch (Exception e) {
log.warn("Compensation retry failed for order {}",
order.getId(), e);
}
}
}
这套Micrometer Tracing + Resilience4j方案,从链路追踪集成、跨服务传播、熔断降级、限流重试到监控告警,覆盖了Spring Boot微服务在生产环境中的可观测性与容错性落地的完整路径。
原创文章,作者:小编,如若转载,请注明出处:https://www.yunthe.com/springboot-wei-fu-wu-lian-lu-zhui-zong-yu-rong-duan-jiang/