子元素

当此 GatewayPollableChannel 接收消息时,必须提供全局默认 Poller 或向 Job Launching Gateway 提供 Poller 子元素。

  • Java

  • XML

以下示例展示了如何在 Java 中提供轮询器

Java 配置
@Bean
@ServiceActivator(inputChannel = "queueChannel", poller = @Poller(fixedRate="1000"))
public JobLaunchingGateway sampleJobLaunchingGateway() {
    JobLaunchingGateway jobLaunchingGateway = new JobLaunchingGateway(jobLauncher());
    jobLaunchingGateway.setOutputChannel(replyChannel());
    return jobLaunchingGateway;
}

以下示例展示了如何在 XML 中提供轮询器

XML 配置
<batch-int:job-launching-gateway request-channel="queueChannel"
    reply-channel="replyChannel" job-launcher="jobLauncher">
  <int:poller fixed-rate="1000">
</batch-int:job-launching-gateway>

提供信息性消息的反馈

由于 Spring Batch 作业可能运行很长时间,因此提供进度信息通常至关重要。例如,利益相关者可能希望在批处理作业的某些部分或全部部分失败时收到通知。Spring Batch 提供对通过以下方式收集此信息的支持

  • 主动轮询

  • 事件驱动的侦听器

在异步启动 Spring Batch 作业时(例如,通过使用作业启动网关),将返回一个 JobExecution 实例。因此,您可以使用 JobExecution.getJobId() 通过使用 JobExplorerJobRepository 检索 JobExecution 的更新实例来持续轮询状态更新。但是,这被认为不是最佳的,并且首选事件驱动的办法。

因此,Spring Batch 提供侦听器,包括三个最常用的侦听器

  • StepListener

  • ChunkListener

  • JobExecutionListener

在以下图像中所示的示例中,已使用 StepExecutionListener 配置了 Spring Batch 作业。因此,Spring Integration 在事件之前或之后接收并处理任何步骤。例如,您可以使用 Router 检查接收到的 StepExecution。根据检查结果,可能会发生各种事情(例如将消息路由到邮件出站通道适配器),以便可以根据某些条件发送电子邮件通知。

Handling Informational Messages
图 1. 处理信息消息

以下两部分示例演示如何将侦听器配置为将消息发送到 Gateway 以进行 StepExecution 事件,并将输出记录到 logging-channel-adapter

首先,创建通知集成 Bean。

  • Java

  • XML

以下示例演示如何在 Java 中创建通知集成 Bean

Java 配置
@Bean
@ServiceActivator(inputChannel = "stepExecutionsChannel")
public LoggingHandler loggingHandler() {
    LoggingHandler adapter = new LoggingHandler(LoggingHandler.Level.WARN);
    adapter.setLoggerName("TEST_LOGGER");
    adapter.setLogExpressionString("headers.id + ': ' + payload");
    return adapter;
}

@MessagingGateway(name = "notificationExecutionsListener", defaultRequestChannel = "stepExecutionsChannel")
public interface NotificationExecutionListener extends StepExecutionListener {}
您需要将 @IntegrationComponentScan 注释添加到您的配置中。

以下示例演示如何在 XML 中创建通知集成 Bean

XML 配置
<int:channel id="stepExecutionsChannel"/>

<int:gateway id="notificationExecutionsListener"
    service-interface="org.springframework.batch.core.StepExecutionListener"
    default-request-channel="stepExecutionsChannel"/>

<int:logging-channel-adapter channel="stepExecutionsChannel"/>

其次,修改您的作业以添加步骤级侦听器。

  • Java

  • XML

以下示例演示如何在 Java 中添加步骤级侦听器

Java 配置
public Job importPaymentsJob(JobRepository jobRepository, PlatformTransactionManager transactionManager) {
    return new JobBuilder("importPayments", jobRepository)
        .start(new StepBuilder("step1", jobRepository)
                .chunk(200, transactionManager)
                .listener(notificationExecutionsListener())
                // ...
                .build();
              )
        .build();
}

以下示例展示了如何在 XML 中添加步骤级侦听器

XML 配置
<job id="importPayments">
    <step id="step1">
        <tasklet ../>
            <chunk ../>
            <listeners>
                <listener ref="notificationExecutionsListener"/>
            </listeners>
        </tasklet>
        ...
    </step>
</job>

异步处理器

异步处理器帮助您扩展项目的处理。在异步处理器用例中,AsyncItemProcessor 充当调度程序,在新线程上为项目执行 ItemProcessor 的逻辑。项目完成后,Future 传递给 AsynchItemWriter 以进行写入。

因此,您可以通过使用异步项目处理来提高性能,基本上让您实现 fork-join 场景。AsyncItemWriter 收集结果,并在所有结果可用后立即回写块。

  • Java

  • XML

以下示例展示了如何在 Java 中配置 AsyncItemProcessor

Java 配置
@Bean
public AsyncItemProcessor processor(ItemProcessor itemProcessor, TaskExecutor taskExecutor) {
    AsyncItemProcessor asyncItemProcessor = new AsyncItemProcessor();
    asyncItemProcessor.setTaskExecutor(taskExecutor);
    asyncItemProcessor.setDelegate(itemProcessor);
    return asyncItemProcessor;
}

以下示例展示了如何在 XML 中配置 AsyncItemProcessor

XML 配置
<bean id="processor"
    class="org.springframework.batch.integration.async.AsyncItemProcessor">
  <property name="delegate">
    <bean class="your.ItemProcessor"/>
  </property>
  <property name="taskExecutor">
    <bean class="org.springframework.core.task.SimpleAsyncTaskExecutor"/>
  </property>
</bean>

delegate 属性引用您的 ItemProcessor bean,而 taskExecutor 属性引用您选择的 TaskExecutor

  • Java

  • XML

以下示例展示了如何在 Java 中配置 AsyncItemWriter

Java 配置
@Bean
public AsyncItemWriter writer(ItemWriter itemWriter) {
    AsyncItemWriter asyncItemWriter = new AsyncItemWriter();
    asyncItemWriter.setDelegate(itemWriter);
    return asyncItemWriter;
}

以下示例展示了如何在 XML 中配置 AsyncItemWriter

XML 配置
<bean id="itemWriter"
    class="org.springframework.batch.integration.async.AsyncItemWriter">
  <property name="delegate">
    <bean id="itemWriter" class="your.ItemWriter"/>
  </property>
</bean>

同样,delegate 属性实际上是对您的 ItemWriter bean 的引用。

外部化批处理执行

到目前为止讨论的集成方法建议使用 Spring Integration 将 Spring Batch 包装成一个外壳的用例。但是,Spring Batch 也可以在内部使用 Spring Integration。通过使用这种方法,Spring Batch 用户可以将项目甚至块的处理委托给外部进程。这可以让您卸载复杂处理。Spring Batch Integration 为以下内容提供专门支持

  • 远程分块

  • 远程分区

远程分块

当您将 Spring Batch 与 Spring Integration 一起使用时,下图展示了远程分块的一种工作方式

Remote Chunking
图 2. 远程分块

更进一步,您还可以通过使用 ChunkMessageChannelItemWriter(由 Spring Batch Integration 提供)来外部化块处理,它会发送项目并收集结果。发送后,Spring Batch 会继续读取和分组项目的进程,而无需等待结果。相反,ChunkMessageChannelItemWriter 负责收集结果并将它们重新集成到 Spring Batch 进程中。

使用 Spring Integration,你可以完全控制进程的并发性(例如,通过使用 QueueChannel 而不是 DirectChannel)。此外,通过依赖 Spring Integration 丰富的通道适配器集合(例如 JMS 和 AMQP),你可以将批处理作业的块分发到外部系统进行处理。

  • Java

  • XML

一个具有远程分块步骤的作业在 Java 中可能具有类似于以下的配置

Java 配置
public Job chunkJob(JobRepository jobRepository, PlatformTransactionManager transactionManager) {
     return new JobBuilder("personJob", jobRepository)
             .start(new StepBuilder("step1", jobRepository)
                     .<Person, Person>chunk(200, transactionManager)
                     .reader(itemReader())
                     .writer(itemWriter())
                     .build())
             .build();
 }

一个具有远程分块步骤的作业在 XML 中可能具有类似于以下的配置

XML 配置
<job id="personJob">
  <step id="step1">
    <tasklet>
      <chunk reader="itemReader" writer="itemWriter" commit-interval="200"/>
    </tasklet>
    ...
  </step>
</job>

ItemReader 引用指向你想要用于在管理器上读取数据的 Bean。ItemWriter 引用指向一个特殊的 ItemWriter(称为 ChunkMessageChannelItemWriter),如前所述。处理器(如果有)被排除在管理器配置之外,因为它是在工作程序上配置的。在实现用例时,你应该检查任何其他组件属性,例如节流限制等。

  • Java

  • XML

以下 Java 配置提供了一个基本的管理器设置

Java 配置
@Bean
public org.apache.activemq.ActiveMQConnectionFactory connectionFactory() {
    ActiveMQConnectionFactory factory = new ActiveMQConnectionFactory();
    factory.setBrokerURL("tcp://127.0.0.1:61616");
    return factory;
}

/*
 * Configure outbound flow (requests going to workers)
 */
@Bean
public DirectChannel requests() {
    return new DirectChannel();
}

@Bean
public IntegrationFlow outboundFlow(ActiveMQConnectionFactory connectionFactory) {
    return IntegrationFlow
            .from(requests())
            .handle(Jms.outboundAdapter(connectionFactory).destination("requests"))
            .get();
}

/*
 * Configure inbound flow (replies coming from workers)
 */
@Bean
public QueueChannel replies() {
    return new QueueChannel();
}

@Bean
public IntegrationFlow inboundFlow(ActiveMQConnectionFactory connectionFactory) {
    return IntegrationFlow
            .from(Jms.messageDrivenChannelAdapter(connectionFactory).destination("replies"))
            .channel(replies())
            .get();
}

/*
 * Configure the ChunkMessageChannelItemWriter
 */
@Bean
public ItemWriter<Integer> itemWriter() {
    MessagingTemplate messagingTemplate = new MessagingTemplate();
    messagingTemplate.setDefaultChannel(requests());
    messagingTemplate.setReceiveTimeout(2000);
    ChunkMessageChannelItemWriter<Integer> chunkMessageChannelItemWriter
            = new ChunkMessageChannelItemWriter<>();
    chunkMessageChannelItemWriter.setMessagingOperations(messagingTemplate);
    chunkMessageChannelItemWriter.setReplyChannel(replies());
    return chunkMessageChannelItemWriter;
}

以下 XML 配置提供了一个基本的管理器设置

XML 配置
<bean id="connectionFactory" class="org.apache.activemq.ActiveMQConnectionFactory">
  <property name="brokerURL" value="tcp://127.0.0.1:61616"/>
</bean>

<int-jms:outbound-channel-adapter id="jmsRequests" destination-name="requests"/>

<bean id="messagingTemplate"
    class="org.springframework.integration.core.MessagingTemplate">
  <property name="defaultChannel" ref="requests"/>
  <property name="receiveTimeout" value="2000"/>
</bean>

<bean id="itemWriter"
    class="org.springframework.batch.integration.chunk.ChunkMessageChannelItemWriter"
    scope="step">
  <property name="messagingOperations" ref="messagingTemplate"/>
  <property name="replyChannel" ref="replies"/>
</bean>

<int:channel id="replies">
  <int:queue/>
</int:channel>

<int-jms:message-driven-channel-adapter id="jmsReplies"
    destination-name="replies"
    channel="replies"/>

前面的配置为我们提供了一些 Bean。我们通过使用 ActiveMQ 和 Spring Integration 提供的入站和出站 JMS 适配器来配置我们的消息传递中间件。如所示,我们的 itemWriter Bean(我们的作业步骤引用该 Bean)使用 ChunkMessageChannelItemWriter 通过配置的中间件写入块。

现在我们可以继续进行工作程序配置,如下例所示

  • Java

  • XML

以下示例显示了 Java 中的工作程序配置

Java 配置
@Bean
public org.apache.activemq.ActiveMQConnectionFactory connectionFactory() {
    ActiveMQConnectionFactory factory = new ActiveMQConnectionFactory();
    factory.setBrokerURL("tcp://127.0.0.1:61616");
    return factory;
}

/*
 * Configure inbound flow (requests coming from the manager)
 */
@Bean
public DirectChannel requests() {
    return new DirectChannel();
}

@Bean
public IntegrationFlow inboundFlow(ActiveMQConnectionFactory connectionFactory) {
    return IntegrationFlow
            .from(Jms.messageDrivenChannelAdapter(connectionFactory).destination("requests"))
            .channel(requests())
            .get();
}

/*
 * Configure outbound flow (replies going to the manager)
 */
@Bean
public DirectChannel replies() {
    return new DirectChannel();
}

@Bean
public IntegrationFlow outboundFlow(ActiveMQConnectionFactory connectionFactory) {
    return IntegrationFlow
            .from(replies())
            .handle(Jms.outboundAdapter(connectionFactory).destination("replies"))
            .get();
}

/*
 * Configure the ChunkProcessorChunkHandler
 */
@Bean
@ServiceActivator(inputChannel = "requests", outputChannel = "replies")
public ChunkProcessorChunkHandler<Integer> chunkProcessorChunkHandler() {
    ChunkProcessor<Integer> chunkProcessor
            = new SimpleChunkProcessor<>(itemProcessor(), itemWriter());
    ChunkProcessorChunkHandler<Integer> chunkProcessorChunkHandler
            = new ChunkProcessorChunkHandler<>();
    chunkProcessorChunkHandler.setChunkProcessor(chunkProcessor);
    return chunkProcessorChunkHandler;
}

以下示例显示了 XML 中的工作程序配置

XML 配置
<bean id="connectionFactory" class="org.apache.activemq.ActiveMQConnectionFactory">
  <property name="brokerURL" value="tcp://127.0.0.1:61616"/>
</bean>

<int:channel id="requests"/>
<int:channel id="replies"/>

<int-jms:message-driven-channel-adapter id="incomingRequests"
    destination-name="requests"
    channel="requests"/>

<int-jms:outbound-channel-adapter id="outgoingReplies"
    destination-name="replies"
    channel="replies">
</int-jms:outbound-channel-adapter>

<int:service-activator id="serviceActivator"
    input-channel="requests"
    output-channel="replies"
    ref="chunkProcessorChunkHandler"
    method="handleChunk"/>

<bean id="chunkProcessorChunkHandler"
    class="org.springframework.batch.integration.chunk.ChunkProcessorChunkHandler">
  <property name="chunkProcessor">
    <bean class="org.springframework.batch.core.step.item.SimpleChunkProcessor">
      <property name="itemWriter">
        <bean class="io.spring.sbi.PersonItemWriter"/>
      </property>
      <property name="itemProcessor">
        <bean class="io.spring.sbi.PersonItemProcessor"/>
      </property>
    </bean>
  </property>
</bean>

这些配置项中的大多数应该看起来与管理器配置中的类似。工作程序不需要访问 Spring Batch JobRepository 也不需要访问实际的作业配置文件。主要关注的 Bean 是 chunkProcessorChunkHandlerChunkProcessorChunkHandlerchunkProcessor 属性采用一个配置的 SimpleChunkProcessor,你可以在其中提供对 ItemWriter(以及可选的 ItemProcessor)的引用,当它从管理器接收块时,将运行在工作程序上。

有关更多信息,请参阅“可扩展性”一章的 远程分块 部分。

从 4.1 版本开始,Spring Batch Integration 引入了 @EnableBatchIntegration 注释,可用于简化远程分块设置。此注释提供了两个 Bean,你可以在应用程序上下文中自动装配它们

  • RemoteChunkingManagerStepBuilderFactory:配置管理器步骤

  • RemoteChunkingWorkerBuilder:配置远程工作程序集成流

这些 API 负责配置许多组件,如下面的图表所示

Remote Chunking Configuration
图 3. 远程分块配置

在管理器端,RemoteChunkingManagerStepBuilderFactory 允许您通过声明来配置管理器步骤

  • 读取项目并将它们发送到工作线程的项目读取器

  • 用于向工作线程发送请求的输出通道(“传出请求”)

  • 用于从工作线程接收答复的输入通道(“传入答复”)

您无需显式配置 ChunkMessageChannelItemWriterMessagingTemplate。(如果您找到这样做的理由,您仍然可以显式配置它们)。

在工作线程端,RemoteChunkingWorkerBuilder 允许您配置工作线程以

  • 侦听管理器在输入通道(“传入请求”)上发送的请求

  • 使用已配置的 ItemProcessorItemWriter 为每个请求调用 ChunkProcessorChunkHandlerhandleChunk 方法

  • 通过输出通道(“传出答复”)向管理器发送答复

您无需显式配置 SimpleChunkProcessorChunkProcessorChunkHandler。(如果您找到这样做的理由,您仍然可以显式配置它们)。

以下示例展示了如何使用这些 API

@EnableBatchIntegration
@EnableBatchProcessing
public class RemoteChunkingJobConfiguration {

    @Configuration
    public static class ManagerConfiguration {

        @Autowired
        private RemoteChunkingManagerStepBuilderFactory managerStepBuilderFactory;

        @Bean
        public TaskletStep managerStep() {
            return this.managerStepBuilderFactory.get("managerStep")
                       .chunk(100)
                       .reader(itemReader())
                       .outputChannel(requests()) // requests sent to workers
                       .inputChannel(replies())   // replies received from workers
                       .build();
        }

        // Middleware beans setup omitted

    }

    @Configuration
    public static class WorkerConfiguration {

        @Autowired
        private RemoteChunkingWorkerBuilder workerBuilder;

        @Bean
        public IntegrationFlow workerFlow() {
            return this.workerBuilder
                       .itemProcessor(itemProcessor())
                       .itemWriter(itemWriter())
                       .inputChannel(requests()) // requests received from the manager
                       .outputChannel(replies()) // replies sent to the manager
                       .build();
        }

        // Middleware beans setup omitted

    }

}

您可以在 此处 找到远程分块作业的完整示例。

远程分区

下图显示了典型的远程分区情况

Remote Partitioning
图 4. 远程分区

另一方面,当导致瓶颈的不是项目的处理而是关联的 I/O 时,远程分区非常有用。通过远程分区,您可以将工作发送到执行完整 Spring Batch 步骤的工作线程。因此,每个工作线程都有自己的 ItemReaderItemProcessorItemWriter。为此,Spring Batch Integration 提供了 MessageChannelPartitionHandler

PartitionHandler 接口的此实现使用 MessageChannel 实例向远程工作线程发送指令并接收其响应。这提供了与用于与远程工作线程通信的传输(例如 JMS 和 AMQP)的良好抽象。

讨论 远程分区 的“可扩展性”章节部分概述了配置远程分区所需的理念和组件,并展示了使用默认 TaskExecutorPartitionHandler 在单独的本地执行线程中进行分区的示例。对于跨多个 JVM 的远程分区,需要两个附加组件

  • 远程结构或网格环境

  • 支持所需远程结构或网格环境的 PartitionHandler 实现

类似于远程分块,您可以将 JMS 用作“远程结构”。在这种情况下,请使用 MessageChannelPartitionHandler 实例作为 PartitionHandler 实现,如前所述。

  • Java

  • XML

以下示例假设存在已分区的作业,重点介绍 Java 中的 MessageChannelPartitionHandler 和 JMS 配置

Java 配置
/*
 * Configuration of the manager side
 */
@Bean
public PartitionHandler partitionHandler() {
    MessageChannelPartitionHandler partitionHandler = new MessageChannelPartitionHandler();
    partitionHandler.setStepName("step1");
    partitionHandler.setGridSize(3);
    partitionHandler.setReplyChannel(outboundReplies());
    MessagingTemplate template = new MessagingTemplate();
    template.setDefaultChannel(outboundRequests());
    template.setReceiveTimeout(100000);
    partitionHandler.setMessagingOperations(template);
    return partitionHandler;
}

@Bean
public QueueChannel outboundReplies() {
    return new QueueChannel();
}

@Bean
public DirectChannel outboundRequests() {
    return new DirectChannel();
}

@Bean
public IntegrationFlow outboundJmsRequests() {
    return IntegrationFlow.from("outboundRequests")
            .handle(Jms.outboundGateway(connectionFactory())
                    .requestDestination("requestsQueue"))
            .get();
}

@Bean
@ServiceActivator(inputChannel = "inboundStaging")
public AggregatorFactoryBean partitioningMessageHandler() throws Exception {
    AggregatorFactoryBean aggregatorFactoryBean = new AggregatorFactoryBean();
    aggregatorFactoryBean.setProcessorBean(partitionHandler());
    aggregatorFactoryBean.setOutputChannel(outboundReplies());
    // configure other propeties of the aggregatorFactoryBean
    return aggregatorFactoryBean;
}

@Bean
public DirectChannel inboundStaging() {
    return new DirectChannel();
}

@Bean
public IntegrationFlow inboundJmsStaging() {
    return IntegrationFlow
            .from(Jms.messageDrivenChannelAdapter(connectionFactory())
                    .configureListenerContainer(c -> c.subscriptionDurable(false))
                    .destination("stagingQueue"))
            .channel(inboundStaging())
            .get();
}

/*
 * Configuration of the worker side
 */
@Bean
public StepExecutionRequestHandler stepExecutionRequestHandler() {
    StepExecutionRequestHandler stepExecutionRequestHandler = new StepExecutionRequestHandler();
    stepExecutionRequestHandler.setJobExplorer(jobExplorer);
    stepExecutionRequestHandler.setStepLocator(stepLocator());
    return stepExecutionRequestHandler;
}

@Bean
@ServiceActivator(inputChannel = "inboundRequests", outputChannel = "outboundStaging")
public StepExecutionRequestHandler serviceActivator() throws Exception {
    return stepExecutionRequestHandler();
}

@Bean
public DirectChannel inboundRequests() {
    return new DirectChannel();
}

public IntegrationFlow inboundJmsRequests() {
    return IntegrationFlow
            .from(Jms.messageDrivenChannelAdapter(connectionFactory())
                    .configureListenerContainer(c -> c.subscriptionDurable(false))
                    .destination("requestsQueue"))
            .channel(inboundRequests())
            .get();
}

@Bean
public DirectChannel outboundStaging() {
    return new DirectChannel();
}

@Bean
public IntegrationFlow outboundJmsStaging() {
    return IntegrationFlow.from("outboundStaging")
            .handle(Jms.outboundGateway(connectionFactory())
                    .requestDestination("stagingQueue"))
            .get();
}

以下示例假设存在已分区的作业,重点介绍 XML 中的 MessageChannelPartitionHandler 和 JMS 配置

XML 配置
<bean id="partitionHandler"
   class="org.springframework.batch.integration.partition.MessageChannelPartitionHandler">
  <property name="stepName" value="step1"/>
  <property name="gridSize" value="3"/>
  <property name="replyChannel" ref="outbound-replies"/>
  <property name="messagingOperations">
    <bean class="org.springframework.integration.core.MessagingTemplate">
      <property name="defaultChannel" ref="outbound-requests"/>
      <property name="receiveTimeout" value="100000"/>
    </bean>
  </property>
</bean>

<int:channel id="outbound-requests"/>
<int-jms:outbound-channel-adapter destination="requestsQueue"
    channel="outbound-requests"/>

<int:channel id="inbound-requests"/>
<int-jms:message-driven-channel-adapter destination="requestsQueue"
    channel="inbound-requests"/>

<bean id="stepExecutionRequestHandler"
    class="org.springframework.batch.integration.partition.StepExecutionRequestHandler">
  <property name="jobExplorer" ref="jobExplorer"/>
  <property name="stepLocator" ref="stepLocator"/>
</bean>

<int:service-activator ref="stepExecutionRequestHandler" input-channel="inbound-requests"
    output-channel="outbound-staging"/>

<int:channel id="outbound-staging"/>
<int-jms:outbound-channel-adapter destination="stagingQueue"
    channel="outbound-staging"/>

<int:channel id="inbound-staging"/>
<int-jms:message-driven-channel-adapter destination="stagingQueue"
    channel="inbound-staging"/>

<int:aggregator ref="partitionHandler" input-channel="inbound-staging"
    output-channel="outbound-replies"/>

<int:channel id="outbound-replies">
  <int:queue/>
</int:channel>

<bean id="stepLocator"
    class="org.springframework.batch.integration.partition.BeanFactoryStepLocator" />

您还必须确保分区 handler 属性映射到 partitionHandler bean。

  • Java

  • XML

以下示例将分区 handler 属性映射到 Java 中的 partitionHandler

Java 配置
	public Job personJob(JobRepository jobRepository) {
		return new JobBuilder("personJob", jobRepository)
				.start(new StepBuilder("step1.manager", jobRepository)
						.partitioner("step1.worker", partitioner())
						.partitionHandler(partitionHandler())
						.build())
				.build();
	}

以下示例将分区 handler 属性映射到 XML 中的 partitionHandler

XML 配置
<job id="personJob">
  <step id="step1.manager">
    <partition partitioner="partitioner" handler="partitionHandler"/>
    ...
  </step>
</job>

您可以在此处找到远程分区作业的完整示例 here

您可以使用 @EnableBatchIntegration 注解来简化远程分区设置。此注解提供了两个对远程分区有用的 bean

  • RemotePartitioningManagerStepBuilderFactory:配置管理器步骤

  • RemotePartitioningWorkerStepBuilderFactory:配置工作步骤

这些 API 负责配置许多组件,如下面的图表所示

Remote Partitioning Configuration (with job repository polling)
图 5. 远程分区配置(带作业库轮询)
Remote Partitioning Configuration (with replies aggregation)
图 6. 远程分区配置(带答复聚合)

在管理器端,RemotePartitioningManagerStepBuilderFactory 允许您通过声明来配置管理器步骤

  • 用于分区数据的 Partitioner

  • 用于向工作程序发送请求的输出通道(“传出请求”)

  • 用于接收来自工作程序的答复的输入通道(“传入答复”)(在配置答复聚合时)

  • 轮询间隔和超时参数(在配置作业库轮询时)

您无需显式配置 MessageChannelPartitionHandlerMessagingTemplate。(如果您找到这样做的原因,您仍然可以显式配置它们)。

在工作程序端,RemotePartitioningWorkerStepBuilderFactory 允许您配置工作程序来

  • 侦听管理器在输入通道(“传入请求”)上发送的请求

  • 为每个请求调用 StepExecutionRequestHandlerhandle 方法

  • 通过输出通道(“传出答复”)向管理器发送答复

您无需显式配置 StepExecutionRequestHandler。(如果您找到这样做的原因,您可以显式配置它)。

以下示例展示了如何使用这些 API

@Configuration
@EnableBatchProcessing
@EnableBatchIntegration
public class RemotePartitioningJobConfiguration {

    @Configuration
    public static class ManagerConfiguration {

        @Autowired
        private RemotePartitioningManagerStepBuilderFactory managerStepBuilderFactory;

        @Bean
        public Step managerStep() {
                 return this.managerStepBuilderFactory
                    .get("managerStep")
                    .partitioner("workerStep", partitioner())
                    .gridSize(10)
                    .outputChannel(outgoingRequestsToWorkers())
                    .inputChannel(incomingRepliesFromWorkers())
                    .build();
        }

        // Middleware beans setup omitted

    }

    @Configuration
    public static class WorkerConfiguration {

        @Autowired
        private RemotePartitioningWorkerStepBuilderFactory workerStepBuilderFactory;

        @Bean
        public Step workerStep() {
                 return this.workerStepBuilderFactory
                    .get("workerStep")
                    .inputChannel(incomingRequestsFromManager())
                    .outputChannel(outgoingRepliesToManager())
                    .chunk(100)
                    .reader(itemReader())
                    .processor(itemProcessor())
                    .writer(itemWriter())
                    .build();
        }

        // Middleware beans setup omitted

    }

}