You need to enable JavaScript to run this app. Spring Cloud Sleuth如何添加拼接span-id的自定义传播字段Request-Id
优惠活动
大模型
产品
解决方案
定价
更多

Spring Cloud Sleuth如何添加拼接span-id的自定义传播字段Request-Id

自定义Request-Id传播字段实现方案

这个需求本质是对分布式链路追踪的传播上下文做自定义扩展,核心需要在传播协议、入口拦截、出口透传三个核心环节做统一改造即可实现:


前置前提

  • 你当前使用的链路追踪组件(OpenTelemetry、SkyWalking、Jaeger等原生或二次封装版本)已经开放自定义上下文传播的扩展能力
  • 所有接入服务统一使用同一套传播协议:HTTP头、gRPC Metadata、MQ消息头等场景下使用相同的字段名约定,避免大小写、拼写差异导致的透传失败

核心实现步骤

1. 统一传播字段定义

先全局约定字段名:HTTP场景推荐使用X-Request-Id,RPC、MQ等场景对应元数据字段名用request_id,降低跨协议适配成本。

2. 入站流量拦截逻辑

在所有服务的流量入口层(网关过滤器、Web拦截器、RPC服务端拦截器)做统一处理:

  • 若入站请求没有携带request_id:判定为链路起点,直接取当前span的span-id作为本服务的request_id值
  • 若入站请求已经携带request_id:取上游透传的request_id + . + 当前span的span-id,拼接后作为本服务的request_id值
    注意:拼接前需要对上游传入的request_id做合法性校验,过滤特殊字符、限制最大长度,避免恶意构造的字段值导致服务异常

3. 出站流量透传逻辑

在所有服务的流量出口层(HTTP客户端拦截器、RPC客户端拦截器、MQ生产者拦截器),把本服务计算完成的request_id值注入到出站请求的元数据中,传递给下游服务。

4. 本地上下文存储

把计算好的request_id存入线程本地存储(ThreadLocal、协程上下文等),方便业务日志打印、问题排查时直接取用。


代码示例(Spring Boot + OpenTelemetry场景)

// 入站请求过滤器
@Component
public class RequestIdFilter implements Filter {
    private static final String REQUEST_ID_HEADER = "X-Request-Id";

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
        HttpServletRequest httpRequest = (HttpServletRequest) request;
        // 读取上游传递的Request-Id
        String upstreamRequestId = httpRequest.getHeader(REQUEST_ID_HEADER);
        // 获取当前Span的SpanId
        String currentSpanId = Span.current().getSpanContext().getSpanId();
        // 拼接生成本地Request-Id
        String localRequestId = upstreamRequestId == null ? currentSpanId : upstreamRequestId + "." + currentSpanId;
        // 存入线程上下文供业务使用
        RequestContextHolder.set("request_id", localRequestId);
        chain.doFilter(request, response);
    }
}

// 出站请求拦截器
@Component
public class RestTemplateInterceptor implements ClientHttpRequestInterceptor {
    private static final String REQUEST_ID_HEADER = "X-Request-Id";

    @Override
    public ClientHttpResponse intercept(HttpRequest request, byte[] body, ClientHttpRequestExecution execution) throws IOException {
        // 从上下文取出Request-Id注入到出站请求头
        String localRequestId = RequestContextHolder.get("request_id");
        if (localRequestId != null) {
            request.getHeaders().add(REQUEST_ID_HEADER, localRequestId);
        }
        return execution.execute(request, body);
    }
}

边界场景兼容

  • 异步调用场景:需要把request_id透传到异步线程/协程上下文中,避免上下文丢失
  • 链路中断场景:如果存在未接入统一规范的中间服务,链路续接时如果没有拿到上游的request_id,直接从当前span重新生成即可
  • 性能影响:拼接逻辑非常轻量,基本不会带来额外性能开销,无需做额外优化

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.14 04:48:02