[英]Using tracing in a multithreaded Java server
I am having trouble with using tracing in my multithreaded application.我在多线程应用程序中使用跟踪时遇到问题。
background:背景:
In my SpringBoot application I have a function "service" which calls another function "innerService", and I want to trace each function with its own span.在我的 SpringBoot 应用程序中,我有一个 function“服务”调用另一个 function“innerService”,我想用自己的跨度跟踪每个 function。 I am implementing OpenTracing with Jaeger in the following way:
我通过以下方式使用 Jaeger 实现 OpenTracing:
AppConfig.java: AppConfig.java:
@Bean
public static JaegerTracer getTracer() {
io.jaegertracing.Configuration.SamplerConfiguration samplerConfig = io.jaegertracing.Configuration.SamplerConfiguration.fromEnv().withType("const").withParam(1);
io.jaegertracing.Configuration.ReporterConfiguration reporterConfig = io.jaegertracing.Configuration.ReporterConfiguration.fromEnv().withLogSpans(true);
io.jaegertracing.Configuration config = new io.jaegertracing.Configuration("myService").withSampler(samplerConfig).withReporter(reporterConfig);
return config.getTracer();
}
I then use it in one of my apps' services:然后我在我的一个应用程序服务中使用它:
@GrpcService
public class ServiceA extends ServiceAGrpc.ServiceAImplBase {
private final Tracer tracer;
@Autowired
public ServiceA(Tracer tracer) {
this.tracer = tracer;
}
@Override
public void service(Request request, StreamObserver<ResultGrpc> responseObserver) {
Span span = startSpanInScope(this.tracer, "service");
...
innerService();
...
span.finish();
}
the function that returns a span:返回跨度的 function:
public static Span startSpanInScope(Tracer tracer, String spanName) {
if (tracer == null) {
return null;
}
Span span = tracer.buildSpan(spanName).start();
Scope scope = tracer.scopeManager().activate(span);
return span;
}
When sending a single request to the service, everything seems fine and the spans appear one inside the other:当向服务发送单个请求时,一切似乎都很好,跨度出现在另一个之中:
However, when I send multiple requests at once, using multiple threads, the spans interfere one another:但是,当我使用多个线程一次发送多个请求时,跨度会相互干扰:
I guess it happens because whenever a span starts it becomes the child of the currently active span, even if this span is from another thread.我猜这是因为每当一个跨度开始时,它就会成为当前活动跨度的子级,即使这个跨度来自另一个线程。 I don't understand why, since I read that the ScopeManager is by default a ThreadLocal object.
我不明白为什么,因为我读到 ScopeManager 默认是 ThreadLocal object。
Can anyone suggest a solution to this?任何人都可以提出解决方案吗? I want a separate trace for each thread, which will show the spans for "service" and "innerService" as its child.
我希望每个线程都有一个单独的跟踪,这将显示“服务”和“innerService”作为其子项的跨度。
You have to close your scope too ( scope.close()
) and not only the span which might be the reason why your trace continuous.你也必须关闭你的 scope (
scope.close()
) 而不仅仅是跨度,这可能是你的跟踪连续的原因。 Closing the scope automatically finishes the span.关闭 scope 会自动完成跨度。 Furthermore, you can directly create a span as an active one in a single command:
Scope scope = tracer.buildSpan(spanName).startActive(true)
.此外,您可以在单个命令中直接创建一个跨度作为活动跨度:
Scope scope = tracer.buildSpan(spanName).startActive(true)
。 This way, you don't have to manually call the scopeManager
.这样,您就不必手动调用
scopeManager
。
Due to the fact that the Scope
class implements the AutoClosable
interface, you can use try-resource blocks in order to prevent missing a scope from closing:由于
Scope
class 实现了AutoClosable
接口,您可以使用 try-resource 块来防止丢失 scope 关闭:
try (Scope scope = this.tracer.buildSpan("service").startActive(true)) {
innerService();
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.