You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

SpringBoot3+Micrometer Tracing并行GRPC调用时Tracer.currentSpan()随机为空

问题

服务端处理并行GRPC调用时,io.micrometer.tracing.Tracer.currentSpan()的值会随机变为null,串行调用则不会出现该问题。服务端堆栈跟踪信息如下:

java.lang.NullPointerException: Cannot invoke "io.micrometer.tracing.Span.context()" because the return value of "io.micrometer.tracing.Tracer.currentSpan()" is null
    at com.example.micrometer.GrpcServerApplication$EchoService.unaryRpc(GrpcServerApplication.java:85) ~[main/:na]
    at io.grpc.testing.protobuf.SimpleServiceGrpc$MethodHandlers.invoke(SimpleServiceGrpc.java:410) ~[grpc-testing-proto-1.54.1.jar:1.54.1]
    at io.grpc.stub.ServerCalls$UnaryServerCallHandler$UnaryServerCallListener.onHalfClose(ServerCalls.java:182) ~[grpc-stub-1.54.1.jar:1.54.1]
    at io.grpc.PartialForwardingServerCallListener.onHalfClose(PartialForwardingServerCallListener.java:35) ~[grpc-api-1.54.1.jar:1.54.1]
    at io.grpc.ForwardingServerCallListener.onHalfClose(ForwardingServerCallListener.java:23) ~[grpc-api-1.54.1.jar:1.54.1]
    at io.grpc.ForwardingServerCallListener$SimpleForwardingServerCallListener.onHalfClose(ForwardingServerCallListener.java:40) ~[grpc-api-1.54.1.jar:1.54.1]
    at io.micrometer.core.instrument.binder.grpc.ObservationGrpcServerCallListener.onHalfClose(ObservationGrpcServerCallListener.java:47) ~[micrometer-core-1.10.6.jar:1.10.6]
    at io.grpc.internal.ServerCallImpl$ServerStreamListenerImpl.halfClosed(ServerCallImpl.java:355) ~[grpc-core-1.54.1.jar:1.54.1]
    at io.grpc.internal.ServerImpl$JumpToApplicationThreadServerStreamListener$1HalfClosed.runInContext(ServerImpl.java:867) ~[grpc-core-1.54.1.jar:1.54.1]
    at io.grpc.internal.ContextRunnable.run(ContextRunnable.java:37) ~[grpc-core-1.54.1.jar:1.54.1]
    at io.grpc.internal.SerializingExecutor.run(SerializingExecutor.java:133) ~[grpc-core-1.54.1.jar:1.54.1]
    at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1136) ~[na:na]
    at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:635) ~[na:na]
    at java.base/java.lang.Thread.run(Thread.java:833) ~[na:na]

已提供可复现问题的最小示例服务端和客户端,请问可能遗漏了什么配置或处理逻辑?

可能的原因与解决方案

  • GRPC上下文与Tracing上下文未正确绑定
    GRPC使用自身的Context机制传递上下文,而Micrometer Tracing的Tracer依赖线程本地存储或GRPC上下文获取Span。并行调用时,若Tracing上下文未正确注入GRPC调用上下文,线程切换后会丢失Span。
    解决:确保正确初始化Micrometer GRPC绑定器,将ObservationGrpcServerInterceptor(或对应Tracing拦截器)添加到GRPC服务器的服务拦截器列表中,让拦截器负责将Tracing上下文绑定到GRPC请求上下文中。

  • 异步处理未传递Tracing上下文
    若服务端处理逻辑使用异步线程池但未手动传递Tracing上下文,并行调用时线程切换会导致currentSpan()返回null。
    解决:使用Tracer包装异步任务,比如调用tracer.withSpan(span).wrap(runnable);或使用支持上下文传递的线程池(如Spring的TaskExecutor配合Tracing装饰器),确保Span上下文在异步线程中可被获取。

  • GRPC SerializingExecutor上下文传递问题
    从堆栈可见请求在SerializingExecutor中执行,并行调用时若上下文未正确传递,仍会出现Span丢失。需确保Micrometer的GRPC绑定器正确处理该执行器的上下文传递。
    解决:检查依赖是否齐全,确认引入micrometer-core和micrometer-tracing-binder-grpc(若用Spring Cloud Sleuth需保证版本兼容),并在配置类中正确注册GRPC的Tracing拦截器。

  • Span被提前结束
    业务代码中若存在手动调用span.end()的逻辑,会导致后续代码中currentSpan()返回null,并行调用时该问题更易触发。
    解决:检查代码中是否有手动结束Span的操作,确保Span在整个请求处理周期结束后才被结束;或使用Micrometer的Observation API自动管理Span生命周期,避免手动操作引发的问题。

内容的提问来源于stack exchange,提问作者daltonfury42

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.23 12:27:47