【问题标题】:Using tracing in a multithreaded Java server在多线程 Java 服务器中使用跟踪
【发布时间】:2021-08-23 11:16:36
【问题描述】:

我在多线程应用程序中使用跟踪时遇到问题。

背景:

在我的 SpringBoot 应用程序中,我有一个函数“service”,它调用另一个函数“innerService”,我想用自己的 span 跟踪每个函数。 我正在通过以下方式使用 Jaeger 实现 OpenTracing:

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();
}

然后我在我的一个应用服务中使用它:

@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();
}

返回范围的函数:

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;
}

向服务发送单个请求时,一切似乎都很好,跨度出现在另一个中:

但是,当我使用多个线程一次发送多个请求时,跨度会相互干扰:

我猜这是因为每当一个跨度启动时,它就会成为当前活动跨度的子级,即使这个跨度来自另一个线程。我不明白为什么,因为我读到 ScopeManager 默认是一个 ThreadLocal 对象。

任何人都可以提出解决方案吗?我希望每个线程都有一个单独的跟踪,它将显示“服务”和“内部服务”的跨度作为其子项。

【问题讨论】:

  • 您应该使用try { ... } finally { } 确保启动的范围随后关闭。

标签: java multithreading spring-boot jaeger opentracing


【解决方案1】:

您也必须关闭您的范围 (scope.close()),而不仅仅是跨度,这可能是您的跟踪连续的原因。关闭范围会自动完成跨度。此外,您可以在单个命令中直接将跨度创建为活动跨度:Scope scope = tracer.buildSpan(spanName).startActive(true)。这样,您就不必手动调用scopeManager

由于Scope 类实现了AutoClosable 接口,您可以使用try-resource 块来防止错过关闭范围:

try (Scope scope = this.tracer.buildSpan("service").startActive(true)) {
    innerService();
}

【讨论】:

  • 谢谢。我看到 startActive 方法在最新的 JaegerTracer 中已被弃用。是实现此行为的另一种方法吗?
猜你喜欢
  • 1970-01-01
  • 2019-05-27
  • 2015-02-10
  • 1970-01-01
  • 2011-10-10
  • 2023-03-23
  • 2016-02-19
  • 1970-01-01
相关资源
最近更新 更多