Spring 跨线程发送TraceId

Spring 跨线程发送TraceId,spring,spring-cloud,zipkin,spring-cloud-sleuth,Spring,Spring Cloud,Zipkin,Spring Cloud Sleuth,我们有一个遵循微服务体系结构的分布式应用程序。在我们的一项微服务中,我们遵循生产者-消费者模式 生产者接收请求,将其持久化到数据库,将请求推送到BlockingQueue并将响应发送回客户端。在单独线程上运行的使用者正在侦听阻塞队列。当它获得请求对象时,它就对其执行特定的操作 生产者收到的请求使用CompleteableFutures异步持久化到数据库 这里的问题是如何将TraceId转发给在使用者线程内处理requestObject的方法。因为使用者线程可能会在响应发送给使用者之后很久处理这些

我们有一个遵循微服务体系结构的分布式应用程序。在我们的一项微服务中,我们遵循生产者-消费者模式

生产者接收请求,将其持久化到数据库,将请求推送到BlockingQueue并将响应发送回客户端。在单独线程上运行的使用者正在侦听阻塞队列。当它获得请求对象时,它就对其执行特定的操作

生产者收到的请求使用CompleteableFutures异步持久化到数据库

这里的问题是如何将TraceId转发给在使用者线程内处理requestObject的方法。因为使用者线程可能会在响应发送给使用者之后很久处理这些对象

另外,如何跨异步调用转发traceId


谢谢这是一个有趣的问题。我认为您可以做的是将请求与其头一起持久化。然后,在用户端,您可以使用与我们在这里使用的方式类似的
SpanExtractor
接口-(
Span parent=SpanExtractor().joinTrace(新的HttpServletRequestTextMap(request));
)。这意味着我们从
HttpServletRequest
中提取值来构建一个范围。然后,一旦检索到
Span
,就可以在处理之前使用
Tracer#continueSpan(Span)
方法,然后在finally块中使用
Tracer#detach(Span)
。例如

Span parent = spanExtractor().joinTrace(new HttpServletRequestTextMap(request));
try {
   tracer.continueSpan(parent);
   // do whatever you need
} catch(Exception e) {
  tracer.addTag("error", doSthWithTheExceptionMsg(e));
} finally {
  tracer.detach(parent); 
}

我们也将尝试这样做,但我们现在正在做的是,持久化traceId,然后在使用者线程中调用:-
Span parent=Span.builder().traceId(Span.hexToId(traceId)).build();tracer.createSpan(“ConsumerSpan”,父级)您看到这种方法有什么缺点吗?此外,由于消费者内部的所有调用都是异步的,消费者再次产生多个线程,什么是正确的方法来处理这个问题?我认为它看起来还可以。您是否观察到任何问题?您好,通过将traceableExecutorPool传递给CompletableFuture.supplyAsync解决了此问题。因为restTemplate是在一个新线程中执行的,该线程没有与之关联的traceId。每次调用restTemplate.exchange都会生成一个新的TraceId<代码>CompletableFuture.SupplySync(()->restTemplate.exchange(requestEntity,String.class),traceableExecutorService)
有些人可能会发现这很有用:)这个例子可以在文档afair中找到。通过可追踪的ES包装可调用的。不管怎么说,我很高兴事情对你有好处!我们能把这个标记为已回答吗?