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
相关产品推荐
相关产品推荐

