我们正在将多个批处理作业分块批处理转换为远程分块批处理,因为我们需要能够在定义的时间范围内处理多达100万个块。我们有工作正在运行,但我们遇到了一些与绩效相关的问题。
我们的工作每个条目/块的处理时间相当长,通常只需几秒钟。
我们在从属端使用以下配置:
<bean id="ourTaskExecutor" class="...ThreadPoolTaskExecutor">
<property name="corePoolSize" value="16" />
<property name="maxPoolSize" value="16" />
<property name="queueCapacity" value="256" />
</bean>
<int-jms:inbound-channel-adapter
id="JobJmsRequests"
connection-factory="jmsConnectionFactory"
channel="requests.chunking"
destination-name="requests.chunking" >
<int:poller task-executor="ourTaskExecutor"
fixed-delay="50"
max-messages-per-poll="4"
receive-timeout="50"/>
</int-jms:inbound-channel-adapter>
<int-jms:outbound-channel-adapter
id="JobJmsReplies"
connection-factory="jmsConnectionFactory"
destination-name="replies.chunking"
channel="replies.chunking"/>
<int:service-activator
id="JobActivator"
input-channel="requests.chunking"
output-channel="replies.chunking"
ref="JobChunkHandler" method="handleChunk"/>
我们已将主节点设置为在64个块上进行限制,因此任何时候都不应处理超过64个块。
我们的假设是轮询器会将收到的消息移交给任务执行器以便对它们进行处理,但是在任务执行器中最多只能有64条消息,这些消息可以容纳256 + 16条消息。
但是,我们看到的异常是已达到队列容量,任务执行者拒绝任务。我们认为这是因为任务执行程序仅由轮询器使用并在轮询线程上处理获取的请求。由于处理需要很长时间,因此我们会使用轮询任务慢慢充斥任务执行程序。并在一个线程中处理他们收到的所有内容。)
我们无法完全解释泛滥,因为我们使用了接收超时和延迟,所以我们的理解是应该在触发新的轮询之前完成处理。然而,情况并非如此。
我们基本上尝试配置的内容如下:
只应同时处理16条消息。 Addtional消息将排队(使用相当小的队列,比如说池的大小)。 当池已满时,我们希望轮询器被阻塞,直到线程池中的空间可用。我们不希望奴隶急切地获取太多的工作。
我们希望在不同的线程上进行轮询和执行。这有可能吗?如何实现?
答案 0 :(得分:0)
使用来电者或来电者RejectedExecutionHandler
。
也就是说,你不需要内存中的块 - 它们会在系统故障时丢失。
您应该使用消息驱动的入站通道适配器,并发性设置为您要处理的并发块数。