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

Zuul网关通过MDC添加Request ID无法传递至客户端微服务

问题:Zuul网关生成的Request ID无法传递到下游微服务

我在Zuul网关中编写了如下Pre Filter:

@Override
public Object run() throws ZuulException
{
    String uniqueID = UUID.randomUUID().toString();
    MDC.put("request_id", uniqueID);
    RequestContext requestContext = RequestContext.getCurrentContext();
    HttpServletRequest request = requestContext.getRequest();
    request.setAttribute("request_id", uniqueID);

    //requestContext.set("request_id", uniqueID);
    logger.info("request-id generated is => {}", uniqueID);
    logger.info("Pre Filter => "+ String.format("%s request to %s", request.getMethod(), request.getRequestURL().toString()));
//        MDC.clear();
    return null;
}

Zuul网关日志已成功显示Request ID:

2022-08-22 01:57:00.283+0200 [http-nio-8080-exec-6] INFO  [] c.h.z.ZuulGatewayApplication$MyFilter - BEFORE
2022-08-22 01:57:00.284+0200 [http-nio-8080-exec-6] INFO  [f40d9b07-c33f-4996-bb3a-b16df3ba6436] c.h.z.filter.MDCLoggingPreFilter - request-id generated is => f90447a5-974d-4c38-beba-377addce446c
2022-08-22 01:57:00.284+0200 [http-nio-8080-exec-6] INFO  [f40d9b07-c33f-4996-bb3a-b16df3ba6436] c.h.z.filter.MDCLoggingPreFilter - Pre Filter => GET request to http://localhost:8080/home
2022-08-22 01:57:00.285+0200 [http-nio-8080-exec-6] INFO  [f40d9b07-c33f-4996-bb3a-b16df3ba6436] c.h.z.f.MDCLoggingPreFilter2 - Pre Filter 2 => GET request to http://localhost:8080/home
2022-08-22 01:57:00.297+0200 [http-nio-8080-exec-6] INFO  [f40d9b07-c33f-4996-bb3a-b16df3ba6436] c.h.z.f.MDCLoggingPostFilter - Post Filter => GET request to http://localhost:8080/home
2022-08-22 01:57:00.298+0200 [http-nio-8080-exec-6] INFO  [f40d9b07-c33f-4996-bb3a-b16df3ba6436] c.h.z.f.MDCLoggingPostFilter2 - Post Filter 2=> GET request to http://localhost:8080/home
2022-08-22 01:57:00.299+0200 [http-nio-8080-exec-6] INFO  [f40d9b07-c33f-4996-bb3a-b16df3ba6436] c.h.z.ZuulGatewayApplication$MyFilter - AFTER

但请求转发到下游微服务后,日志里没有Request ID:

2022-08-22 01:57:00.287+0200 [http-nio-8081-exec-3] INFO  [] c.h.z.controller.HomeController - simple get method

解决方案

问题核心是:当前代码仅把Request ID存在网关本地的HttpServletRequest属性和MDC中,Zuul转发请求时不会自动传递这些本地属性。需要将Request ID放入请求头传递到下游,再由下游服务从请求头取出并配置到MDC中。

步骤1:修改Zuul Pre Filter,添加请求头传递逻辑

更新网关的Pre Filter,用Zuul提供的addZuulRequestHeader方法把Request ID写入请求头,确保转发时携带:

@Override
public Object run() throws ZuulException
{
    String uniqueID = UUID.randomUUID().toString();
    // 网关本地MDC配置,用于网关自身日志
    MDC.put("request_id", uniqueID);
    RequestContext requestContext = RequestContext.getCurrentContext();
    
    // 关键:将Request ID加入请求头,传递给下游服务
    requestContext.addZuulRequestHeader("X-Request-ID", uniqueID);
    
    HttpServletRequest request = requestContext.getRequest();
    request.setAttribute("request_id", uniqueID);

    logger.info("request-id generated is => {}", uniqueID);
    logger.info("Pre Filter => "+ String.format("%s request to %s", request.getMethod(), request.getRequestURL().toString()));
    return null;
}

步骤2:下游微服务配置Request ID拦截器

在下游微服务中添加拦截器,从请求头获取X-Request-ID并放入MDC,同时在请求结束后清理MDC避免内存泄漏。

拦截器实现代码

@Component
public class RequestIdInterceptor implements HandlerInterceptor {

    private static final String REQUEST_ID_HEADER = "X-Request-ID";
    private static final String MDC_REQUEST_ID_KEY = "request_id";

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        String requestId = request.getHeader(REQUEST_ID_HEADER);
        if (requestId != null) {
            MDC.put(MDC_REQUEST_ID_KEY, requestId);
        }
        return true;
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        // 请求结束后移除MDC中的Request ID
        MDC.remove(MDC_REQUEST_ID_KEY);
    }
}

注册拦截器

@Configuration
public class WebConfig implements WebMvcConfigurer {

    @Autowired
    private RequestIdInterceptor requestIdInterceptor;

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        // 对所有请求生效
        registry.addInterceptor(requestIdInterceptor).addPathPatterns("/**");
    }
}

步骤3:配置下游微服务日志格式

确保下游微服务的日志配置(如logback.xml)中包含%X{request_id}占位符,示例:

<appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
    <encoder>
        <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level [%X{request_id}] %logger{36} - %msg%n</pattern>
    </encoder>
</appender>

完成以上配置后,下游微服务的日志即可显示从Zuul传递过来的Request ID。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.21 11:03:15