【问题标题】:Spring rabbit starts SimpleAsyncTaskExecutor threads that don't let Tomcat shutdownSpring rabbit 启动不让 Tomcat 关闭的 SimpleAsyncTaskExecutor 线程
【发布时间】:2016-01-26 21:24:12
【问题描述】:

当关闭 Tomcat 时,它会挂起。线程转储显示了八个仍在运行的非守护程序线程,例如:

"SimpleAsyncTaskExecutor-1" #191 prio=5 os_prio=0      tid=0x00007fb138cfa000 nid=0x1e8c waiting on condition    [0x00007fb137bfa000]
   java.lang.Thread.State: TIMED_WAITING (parking)
at sun.misc.Unsafe.park(Native Method)
- parking to wait for  <0x00000000e03e5198> (a java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject)
at java.util.concurrent.locks.LockSupport.parkNanos(LockSupport.java:215)
at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.awaitNanos(AbstractQueuedSynchronizer.java:2078)
at java.util.concurrent.LinkedBlockingQueue.poll(LinkedBlockingQueue.java:467)
at org.springframework.amqp.rabbit.listener.BlockingQueueConsumer.nextMessage(BlockingQueueConsumer.java:359)
at org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer.doReceiveAndExecute(SimpleMessageListenerContainer.java:1000)
at org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer.receiveAndExecute(SimpleMessageListenerContainer.java:989)
at org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer.access$700(SimpleMessageListenerContainer.java:82)
at org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer$AsyncMessageProcessingConsumer.run(SimpleMessageListenerContainer.java:1103)
at java.lang.Thread.run(Thread.java:745)

当我通过 intellij 运行应用程序时,这些线程没有启动,并且在通过 intellij 完成时正确关闭。它们仅在使用启动 shell 脚本启动 Web 应用程序时启动。

我如何确定是什么导致了这些线程被创建以及为什么它们不会关闭?

更新:这是我的项目的 web.xml。

<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
     xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
      http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
     version="3.1"
     metadata-complete="true">

<absolute-ordering/>

<display-name>Test Web</display-name>
<context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>
        classpath*:spring/app-context.xml
    </param-value>
</context-param>

<welcome-file-list>
    <welcome-file>index.html</welcome-file>
</welcome-file-list>

<listener>
    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>

<listener>
    <listener-class>org.springframework.security.web.session.HttpSessionEventPublisher</listener-class>
</listener>

<servlet>
    <servlet-name>dispatcherServlet</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <load-on-startup>1</load-on-startup>
    <async-supported>true</async-supported>
</servlet>

<servlet-mapping>
    <servlet-name>dispatcherServlet</servlet-name>
    <url-pattern>/</url-pattern>
</servlet-mapping>

<filter>
    <filter-name>springSessionRepositoryFilter</filter-name>
    <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>
<filter-mapping>
    <filter-name>springSessionRepositoryFilter</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>

<filter>
    <filter-name>springSecurityFilterChain</filter-name>
    <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
    <async-supported>true</async-supported>
</filter>
<filter-mapping>
    <filter-name>springSecurityFilterChain</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>

<filter>
    <filter-name>corsFilter</filter-name>
    <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
    <async-supported>true</async-supported>
</filter>
<filter-mapping>
    <filter-name>corsFilter</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>

<filter>
    <filter-name>etagFilter</filter-name>
    <filter-class>org.springframework.web.filter.ShallowEtagHeaderFilter</filter-class>
    <async-supported>true</async-supported>
</filter>
<filter-mapping>
    <filter-name>etagFilter</filter-name>
    <url-pattern>/resource/*</url-pattern>
</filter-mapping>

<session-config>
    <session-timeout>60</session-timeout>
</session-config>

【问题讨论】:

  • 您是否在转储中看到0x00000000e03e5198 被锁定(您应该能够)?

标签: tomcat spring-rabbit


【解决方案1】:

这意味着应用程序上下文没有被正确关闭。这些线程在SimpleMessageListenerContainer 中用于向侦听器传递消息。

您是如何加载应用程序上下文的?如果您在代码中执行此操作,则您有责任close() 上下文以停止容器。

在 Web 容器中,上下文应由 DispatcherServlet、ContextLoaderListener 或 WebApplicationInitializer 加载,以便正确关闭。

【讨论】:

  • 我完全通过 web.xml 文件加载我的应用程序。我的每个消费者都有 17 个类似的线程,它们也被加载。那些是正确关闭的。我注意到当我在 intellij 中加载我的应用程序时,仅启动了这 17 个,但是当我仅通过 tomcat 启动它时,又启动了 8 个线程,这也与我拥有的入站通道适配器的数量相匹配。我会尝试切换到 WebApplicationInitializer 看看是否可以解决它。
  • 听起来您可能正在加载 2 个上下文,其中一个没有关闭;使用您的 web.xml 编辑您的问题。这是一个常见的错误。
  • 问题是加载了多个上下文。我在类路径上有多个名为 app-context.xml 的文件。
猜你喜欢
  • 1970-01-01
  • 2014-10-30
  • 1970-01-01
  • 2021-10-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-04-21
相关资源
最近更新 更多