Tomcat - 针对异步请求的WELD解决方法

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Tomcat - 针对异步请求的WELD解决方法相关的知识,希望对你有一定的参考价值。

我在Tomcat 9上运行了WELD 3.0.5和RestEasy 3.6.1的REST应用程序。

对于异步请求,Tomcat在与触发初始化事件的线程不同的线程中触发请求销毁事件。在这种情况下,使用ThreadLocals的WELD不会停用请求上下文,因此不会调用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();
        }
    }
}

这样做可以很好地丢弃bean并删除一些线程局部变量。不幸的是,一些变量仍然与池化线程相关联,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.

我的理解是ThreadLocals被覆盖了每个请求,所以这不是内存泄漏,但我仍然不满意这个解决方案。

有谁知道解决这个问题的更好方法?

答案

以下信息不是我尝试过的解决方案,但它是我最好的解决方法,你可以如何补救其中的一些。

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)。释放这种背景可能会使这种情况消失。

以上是关于Tomcat - 针对异步请求的WELD解决方法的主要内容,如果未能解决你的问题,请参考以下文章

解决springboot项目请求出现非法字符问题

[tomcat]源码简析 异步/非阻塞和请求构成

[tomcat]源码简析 异步/非阻塞和请求构成

Tomcat对异步Servlet的支持

无法将 JSF + CDI 项目从 Tomcat 迁移到 Wildfly

27 | 新特性:Tomcat如何支持异步Servlet?