Akka没有在Servlet中干净利落地关闭

时间:2015-03-27 11:25:36

标签: java scala servlets concurrency akka

我正在Scala中开发一个基于Servlet的Web应用程序,并使用Akka。在启动和运行时一切正常,我在查看代码时看到没有错误,我的孩子们都把自己搞砸了,正确关闭了自己。然而;当我尝试关闭服务器或重新部署时,我在控制台中遇到了很多错误:

Shutting down...
Shut down successfully.
27-Mar-2015 11:21:22.233 SEVERE [localhost-startStop-2] org.apache.catalina.loader.WebappClassLoaderBase.checkThreadLocalMapForLeaks The web application [ROOT] created a ThreadLocal with key of type [java.lang.ThreadLocal] (value [java.lang.ThreadLocal@68d6d1aa]) and a value of type [scala.concurrent.forkjoin.ForkJoinPool.Submitter] (value [scala.concurrent.forkjoin.ForkJoinPool$Submitter@1045f98]) 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.
27-Mar-2015 11:21:22.233 SEVERE [localhost-startStop-2] org.apache.catalina.loader.WebappClassLoaderBase.checkThreadLocalMapForLeaks The web application [ROOT] created a ThreadLocal with key of type [scala.util.DynamicVariable$$anon$1] (value [scala.util.DynamicVariable$$anon$1@5f818593]) and a value of type [org.apache.tomcat.util.log.SystemLogHandler] (value [org.apache.tomcat.util.log.SystemLogHandler@5b616a23]) 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.
27-Mar-2015 11:21:22.241 INFO [main] org.apache.coyote.AbstractProtocol.stop Stopping ProtocolHandler ["http-nio-8080"]
27-Mar-2015 11:21:22.243 INFO [main] org.apache.coyote.AbstractProtocol.stop Stopping ProtocolHandler ["ajp-nio-8009"]
27-Mar-2015 11:21:22.244 INFO [main] org.apache.coyote.AbstractProtocol.destroy Destroying ProtocolHandler ["http-nio-8080"]
27-Mar-2015 11:21:22.244 INFO [main] org.apache.coyote.AbstractProtocol.destroy Destroying ProtocolHandler ["ajp-nio-8009"]
Disconnected from server

如果我尝试使用常规的同步servlet,我在关机时不会在日志中收到消息。

我在servlet上有一个上下文监听器,它是:

class ContextListener extends ServletContextListener {
    private var system: ActorSystem = _

    override def contextInitialized(sce: ServletContextEvent): Unit = {
        val context = sce.getServletContext

        system = ActorSystem.create("StridentStandard")

        context.setAttribute("actor.system", system)
    }

    override def contextDestroyed(sce: ServletContextEvent): Unit = {
        println("Shutting down...")
        system.shutdown()
        system.awaitTermination()
        println("Shut down successfully.")
    }
}

所以,从它看起来的样子 - ActorSystem 应该正确关闭 - 但似乎有些线程挂在上面。

我对Scala和Akka以及并发都很新,因此我不确定从这里开始。

2 个答案:

答案 0 :(得分:1)

尝试在application.conf中设置

akka {
  daemonic=on
}

that questions一样 - 我遇到了同样的问题而且有帮助

答案 1 :(得分:1)

问题的关键在于此日志行

27-Mar-2015 11:21:22.233 SEVERE [localhost-startStop-2] org.apache.catalina.loader.WebappClassLoaderBase.checkThreadLocalMapForLeaks The web application [ROOT] created a ThreadLocal with key of type [scala.util.DynamicVariable$$anon$1] (value [scala.util.DynamicVariable$$anon$1@5f818593]) and a value of type [org.apache.tomcat.util.log.SystemLogHandler] (value [org.apache.tomcat.util.log.SystemLogHandler@5b616a23]) 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.

在webapp卸载时,Tomcat收到了很多资源泄漏的报告,这些报告是由于webapp而不是他们实现此检查的tomcat容器造成的。错误不是报告akka线程已经运行,而是存储在ThreadLocal中的值尚未清除。这将阻止JVM在卸载webapp时对Web应用程序进行GC操作。

罪魁祸首是DynamicVariable,一个包装ThreadLocal的scala类。要删除此错误,您需要跟踪谁正在使用此代码并使其自行清理。如果是负责的akka​​代码,那么尝试升级到更高版本,如果问题仍然存在,请考虑向akka团队提交补丁。

Tomcat记录了他们的内存泄漏保护协议here