在应用系统中通常我们需要把请求的链路连接起来,那么需要把该请求系统上下文传递到下一个系统中,依次类推主线程的上下文也需要把内容传递到子线程中,这些在Sleuth都有所实现,但是在RocketMQ中等MQ也就没有该实现,那么怎么样通过上层TraceId设置到当前系统中呢。
import brave.propagation.Propagation.RemoteGetter;
public class DemoRemoteGetter implements RemoteGetter<Map<String,String>> {
@Override
public Kind spanKind() {
return Span.Kind.SERVER;
}
@Override
public String get(Map<String, String> request, String fieldName) {
return request.get(fieldName);
}
}
import brave.propagation.TraceContext.Extractor;
import brave.propagation.TraceContextOrSamplingFlags;
import brave.propagation.CurrentTraceContext.Scope;
import org.springframework.cloud.sleuth.SpanNamer;
// Tracing tracing 该对象注入进来
Extractor<Map<String,String>> extractor = tracing.propagation().extractor(new DemoRemoteGetter());
Map<String,String> map = new HashMap<>();
// 该地方模拟拿到请求的过来的对应参数-traceId
map.put("X-B3-TraceId","a50bc6028f408387");
map.put("X-B3-SpanId","a50bc6028f408387");
map.put("X-B3-ParentSpanId","a50bc6028f408387");
map.put("X-B3-Sampled","0");
TraceContextOrSamplingFlags contextOrSamplingFlags = extractor.extract(map);
Span span = tracing.tracer().nextSpan(contextOrSamplingFlags);
Scope scope = tracing.currentTraceContext().newScope(span.context());
log.info("重新定义了日志这个时候是多少");
// 如果该上下文中已经存在了该设置无效
scope.close();
注意TraceId 不可用随便定义需要通过系统规则定义,因为设置之后系统会转换为数字Long,如果不合规则那么就会重新重新生成则无效。
可以通过一下生成一个:
Span span = Tracing.newBuilder().build().tracer().newTrace();
String traceId = span.context().traceIdString();
系统内置的方式
异步的情况可以通过
org.springframework.cloud.sleuth.instrument.async.TraceCallable 需要有返回值org.springframework.cloud.sleuth.instrument.async.TraceRunnable 没有返回值来实现
平常我们通过Feign调用的时候是通过
该类负责组装请求参数
org.springframework.cloud.sleuth.instrument.web.client.feign.TracingFeignClient
该类负责解读请求参数
org.springframework.cloud.sleuth.instrument.web.LazyTracingFilter
最终会把结果转移到 brave.servlet.TracingFilter 来处理