响应式SpringBoot项目中Jaeger未生成Elasticsearch请求跨度的问题咨询
问题原因&解决方案
核心原因
- 你引入的
io.opentracing.contrib:opentracing-elasticsearch7-client:0.1.2仅支持同步RestHighLevelClient的埋点,Spring Data Elasticsearch响应式模式底层使用ReactiveElasticsearchClient,该依赖无法自动识别和埋点响应式ES客户端的请求 - 响应式编程模型下未配置tracer的上下文传递规则,链路信息无法从Web请求的span传递到ES请求的执行链路中
- 版本兼容问题:Spring Boot 2.4.2对应的Spring Data Elasticsearch内置的ES客户端版本,高于
opentracing-elasticsearch7-client:0.1.2支持的版本范围,自动配置无法生效
解决方案
方案1:使用Spring Cloud Sleuth自动埋点(推荐)
- 移除现有opentracing ES相关依赖,引入Spring Cloud Sleuth适配依赖,Spring Boot 2.4.x对应Spring Cloud 2020.0.x版本,在gradle中调整配置:
ext { set('springCloudVersion', "2020.0.6") } dependencies { // 原有其他依赖保留 implementation 'org.springframework.cloud:spring-cloud-starter-sleuth' implementation 'org.springframework.cloud:spring-cloud-sleuth-brave' implementation 'io.opentracing.contrib:opentracing-spring-jaeger-web-starter:2.0.3' } dependencyManagement { imports { mavenBom "org.springframework.cloud:spring-cloud-dependencies:${springCloudVersion}" } }
- 无需额外代码配置,Sleuth会自动对
ReactiveElasticsearchClient的请求做埋点,链路信息会自动在reactor上下文中完成传递。
方案2:手动为响应式ES客户端添加埋点
如果不想引入Spring Cloud Sleuth,可以手动自定义ReactiveElasticsearchClient的装饰器,在ES请求执行前后手动创建、结束span:
@Configuration public class EsTracingConfig { @Bean public ReactiveElasticsearchClientCustomizer tracingEsClientCustomizer(Tracer tracer) { return client -> new TracingReactiveElasticsearchClient(client, tracer); } private static class TracingReactiveElasticsearchClient implements ReactiveElasticsearchClient { private final ReactiveElasticsearchClient delegate; private final Tracer tracer; public TracingReactiveElasticsearchClient(ReactiveElasticsearchClient delegate, Tracer tracer) { this.delegate = delegate; this.tracer = tracer; } // 以search方法为例,其他请求方法按照相同逻辑重写即可 @Override public Flux<SearchHit> search(SearchRequest request) { return Mono.deferContextual(contextView -> { Span span = tracer.buildSpan("elasticsearch:search") .withTag("elasticsearch.index", request.indices()[0]) .asChildOf(tracer.activeSpan()) .start(); return delegate.search(request) .doOnError(e -> span.setTag("error", true).log(e.getMessage())) .doFinally(signalType -> span.finish()); }); } } }
配置完成后重启应用发起请求,即可在Jaeger链路中看到嵌套的ES请求span。
内容的提问来源于stack exchange,提问作者Mikhail Geyer
相关产品推荐
相关产品推荐

