即使并发性为10,Spring批处理管理远程分区步骤最多可运行8个线程?

时间:2014-07-04 13:02:28

标签: spring spring-batch spring-integration spring-batch-admin

我正在使用spring批量远程分区进行批处理。我正在使用spring batch admin启动工作。

我的入站网关消费者并发步骤为10,但并行运行的最大分区数为8。

我希望稍后将消费者并发度提高到15。

以下是我的配置

<task:executor id="taskExecutor" pool-size="50" />

<rabbit:template id="computeAmqpTemplate"
    connection-factory="rabbitConnectionFactory" routing-key="computeQueue"
    reply-timeout="${compute.partition.timeout}">
</rabbit:template>

<int:channel id="computeOutboundChannel">
    <int:dispatcher task-executor="taskExecutor" />
</int:channel>

<int:channel id="computeInboundStagingChannel" />

<amqp:outbound-gateway request-channel="computeOutboundChannel"
    reply-channel="computeInboundStagingChannel" amqp-template="computeAmqpTemplate"
    mapped-request-headers="correlationId, sequenceNumber, sequenceSize, STANDARD_REQUEST_HEADERS"
    mapped-reply-headers="correlationId, sequenceNumber, sequenceSize, STANDARD_REQUEST_HEADERS" />


<beans:bean id="computeMessagingTemplate"
    class="org.springframework.integration.core.MessagingTemplate"
    p:defaultChannel-ref="computeOutboundChannel"
    p:receiveTimeout="${compute.partition.timeout}" />


<beans:bean id="computePartitionHandler"
    class="org.springframework.batch.integration.partition.MessageChannelPartitionHandler"
    p:stepName="computeStep" p:gridSize="${compute.grid.size}"
    p:messagingOperations-ref="computeMessagingTemplate" />

<int:aggregator ref="computePartitionHandler"
    send-partial-result-on-expiry="true" send-timeout="${compute.step.timeout}"
    input-channel="computeInboundStagingChannel" />

<amqp:inbound-gateway concurrent-consumers="${compute.consumer.concurrency}"
    request-channel="computeInboundChannel" 
    reply-channel="computeOutboundStagingChannel" queue-names="computeQueue"
    connection-factory="rabbitConnectionFactory"
    mapped-request-headers="correlationId, sequenceNumber, sequenceSize, STANDARD_REQUEST_HEADERS"
    mapped-reply-headers="correlationId, sequenceNumber, sequenceSize, STANDARD_REQUEST_HEADERS" />


<int:channel id="computeInboundChannel" />

<int:service-activator ref="stepExecutionRequestHandler"
    input-channel="computeInboundChannel" output-channel="computeOutboundStagingChannel" />

<int:channel id="computeOutboundStagingChannel" />

<beans:bean id="computePartitioner"
    class="org.springframework.batch.core.partition.support.MultiResourcePartitioner"
    p:resources="file:${spring.tmp.batch.dir}/#{jobParameters[batch_id]}/shares_rics/shares_rics_*.txt"
    scope="step" />



<beans:bean id="computeFileItemReader"
    class="org.springframework.batch.item.file.FlatFileItemReader"
    p:resource="#{stepExecutionContext[fileName]}" p:lineMapper-ref="stLineMapper"
    scope="step" />

<beans:bean id="computeItemWriter"
    class="com.st.batch.foundation.writers.ComputeItemWriter"
    p:symfony-ref="symfonyStepScoped" p:timeout="${compute.item.timeout}"
    p:batchId="#{jobParameters[batch_id]}" scope="step" />


<step id="computeStep">
    <tasklet transaction-manager="transactionManager">
        <chunk reader="computeFileItemReader" writer="computeItemWriter"
            commit-interval="${compute.commit.interval}" />
    </tasklet>
</step>

<flow id="computeFlow">
    <step id="computeStep.master">
        <partition partitioner="computePartitioner"
            handler="computePartitionHandler" />
    </step>
</flow>

<job id="computeJob" restartable="true">
    <flow id="computeJob.computeFlow" parent="computeFlow" />
</job>



compute.grid.size = 112
compute.consumer.concurrency = 10

Input files are splited to 112 equal parts = compute.grid.size = total number of partitions

Number of servers = 4.

有两个问题,

i)尽管我已将并发设置为10,但最大运行线程数为8。

ii)

有些速度较慢,因为其他进程在它们上运行,有些速度更快,所以我想确保步骤执行是公平分配的,即如果执行速度更快的服务器,队列中的其他剩余执行应该转到它们。它不应该以循环方式分发。

我知道在rabbitmq中有预取计数设置和ack模式来分配。对于弹簧集成,预取计数默认为1,ack模式默认为AUTO。但是,即使其他服务器长时间运行,仍有一些服务器会继续运行更多分区。理想情况下,没有服务器应该闲置。

更新

我现在观察到的另一件事是,对于使用拆分并行运行的一些步骤(不使用远程分区分布),也可以并行运行max 8。它看起来像线程池限制问题但是你可以看到taskExecutor的pool-size设置为50。

spring-batch / spring-batch-admin中有什么限制了并发运行步骤的数量吗?

第二次更新:

并且,如果在并行处理项目中有8个或更多线程运行,则弹出批处理管理员不会加载。它只是挂起。如果我减少并发性,那么Spring批量管理会加载。我甚至通过在一台服务器上设置并发4和在其他服务器上设置8来测试它,Spring批处理管理员没有加载它我使用服务器的URL,其中8个线程正在运行,但它可以在运行4个线程的服务器上运行。 / p>

Spring批处理管理器具有jobLauncher配置,

<bean id="jobLauncher" class="org.springframework.batch.core.launch.support.SimpleJobLauncher">
    <property name="jobRepository" ref="jobRepository" />
    <property name="taskExecutor" ref="jobLauncherTaskExecutor" />
</bean>

<task:executor id="jobLauncherTaskExecutor" pool-size="6" rejection-policy="ABORT" />

那里的游泳池大小是6,与上述问题有什么关系吗?

或者tomcat 7中有什么限制运行的线程数为8?

2 个答案:

答案 0 :(得分:1)

您是否正在使用JobRepository的数据库?

在执行期间,批处理框架会持续执行步骤,并且与JobRepository数据库的连接数会干扰并行步骤执行。

8的并发性让我觉得你可能正在使用BasicDataSource?如果是这样,请切换到DriverManagerDataSource之类的内容,然后查看。

答案 1 :(得分:0)

困惑 - 你说&#34;我已经将并发设置为10&#34;但然后显示compute.consumer.concurrency = 8。所以它按配置工作。如果属性设置为10,则不可能只有8个消费者线程。

从Rabbit的角度来看,所有消费者都是平等的 - 如果慢速盒子上有10个消费者,快速盒子上有10个消费者,而你只有10个分区,那么所有10个分区都可能会结束在缓慢的盒子上。

RabbitMQ不会跨服务器分发工作,它只在消费者之间分配工作。

通过降低并发性可以获得更好的分发。您还应该在较慢的框上设置较低的并发性。