java - Spring boot Tomcat场景下如何清除线程上下文?

标签 java spring-boot spring-boot-actuator

我们实现了一个HandlerInterceptor来在preHandle方法中设置MDC线程上下文数据。

然后我们将这些数据用于日志记录和指标目的。

但是,如果我们在 afterCompletion 方法中使用 MDC.clear() 清除 MDC 数据,则此后的指标处理程序会丢失有值(value)的信息。我特别谈论的是 WebMvcTagsProvider,但我认为这适用于所有类型的用例。

既然有线程池,线程最终会被重用,并且包含之前HTTP请求的MDC上下文,这是非常糟糕的!

那么如何在 setup 和 Finalize 方法中“包装”线程的使用呢? 理想情况下,这将是一个通用解决方案。我不想更改现有代码。目标是新传入请求无法访问之前的 MDC 上下文。

我已经知道如何在 Java EE 世界中解决这个问题,例如:

@Provider
@Priority(Priorities.USER + 1)
public class MdcClearFilter implements ContainerResponseFilter {
    @Override
    public void filter(
        ContainerRequestContext requestContext,
        ContainerResponseContext responseContext) {
        MDC.clear();
    }
}

那么我该如何在 Spring Boot 世界中做同样的事情呢?

最佳答案

由于 HandlerInterceptor 都位于 Servlet 上下文中,因此它们无法突破。

因此,解决方案是使用顺序为 Ordered.HIGHEST_PRECEDENCE 的 servlet Filter

@Component
@Order(Ordered.HIGHEST_PRECEDENCE)
public class MDCClearFilter implements Filter {

    @Override
    public void doFilter(ServletRequest request, 
                         ServletResponse response, 
                         FilterChain chain)
            throws IOException, ServletException {

        chain.doFilter(request, response);
        MDC.clear();
    }
}

关于java - Spring boot Tomcat场景下如何清除线程上下文?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58978540/

相关文章:

unit-testing - 使用 spring boot、kotlin 和 junit 进行 Rest Controller 单元测试

java - 如何在opentelemetry中排除url(健康检查痕迹)

java - Kubernetes liveness - 使用 Spring Boot 为特定端点保留线程/内存

java - Spring Boot spring.datasource.CONFIGURATION_PROPERTIES 无法序列化

java - 如何在Java中使用JSpeex

java - 我认为我可能误解了 Map 类方法

java - 依赖更新后gradle构建失败

java - Spring Boot MVC/Rest Controller 和枚举反序列化转换器

java - swagger是否保存任何文件

prometheus - 在普罗米修斯中显示任意@Timed指标