4. 批处理

本部分更详细地介绍了 Spring Cloud Task 与 Spring Batch 的集成。包括将作业执行与执行该作业的任务之间的关联跟踪,以及通过 Spring Cloud Deployer 远程分区均在本部分中介绍。spring-doc.cadn.net.cn

4.1. 将作业执行关联到其执行的任务

Spring Boot 提供了在 uber-jar 中执行批处理作业的设施。 Spring Boot 对此功能的支持让开发人员可以在同一个执行中运行多个批处理作业。 Spring Cloud Task 提供了将作业的执行(即作业执行)与任务的执行关联起来的能力,使得两者可以相互追溯。spring-doc.cadn.net.cn

Spring Cloud Task 通过使用 TaskBatchExecutionListener 来实现此功能。 默认情况下, 此监听器会在任何同时具有配置了 Spring Batch 作业(通过在上下文中定义了类型为 Job 的 bean)且在类路径上有 spring-cloud-task-batch jar 的上下文中自动配置。该监听器会被注入到所有符合条件的作业中。spring-doc.cadn.net.cn

4.1.1. 覆盖任务批处理执行监听器

为了防止侦听器被注入到当前上下文内的任何批处理作业中,您可以使用标准的 Spring Boot 机制来禁用自动配置。spring-doc.cadn.net.cn

仅在特定作业的上下文中将监听器注入到特定作业中,可重写 batchTaskExecutionListenerBeanPostProcessor 并提供作业bean ID列表,如下例所示:spring-doc.cadn.net.cn

public TaskBatchExecutionListenerBeanPostProcessor batchTaskExecutionListenerBeanPostProcessor() {
    TaskBatchExecutionListenerBeanPostProcessor postProcessor =
        new TaskBatchExecutionListenerBeanPostProcessor();

    postProcessor.setJobNames(Arrays.asList(new String[] {"job1", "job2"}));

    return postProcessor;
}
您可以在Spring Cloud Task项目samples模块中找到一个示例批处理应用程序, 在这里

4.2. 远程分片

Spring Cloud Deployer 提供了在 大多数云基础设施上启动基于 Spring Boot 的应用程序的设施。The 0 和 The 1 将工作步骤执行的启动委托给 Spring Cloud Deployer。spring-doc.cadn.net.cn

要配置 DeployerStepExecutionHandler,必须提供一个表示要执行的 Spring Boot uber-jar 的 Resource,以及一个 TaskLauncher。 你还可以配置任何环境属性、同时执行的最大工作者数量、轮询结果的间隔(默认为 10 秒),以及超时(默认为 -1 或无限期)。以下示例展示了如何配置这个 PartitionHandlerspring-doc.cadn.net.cn

@Bean
public PartitionHandler partitionHandler(TaskLauncher taskLauncher,
        JobExplorer jobExplorer) throws Exception {

    MavenProperties mavenProperties = new MavenProperties();
    mavenProperties.setRemoteRepositories(new HashMap<>(Collections.singletonMap("springRepo",
        new MavenProperties.RemoteRepository(repository))));

    Resource resource =
        MavenResource.parse(String.format("%s:%s:%s",
                "io.spring.cloud",
                "partitioned-batch-job",
                "1.1.0.RELEASE"), mavenProperties);

    DeployerPartitionHandler partitionHandler =
        new DeployerPartitionHandler(taskLauncher, jobExplorer, resource, "workerStep");

    List<String> commandLineArgs = new ArrayList<>(3);
    commandLineArgs.add("--spring.profiles.active=worker");
    commandLineArgs.add("--spring.cloud.task.initialize.enable=false");
    commandLineArgs.add("--spring.batch.initializer.enabled=false");

    partitionHandler.setCommandLineArgsProvider(
        new PassThroughCommandLineArgsProvider(commandLineArgs));
    partitionHandler.setEnvironmentVariablesProvider(new NoOpEnvironmentVariablesProvider());
    partitionHandler.setMaxWorkers(2);
    partitionHandler.setApplicationName("PartitionedBatchJobTask");

    return partitionHandler;
}
当将环境变量传递给分区时,每个分区可能位于不同的机器上,且环境设置不同。 因此,您应该只传递所需的环境变量。

注意在上面的例子中,我们设置了工作者的最大数量为 2。 设置工作者的最大数量确定了在一次运行中应同时运行的分区的最大数量。spring-doc.cadn.net.cn

The Resource to be executed is expected to be a Spring Boot über-jar with a DeployerStepExecutionHandler configured as a CommandLineRunner in the current context. The repository enumerated in the preceding example should be the remote repository in which the über-jar is located. Both the manager and worker are expected to have visibility into the same data store being used as the job repository and task repository. Once the underlying infrastructure has bootstrapped the Spring Boot jar and Spring Boot has launched the DeployerStepExecutionHandler, the step handler executes the requested Step. The following example shows how to configure the DeployerStepExecutionHandler:spring-doc.cadn.net.cn

@Bean
public DeployerStepExecutionHandler stepExecutionHandler(JobExplorer jobExplorer) {
    DeployerStepExecutionHandler handler =
        new DeployerStepExecutionHandler(this.context, jobExplorer, this.jobRepository);

    return handler;
}
您可以在 Spring Cloud Task 项目中的 samples 模块找到一个远程分区应用程序的示例, 在这里

4.2.1. 在Kubernetes平台为批处理分区应用程序进行开发的注意事项

  • 在部署分区应用程序到 Kubernetes 平台时,必须使用以下依赖项:Spring Cloud Kubernetes Deployerspring-doc.cadn.net.cn

    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-deployer-kubernetes</artifactId>
    </dependency>
  • 该任务应用程序的应用程序名称及其分区需要遵循 以下正则表达式模式: [a-z0-9]([-a-z0-9]*[a-z0-9])。 否则,会抛出异常。spring-doc.cadn.net.cn

4.2.2. 在Cloud Foundry平台为分批分区应用程序进行开发的注意事项

  • 在 Cloud Foundry 平台部署分区应用程序时,必须使用以下依赖项用于 Spring Cloud Foundry 部署器:spring-doc.cadn.net.cn

    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-deployer-cloudfoundry</artifactId>
    </dependency>
    <dependency>
        <groupId>io.projectreactor</groupId>
        <artifactId>reactor-core</artifactId>
        <version>3.1.5.RELEASE</version>
    </dependency>
    <dependency>
        <groupId>io.projectreactor.ipc</groupId>
        <artifactId>reactor-netty</artifactId>
        <version>0.7.5.RELEASE</version>
    </dependency>
  • 当配置分区处理器时,需要建立Cloud Foundry部署环境变量,以便分区处理器可以启动分区。以下列表显示了所需的环境变量:spring-doc.cadn.net.cn

一个使用 0 数据库服务的分区任务的部署环境变量示例可能如下所示:spring-doc.cadn.net.cn

spring_cloud_deployer_cloudfoundry_url=https://api.local.pcfdev.io
spring_cloud_deployer_cloudfoundry_org=pcfdev-org
spring_cloud_deployer_cloudfoundry_space=pcfdev-space
spring_cloud_deployer_cloudfoundry_domain=local.pcfdev.io
spring_cloud_deployer_cloudfoundry_username=admin
spring_cloud_deployer_cloudfoundry_password=admin
spring_cloud_deployer_cloudfoundry_services=mysql
spring_cloud_deployer_cloudfoundry_taskTimeout=300
在使用 PCF-Dev 时,还需要以下环境变量: spring_cloud_deployer_cloudfoundry_skipSslValidation=true

4.3. 批处理信息性消息

Spring Cloud Task 提供了批处理作业发送信息性消息的能力。 The “Spring Batch 事件”部分对此功能有详细说明。spring-doc.cadn.net.cn

4.4. 批处理作业退出代码

正如前面讨论的,Spring Cloud Task 应用程序支持记录任务执行的退出码。但是,当你在任务中运行一个 Spring Batch 作业时,无论该 Batch 作业执行如何完成,使用默认的 Batch/Boot 行为时,任务的结果总是零。请记住,任务就是一个启动应用程序,其返回的退出码与启动应用程序相同。 要覆盖这种行为,允许在作业返回一个 BatchStatusFAILED,设置 spring.cloud.task.batch.fail-on-job-failuretrue。然后任务的退出码可以是 1(默认)或基于 指定的 ExitCodeGeneratorspring-doc.cadn.net.cn

此功能使用一个新的CommandLineRunner,它替代了由Spring Boot提供的那个。默认情况下,它配置为相同的顺序。但是,如果你想自定义CommandLineRunner的运行顺序,可以通过设置spring.cloud.task.batch.commandLineRunnerOrder属性来设置。要使你的任务根据批处理作业执行结果返回退出代码,你需要编写自己的CommandLineRunnerspring-doc.cadn.net.cn