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

Spring Boot3升级:从Sleuth迁移至Micrometer时替换WebFluxSleuthOperators

问题描述

我们正在将Spring Boot从2.x版本升级至3.x版本,但Spring Cloud Sleuth无法兼容Spring Boot 3。代码中多次使用WebFluxSleuthOperators类,迁移到Micrometer Tracing后找不到直接替代方案,现有迁移指南对该场景帮助有限。以下是相关代码:

import org.springframework.beans.factory.annotation.Autowired
import org.springframework.cloud.sleuth.CurrentTraceContext
import org.springframework.cloud.sleuth.Tracer
import org.springframework.cloud.sleuth.instrument.web.WebFluxSleuthOperators
import org.springframework.core.Ordered
import org.springframework.stereotype.Component
import org.springframework.web.server.ServerWebExchange
import org.springframework.web.server.WebFilter
import org.springframework.web.server.WebFilterChain
import reactor.core.publisher.Mono

@Component
open class SleuthBaggageToResponseHeadersFilter(
    @Autowired private val tracer: Tracer,
    @Autowired private val currentTraceContext: CurrentTraceContext,
) : WebFilter, Ordered {

    override fun filter(exchange: ServerWebExchange, chain: WebFilterChain): Mono<Void> {
        exchange.response.beforeCommit {
            Mono.deferContextual { Mono.just(it) }.doOnNext { addToResponseHeaders(exchange) }.then()
        }

        return chain.filter(exchange)
    }

    private fun addToResponseHeaders(exchange: ServerWebExchange) =
        WebFluxSleuthOperators.withSpanInScope(tracer, currentTraceContext, exchange) {
            val requestId = tracer.getBaggage("REQUEST_ID")?.get() ?: "NOT_FOUND"
            exchange.response.headers.remove("REQUEST_ID")
            exchange.response.headers.add("REQUEST_ID", requestId)
        }

    override fun getOrder() = SleuthBaggageDefaultValuesFilter.ORDER + 1
}
替代方案

针对该场景,可通过以下方式完成Micrometer Tracing的适配:

1. 依赖调整

移除Spring Cloud Sleuth相关依赖,引入Micrometer Tracing的WebFlux适配依赖。例如使用Brave作为实现时,需引入:

  • micrometer-tracing-bridge-brave
  • brave-instrumentation-spring-webflux

2. 代码改造

Micrometer Tracing的Tracer与CurrentTraceContextAPI和Sleuth兼容度较高,无需借助专门的WebFlux工具类即可实现原有逻辑,改造后的代码如下:

import org.springframework.beans.factory.annotation.Autowired
import org.springframework.core.Ordered
import org.springframework.stereotype.Component
import org.springframework.web.server.ServerWebExchange
import org.springframework.web.server.WebFilter
import org.springframework.web.server.WebFilterChain
import reactor.core.publisher.Mono
import io.micrometer.tracing.Tracer
import io.micrometer.tracing.CurrentTraceContext

@Component
open class SleuthBaggageToResponseHeadersFilter(
    @Autowired private val tracer: Tracer,
    @Autowired private val currentTraceContext: CurrentTraceContext,
) : WebFilter, Ordered {

    override fun filter(exchange: ServerWebExchange, chain: WebFilterChain): Mono<Void> {
        exchange.response.beforeCommit {
            Mono.deferContextual {
                Mono.fromRunnable { addToResponseHeaders(exchange) }
            }.then()
        }

        return chain.filter(exchange)
    }

    private fun addToResponseHeaders(exchange: ServerWebExchange) {
        // 直接从当前Span获取Baggage
        val requestId = tracer.currentSpan()?.getBaggage("REQUEST_ID") ?: "NOT_FOUND"
        exchange.response.headers.remove("REQUEST_ID")
        exchange.response.headers.add("REQUEST_ID", requestId)
    }

    // 原SleuthBaggageDefaultValuesFilter.ORDER值为100,此处沿用原逻辑设为101
    override fun getOrder() = 101
}

3. 关键逻辑说明

  • Span与Baggage获取:Micrometer Tracing中tracer.currentSpan()可直接获取当前上下文绑定的Span,无需WebFluxSleuthOperators做线程绑定。
  • Scope手动管理:若需在非Reactor线程中操作Span,可使用currentTraceContext.wrap(Runnable)或currentTraceContext.maybeScope(span)实现,等价于原withSpanInScope的作用。
  • 过滤器顺序:原SleuthBaggageDefaultValuesFilter.ORDER常量在Micrometer中不存在,直接使用原数值+1(100+1=101)即可保持原有执行顺序。

内容的提问来源于stack exchange,提问作者Clarence the Bard

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.05 20:57:12