代码之家  ›  专栏  ›  技术社区  ›  b0gusb

异步请求的Tomcat-WELD解决方案

  •  0
  • b0gusb  · 技术社区  · 6 年前

    对于异步请求,Tomcat在与触发初始化事件的线程不同的线程中触发requestdestromed事件。 在这种情况下,使用 ThreadLocals ,不会停用请求上下文,因此不会调用bean处理方法。

    请参见: What do WELD-000225, WELD-000335 and WELD-000715 warnings mean?

    Tomcat Bug 57314

    我的应用程序依赖于容器生命周期事件来关闭资源和清理,因此我需要一种方法使异步请求的所有内容都能正常工作。我想出的解决办法是添加一个 WebFilter 使执行链末尾的当前请求上下文无效。

    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
                throws Exception {
    
        BeanManager beanManager = CDI.current().getBeanManager();
        AlterableContext context = (AlterableContext) beanManager.getContext(RequestScoped.class);
        try {
            chain.doFilter(request, response);
        } finally {
            if (request.isAsyncStarted()) {
                AbstractBoundContext<?> ctxt = (AbstractBoundContext<?>) delegate;
                ctxt.invalidate();
                ctxt.deactivate();
                ctxt.cleanup();
            }
        }
    }
    

    Tomcat抱怨说:

    SEVERE: The web application [cdi-weld] created a ThreadLocal with key of type [java.lang.ThreadLocal] (value [java.lang.ThreadLocal@3d97cd8b]) and a value of type [org.jboss.weld.module.web.servlet.HttpContextLifecycle.Counter] (value [org.jboss.weld.module.web.servlet.HttpContextLifecycle$Counter@43a15b16]) but failed to remove it when the web application was stopped. Threads are going to be renewed over time to try and avoid a probable memory leak.
    Nov 02, 2018 10:43:55 AM org.apache.catalina.loader.WebappClassLoaderBase checkThreadLocalMapForLeaks
    SEVERE: The web application [cdi-weld] created a ThreadLocal with key of type [java.lang.ThreadLocal] (value [java.lang.ThreadLocal@21d33dd8]) and a value of type [org.jboss.weld.contexts.AbstractManagedContext.ManagedState] (value [org.jboss.weld.contexts.AbstractManagedContext$ManagedState@2a336421]) but failed to remove it when the web application was stopped. Threads are going to be renewed over time to try and avoid a probable memory leak.
    Nov 02, 2018 10:43:55 AM org.apache.catalina.loader.WebappClassLoaderBase checkThreadLocalMapForLeaks
    SEVERE: The web application [cdi-weld] created a ThreadLocal with key of type [java.lang.ThreadLocal] (value [java.lang.ThreadLocal@294b0f79]) and a value of type [org.jboss.weld.module.web.servlet.ConversationContextActivator$$Lambda$555/1676983761] (value [org.jboss.weld.module.web.servlet.ConversationContextActivator$$Lambda$555/1676983761@60fb88ad]) but failed to remove it when the web application was stopped. Threads are going to be renewed over time to try and avoid a probable memory leak.
    

    我的理解是,每个请求的线程局部变量都会被覆盖,所以这并不完全是内存泄漏,但我仍然对这个解决方案不是100%满意。

    1 回复  |  直到 6 年前
        1
  •  1
  •   Siliarus    6 年前

    org.jboss.weld.module.web.servlet.HttpContextLifecycle.Counter 你可能无法修复,或者至少我不知道如何修复。

    但是另外两个是不同的上下文,您可以通过停用它们来解决这个问题,就像您对请求上下文所做的那样。

    org.jboss.weld.contexts.AbstractManagedContext.ManagedState BeanManager

    org.jboss.weld.module.web.servlet.ConversationContextActivator$$Lambda$555/1676983761 这应该是会话上下文(可能是 LazyHttpConversationContextImpl ). 释放这种背景可以让这一切消失。