我的应用程序是通过Jms MessageListener类读取消息,并且在某些时候它正在抛出 TaskRejectedException 。我知道大多数人会说 maxPoolSize 超出了线程数,队列也已满。
但是我发现了一些事情。发送到MessageListener类从中获取消息的队列的消息数是10353,而threadPoolExecutor的spring属性如下:
<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]不接受任务:com.batman.rapid.rapidserver.sla.TicketHandler@1be5e598 在org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor.execute(ThreadPoolTaskExecutor.java:244) 在com.batman.rapid.rapidserver.sla.JmsTicketReceiver.onMessage(JmsTicketReceiver.java:58) 在org.springframework.jms.listener.AbstractMessageListenerContainer.doInvokeListener(AbstractMessageListenerContainer.java:560) 在org.springframework.jms.listener.AbstractMessageListenerContainer.invokeListener(AbstractMessageListenerContainer.java:498) 在org.springframework.jms.listener.AbstractMessageListenerContainer.doExecuteListener(AbstractMessageListenerContainer.java:467) 在org.springframework.jms.listener.AbstractPollingMessageListenerContainer.doReceiveAndExecute(AbstractPollingMessageListenerContainer.java:325) 在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) 在org.springframework.jms.listener.DefaultMessageListenerContainer $ AsyncMessageListenerInvoker.run(DefaultMessageListenerContainer.java:947) 在java.lang.Thread.run(Thread.java:662) 引起: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) 在org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor.execute(ThreadPoolTaskExecutor.java:241) ......还有10个
这是相关代码:
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>
答案 0 :(得分:1)
不确定究竟是什么原因。但是我强烈地感觉到,最大消息数可能会超出您设置的maxqueueCapacity。但是,您使用的不同方法与JMS的一般用法不同。通常在DefaultMessageListener中,我们配置Max-consumer的数量,以并行处理异步处理。基于服务器资源,我们配置服务器可以处理的最大消费者
但是在您的情况下,从DefaultMessageListener中读取消息并生成新线程并在新线程中执行业务逻辑。由于消息侦听器读取比业务逻辑更快,因此任务在线程任务队列中累积。
我建议重新接近你当前的实现。因为它不支持交易。我的意思是当服务器崩溃时,任务中的所有待处理消息处理都将被终止/丢失,并且由于您将设置auto-ack,因此该消息将从队列中删除。其他问题如设置线程队列的手动限制等。
最后回到你的问题,你可以快速检查你设置的150个线程中是否有锁