Spring Cloud Edgware.SR1下如何将Sleuth Trace ID传递至EurekaHttpClient?
解决Spring Cloud Edgware.SR1中Sleuth Trace ID传递至EurekaHttpClient的问题
我之前在维护同版本的微服务架构时,也碰到过一模一样的问题——Edgware.SR1版本的Spring Cloud Sleuth默认不会对Eureka的HTTP请求做追踪包装,导致服务注册、心跳、拉取注册表这些Eureka相关调用,完全不会出现在Zipkin的链路视图里。下面是我实测可行的解决思路和代码实现:
1. 自定义EurekaHttpClient拦截器注入Trace信息
我们需要写一个拦截器,把当前线程的Sleuth Trace ID、Span ID等信息,放到Eureka请求的Header里,让Eureka Server能接收到这些追踪标识,进而被Zipkin捕获链路。
import brave.Span; import brave.Tracer; import com.netflix.discovery.EurekaHttpClient; import com.netflix.discovery.EurekaHttpRequest; import com.netflix.discovery.EurekaHttpResponse; import com.netflix.discovery.interceptor.EurekaHttpClientInterceptor; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; @Component public class TraceEurekaHttpClientInterceptor implements EurekaHttpClientInterceptor { private final Tracer tracer; @Autowired public TraceEurekaHttpClientInterceptor(Tracer tracer) { this.tracer = tracer; } @Override public <R> EurekaHttpResponse<R> intercept(EurekaHttpRequest request, EurekaHttpClient delegate) { Span currentSpan = tracer.currentSpan(); if (currentSpan != null) { // 把Sleuth标准的Trace头添加到Eureka请求里 request.getHeaders().put("X-B3-TraceId", currentSpan.context().traceIdString()); request.getHeaders().put("X-B3-SpanId", currentSpan.context().spanIdString()); request.getHeaders().put("X-B3-Sampled", currentSpan.context().sampled() != null ? currentSpan.context().sampled().toString() : "1"); } return delegate.execute(request); } }
2. 配置Eureka客户端加载自定义拦截器
接下来要让Eureka客户端用上我们的拦截器,通过自定义EurekaHttpClientFactory来替换默认的客户端工厂:
import com.netflix.discovery.EurekaHttpClient; import com.netflix.discovery.EurekaHttpClientFactory; import com.netflix.discovery.shared.transport.EurekaTransportConfig; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.cloud.netflix.eureka.EurekaClientConfigurer; import org.springframework.cloud.netflix.eureka.EurekaClientFactoryBean; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import java.util.Collections; @Configuration public class EurekaTraceConfig implements EurekaClientConfigurer { private final TraceEurekaHttpClientInterceptor traceInterceptor; @Autowired public EurekaTraceConfig(TraceEurekaHttpClientInterceptor traceInterceptor) { this.traceInterceptor = traceInterceptor; } @Override public void configureEurekaHttpClientFactory(EurekaClientFactoryBean factory) { factory.setEurekaHttpClientFactory(new EurekaHttpClientFactory() { @Override public EurekaHttpClient newClient(EurekaTransportConfig transportConfig) { // 获取默认Eureka客户端,再添加我们的追踪拦截器 EurekaHttpClient defaultClient = EurekaHttpClientFactory.DEFAULT.newClient(transportConfig); return defaultClient.interceptWith(Collections.singletonList(traceInterceptor)); } }); } }
3. 验证配置效果
做完上面两步后重启服务,你可以:
- 查看Eureka Server的访问日志,确认请求头里已经带上了
X-B3-TraceId、X-B3-SpanId这些标识; - 刷新Zipkin UI,就能看到从业务服务/网关到Eureka Server的完整链路节点了。
额外注意点
- 确保项目里已经正确引入
spring-cloud-starter-sleuth和spring-cloud-starter-zipkin依赖,版本要和Edgware.SR1匹配(对应Sleuth 1.3.x版本); - 如果是多节点Eureka集群,不需要给Server端做额外配置,只要客户端传递了Trace头,Zipkin就能自动捕获链路。
内容的提问来源于stack exchange,提问作者Matvey
相关产品推荐
相关产品推荐

