Spring WebFlux中Micrometer与Zipkin2集成问题求助
Spring WebFlux 3.0.5 集成 Micrometer、Zipkin2 与 Brave 正确配置方案
一、修正 Gradle 依赖
确保依赖版本匹配 Spring WebFlux 3.0.5(对应 Spring Boot 3.0.x 系列),避免依赖冲突:
dependencies { // Spring WebFlux 核心 implementation 'org.springframework.boot:spring-boot-starter-webflux:3.0.5' // Micrometer 与 Brave 桥接 implementation 'io.micrometer:micrometer-tracing-bridge-brave:1.0.4' implementation 'io.micrometer:micrometer-registry-prometheus:1.10.5' // Zipkin 上报组件 implementation 'io.zipkin.reporter2:zipkin-reporter-brave:2.16.3' // Netty 依赖(与 Spring Boot 内置版本对齐) implementation 'io.netty:netty-codec-http:4.1.94.Final' }
二、解决 MeterRegistry 初始化 NPE 问题
之前的空指针是因为启动阶段 MDC 中无 TraceId,不能直接在初始化时绑定标签。WebFlux 是异步场景,需通过 Reactor Context 传递 TraceId,配合动态 MeterFilter 实现指标标签注入:
1. 核心追踪配置类
import io.micrometer.core.instrument.MeterRegistry; import io.micrometer.core.instrument.config.MeterFilter; import io.micrometer.tracing.Tracer; import io.zipkin.reporter2.AsyncZipkinSpanHandler; import io.zipkin.reporter2.ZipkinReporter; import io.zipkin.reporter2.okhttp3.OkHttpSender; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @Configuration public class TracingConfig { // 绑定 Brave Tracer 到 Micrometer @Bean public Tracer braveTracer(com.github.kristofa.brave.Tracing braveTracing) { return new BraveTracer(braveTracing); } // 动态为指标添加 TraceId 标签(仅当存在活跃 Span 时生效) @Bean public MeterFilter traceIdMeterFilter(Tracer tracer) { return MeterFilter.commonTags(() -> { if (tracer.currentSpan() != null) { return java.util.Map.of("traceId", tracer.currentSpan().context().traceId()); } return java.util.Map.of(); }); } // 配置 Zipkin 上报处理器 @Bean public com.github.kristofa.brave.SpanHandler zipkinSpanHandler(ZipkinReporter<io.zipkin2.Span> reporter) { return AsyncZipkinSpanHandler.create(reporter); } // 配置 Zipkin 上报器 @Bean public ZipkinReporter<io.zipkin2.Span> zipkinReporter() { return OkHttpSender.create("http://localhost:9411/api/v2/spans") .buildReporter(); } // 初始化 Brave 核心追踪实例 @Bean public com.github.kristofa.brave.Tracing braveTracing() { return com.github.kristofa.brave.Tracing.newBuilder() .localServiceName("your-service-name") .build(); } }
2. WebFlux 上下文传递 TraceId
在过滤器中将 TraceId 放入 Reactor Context,替代 ThreadLocal 版 MDC:
import io.micrometer.tracing.Tracer; import org.springframework.core.annotation.Order; import org.springframework.stereotype.Component; import org.springframework.web.server.ServerWebExchange; import org.springframework.web.server.WebFilter; import org.springframework.web.server.WebFilterChain; import reactor.core.publisher.Mono; @Component @Order(1) public class TraceIdContextFilter implements WebFilter { private final Tracer tracer; public TraceIdContextFilter(Tracer tracer) { this.tracer = tracer; } @Override public Mono<Void> filter(ServerWebExchange exchange, WebFilterChain chain) { return chain.filter(exchange) .contextWrite(context -> { if (tracer.currentSpan() != null) { return context.put("traceId", tracer.currentSpan().context().traceId()); } return context; }); } }
3. 日志中输出 TraceId
配置 Logback 读取 Reactor Context 中的 TraceId,修改 logback-spring.xml:
<appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender"> <encoder> <pattern>%d{HH:mm:ss.SSS} [%X{traceId}] [%thread] %-5level %logger{36} - %msg%n</pattern> </encoder> </appender>
添加 Reactor 上下文到 MDC 的钩子:
import io.micrometer.tracing.Tracer; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import reactor.core.publisher.Hooks; @Configuration public class ReactorMdcConfig { @Bean public void reactorMdcHook(Tracer tracer) { Hooks.onEachOperator((scannable, coreSubscriber) -> { coreSubscriber.currentContext().getOrEmpty("traceId") .ifPresent(traceId -> { try (var scope = tracer.withSpan(tracer.currentSpan())) { // 绑定到 MDC 供日志使用 org.slf4j.MDC.put("traceId", traceId); } }); return coreSubscriber; }); } }
三、解决 localhost:9411 连接拒绝问题
该错误是因为 Zipkin 服务未启动或配置错误,两种解决方式:
1. 启动本地 Zipkin 服务
用 Docker 快速启动:
docker run -d -p 9411:9411 openzipkin/zipkin:2.24.3
或下载 Jar 包启动:
curl -sSL https://zipkin.io/quickstart.sh | bash -s java -jar zipkin.jar
2. 临时禁用 Zipkin 上报(调试用)
在 application.yml 中设置采样率为 0:
management: tracing: sampling: probability: 0.0
四、CustomTraceBaggage 正确配置
如需自定义跨服务传递的元数据,通过 Brave 的 BaggagePropagation 配置:
import com.github.kristofa.brave.BaggagePropagation; import com.github.kristofa.brave.Tracing; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @Configuration public class BaggageConfig { @Bean public Tracing braveTracing() { return Tracing.newBuilder() .localServiceName("your-service-name") .propagationFactory(BaggagePropagation.newFactoryBuilder() // 添加自定义 Baggage 键 .add(BaggagePropagation.SingleBaggageField.create("custom-baggage-key")) .build()) .build(); } }
五、验证配置
- 启动应用后访问端点,查看日志是否输出 TraceId;
- 访问 Zipkin UI(http://localhost:9411/zipkin),搜索服务名查看 Trace 数据;
- 访问
/actuator/prometheus,检查指标是否包含traceId标签。
内容的提问来源于stack exchange,提问作者LowCool
相关产品推荐
相关产品推荐

