在春季的HTTP请求之后,我们是否需要清除MDC

2022-09-02 01:46:15

根据这个答案线程局部变量,当我们使用线程局部时,我们应该清除线程池环境中的所有变量。

所以基本上我只想确认,当我们使用MDC(映射的诊断上下文)时,我们也应该清除MDC以感知内存泄漏,这是真的吗?

例如:

@Configuration
public class WebConfig implements WebMvcConfigurer {
    public class HttpInterceptor implements HandlerInterceptor {
        @Override
        public boolean preHandle(final HttpServletRequest request,
                                 final HttpServletResponse response,
                                 final Object handler) {
            MDC.put(SESSION_ID, session_id);
        {

        @Override
        public void postHandle(final HttpServletRequest request,
                               final HttpServletResponse response,
                               final Object handler,
                               final ModelAndView modelAndView) {
           MDC.clear(); //WE SHOULD CLEAR MDC.... if not memory leaks ?
        }
    }

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(new MdcHandlerInterceptor());
    }
}

答案 1

不是为了内存泄漏,而是为了防止在请求之间保留信息。您不希望您的第一个请求放置,而您的第二个请求放置 ,最终以 而不是只是 .foobarfoobarbar

当然,如果您总是只填写相同的确切值(如远程IP等),这不会发生,但安全总比抱歉好。您不想记录不良信息。

注意:您在一个请求中输入的信息并不总是传播到下一个请求,因为它们可以在其他线程上执行,即使对于同一端点也是如此。这就是为什么这个问题可能会被忽视,因为它不能可靠地再现,特别是在你覆盖了大部分值的情况下。


答案 2

您可以编写如下所示的测试代码。

    public static void request(ThrowingRunnable runnable, String para)  {
            CompletableFuture.runAsync(() -> {
                MDC.put("var"+ para, "value"+ para);
                try {
                    runnable.runThrows();
                } catch (Exception e) {
                    log.warn(e.getMessage(), e);
                }finally {
                    // get MDC variables
                    String st = MDC.getCopyOfContextMap().entrySet().stream().map(e -> e.getKey() + "=" + e.getValue()).reduce((a, b) -> a + "," + b).orElse("");
                    log.info(st);
                }
            });
    }

    public static void main(String[] args) throws InterruptedException {
        for (int i = 0; i < 100; i++) {
            request(() -> {
            }, i + "");
        }
        Thread.sleep(10000);
    }

推荐