线程池执行器:来自执行器的任务拒绝异常

4

我的应用程序通过Jms MessageListener类读取消息,在某个时候会抛出TaskRejectedException异常。我知道你们中的大多数人会说线程数超过了maxPoolSize和队列也已经满了。

但是我注意到了一些东西。从MessageListener类获取消息的队列发送的消息数量为10353,我的spring属性threadPoolExecutor如下:

<bean id="ticketReaderThreadPool" class="org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor" scope="singleton" destroy-method="destroy">
    <property name="corePoolSize" value="10" />
    <property name="maxPoolSize" value="150" />
    <property name="queueCapacity" value="11000" />
</bean>

根据我的看法,maxPoolSize已经足够处理这么多的请求了。因此,如果你们中有人能给出除了maxPoolSize超过限制之外的原因,请告诉我们。

我们现在已经遇到了第二次这个问题,之前我们已经尝试增加maxPoolSize,但是在15天后我们又开始每天遇到大约5000到8000次的异常。

更新:

以下是完整的异常堆栈信息:

读取队列/处理消息时发生常规异常 org.springframework.core.task.TaskRejectedException: Executor [java.util.concurrent.ThreadPoolExecutor@408b9775] did not accept task: com.batman.rapid.rapidserver.sla.TicketHandler@1be5e598 at org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor.execute(ThreadPoolTaskExecutor.java:244) at com.batman.rapid.rapidserver.sla.JmsTicketReceiver.onMessage(JmsTicketReceiver.java:58) at org.springframework.jms.listener.AbstractMessageListenerContainer.doInvokeListener(AbstractMessageListenerContainer.java:560) at org.springframework.jms.listener.AbstractMessageListenerContainer.invokeListener(AbstractMessageListenerContainer.java:498) at org.springframework.jms.listener.AbstractMessageListenerContainer.doExecuteListener(AbstractMessageListenerContainer.java:467) at org.springframework.jms.listener.AbstractPollingMessageListenerContainer.doReceiveAndExecute(AbstractPollingMessageListenerContainer.java:325) at org.springframework.jms.listener.AbstractPollingMessageListenerContainer.receiveAndExecute(AbstractPollingMessageListenerContainer.java:263) at org.springframework.jms.listener.DefaultMessageListenerContainer$AsyncMessageListenerInvoker.invokeListener(DefaultMessageListenerContainer.java:1058) at org.springframework.jms.listener.DefaultMessageListenerContainer$AsyncMessageListenerInvoker.executeOngoingLoop(DefaultMessageListenerContainer.java:1050) at org.springframework.jms.listener.DefaultMessageListenerContainer$AsyncMessageListenerInvoker.run(DefaultMessageListenerContainer.java:947) at java.lang.Thread.run(Thread.java:662) Caused by: java.util.concurrent.RejectedExecutionException at java.util.concurrent.ThreadPoolExecutor$AbortPolicy.rejectedExecution(ThreadPoolExecutor.java:1774) at java.util.concurrent.ThreadPoolExecutor.reject(ThreadPoolExecutor.java:768) at java.util.concurrent.ThreadPoolExecutor.execute(ThreadPoolExecutor.java:656) at org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor.execute(ThreadPoolTaskExecutor.java:241) ... 10 more

以下是相关代码:

if (message instanceof TextMessage)
{
    textMessage = (TextMessage) message;
    ticketReaderThreadPool.execute(new TicketHandler(textMessage.getText()));
}

以下是所请求的配置:

    <!-- End of JMS Queue Support -->

    <bean id="ticketReaderThreadPool" class="org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor" scope="singleton" destroy-method="destroy">
    <property name="corePoolSize" value="10" />
    <property name="maxPoolSize" value="150" />
    <property name="queueCapacity" value="11000" />
</bean>

    <bean id="notificationThreadPool" class="org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor" scope="singleton" destroy-method="destroy">
            <property name="corePoolSize" value="10" />
            <property name="maxPoolSize" value="100" />
            <property name="queueCapacity" value="10000" />
    </bean>

    <bean id="notificationManager" class="com.batman.rapid.rapidserver.sla.scheduler.NotificationManager" scope="singleton">
            <property name="defaultPercent" value="80"></property>
    </bean>

    <bean id="dbUpdateThreads" class="org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor" scope="singleton" destroy-method="destroy">
            <property name="corePoolSize" value="1" />
            <property name="maxPoolSize" value="100" />
            <property name="queueCapacity" value="10000" />
    </bean>

我们可以看到完整的JMS配置吗? - Karthik Prasad
我没听懂你的意思,请详细说明你的需求。 - darecoder
该错误意味着执行器已关闭或者没有可用线程来处理任务。 - Jesper
@KarthikPrasad 请查看更新中请求的配置...问题发生在接收到消息时,因此我认为最初提供的bean配置是相关的。 - darecoder
作业只需要几毫秒就能完成执行。正如您所看到的,我的queueCapacity配置足以处理应用程序正在读取的消息数量。因此,我认为没有所有线程都处于占用状态的余地。 - darecoder
显示剩余4条评论
1个回答

1
我不确定确切的原因。但我强烈感觉,最大消息计数可能超过了您设置的最大队列容量。然而,您使用的方法与JMS的一般用法有所偏差。通常,在DefaultMessageListener中,我们配置最大消费者数量以并行处理异步处理。根据服务器资源,我们配置服务器可以处理的最大消费者。
但是在您的情况下,从DefaultMessageListener读取消息,并在新线程中执行业务逻辑。由于消息侦听器的读取速度比业务逻辑快,任务会在线程任务队列中积累。
我建议重新审视您当前的实现。因为它不支持事务。我的意思是当服务器崩溃时,所有待处理的任务都将被终止/丢失,并且由于您将设置自动确认,因此消息将已从队列中删除。其他问题包括手动设置线程队列的限制等。
最后回到您的问题,您可以快速检查150个线程中是否有任何锁定。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接