简体   繁体   English

在多线程 Java 服务器中使用跟踪

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM