一直没弄明白sleuth的tracerContext是如何创建和传递的,闲来无事研究了一下。由于对sleuth的源码不熟悉,准备通过debug brave.Tracer的nextId()方法,查看方法调用栈来找来龙去脉。
首先创建两个service A和B,记作srvA、srvB,在srvA中添加testA controller,sevB中添加testB controller,testA中通过Feign调用testB。

先看当用户通过浏览器调用srvA的时候,srvA是作为server的。
configuration:
TraceWebServletAutoConfiguration==>TracingFilter
TraceHttpAutoConfiguration==>HttpTracing
TraceAutoConfiguration==>Tracing
SleuthLogAutoConfiguration.Slf4jConfiguration==>CurrentTraceContext

配置中,TracingFilter在实例化时需要一个HttpTracing:
public static Filter create(HttpTracing httpTracing) {
return new TracingFilter(httpTracing);
}
//Servlet运行时类
final ServletRuntime servlet = ServletRuntime.get();
//Slf4jCurrentTraceContext
final CurrentTraceContext currentTraceContext;
final Tracer tracer;
final HttpServerHandler<HttpServletRequest, HttpServletResponse> handler;
//TraceContext的数据提取器
final TraceContext.Extractor<HttpServletRequest> extractor;
TracingFilter(HttpTracing httpTracing) {
tracer = httpTracing.tracing().tracer();
currentTraceContext = httpTracing.tracing().currentTraceContext();
handler = HttpServerHandler.create(httpTracing, ADAPTER);
extractor = httpTracing.tracing().propagation().extractor(GETTER);
}
HttpTracing Builder模式构造时接收一个Tracing:
Tracing tracing;
//客户端span解析器
HttpClientParser clientParser;
String serverName;
//服务端span解析器
HttpServerParser serverParser;
HttpSampler clientSampler, serverSampler;
Builder(Tracing tracing) {
if (tracing == null) throw new NullPointerException("tracing == null");
final ErrorParser errorParser = tracing.errorParser();
this.tracing = tracing;
this.serverName = "";
// override to re-use any custom error parser from the tracing component
this.clientParser = new HttpClientParser() {
@Override protected ErrorParser errorParser() {
return errorParser;
}
};
this.serverParser = new HttpServerParser() {
@Override protected ErrorParser errorParser() {
return errorParser;
}
};
this.clientSampler = HttpSampler.TRACE_ID;
this.serverSampler(HttpSampler.TRACE_ID);
}
Tracing实例化:
@Bean
@ConditionalOnMissingBean
// NOTE: stable bean name as might be used outside sleuth
Tracing tracing(@Value("${spring.zipkin.service.name:${spring.application.name:default}}") String serviceName,
Propagation.Factory factory,
CurrentTraceContext currentTraceContext,
Reporter<zipkin2.Span> reporter,
Sampler sampler,
ErrorParser errorParser,
SleuthProperties sleuthProperties
) {
return Tracing.newBuilder()
.sampler(sampler)
.errorParser(errorParser)
.localServiceName(serviceName)
//ExtraFieldPropagation.Factory
.propagationFactory(factory)
.currentTraceContext(currentTraceContext)
.spanReporter(adjustedReporter(reporter))
.traceId128Bit(sleuthProperties.isTraceId128())
.supportsJoin(sleuthProperties.isSupportsJoin())
.build();
}










