【问题标题】:Do we need clear MDC after HTTP request in SpringSpring中的HTTP请求后我们是否需要清除MDC
【发布时间】:2017-07-13 20:51:27
【问题描述】:

根据这个答案thread local variable,当我们使用线程本地时,我们应该清除线程​​池环境中的所有变量。

所以基本上我只想确认,当我们使用 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());
    }
}

【问题讨论】:

  • 我猜危险与其说是内存泄漏,不如说是一个请求无意中“继承”了前一个请求的 MDC 值。

标签: java spring logging log4j logback


【解决方案1】:

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

    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);
    }

【讨论】:

    【解决方案2】:

    MDC 是基于线程的,因此不可能在线程之间共享信息...只有在同一线程中有人再次使用 MDC-Values 时才会产生影响... 而当线程结束时,MDC的ThreadLocalMap就会消失……我猜……

    【讨论】:

    • 你不需要回答已经有答案的古老问题,尤其不应该用猜测来回答。如果您觉得我的回答有遗漏,请告诉我,我会详细说明。
    • 危险在于请求由线程池处理,其中线程被重用并保留其先前的值。所以最好明确清除 MDC,这样处理请求的线程才能被重用。
    【解决方案3】:

    不是为了内存泄漏,而是为了防止在请求之间保留信息。您不希望您的第一个请求输入foo,而您的第二个请求输入bar,最终以foo bar 而不仅仅是bar

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

    注意:您放入一个请求的信息并不总是传播到下一个请求,因为它们可以在其他线程上执行,即使对于同一个端点。这就是为什么该问题可能会被忽略的原因,因为它不能可靠地重现,尤其是在您覆盖大部分值的情况下。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2013-01-02
      • 2011-08-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-12-13
      相关资源
      最近更新 更多