一、概述

 

Spring Cloud Task 的目标是为 Spring Boot 应用程序提供创建短期微服务的功能。

在 Spring Cloud Task 中,我们可以灵活地动态运行任何任务,按需分配资源并在任务完成后检索结果。

Tasks 是 Spring Cloud Data Flow 中的一个新原语,允许用户将几乎任何 Spring Boot 应用程序作为短期任务执行。

2. 开发一个简单的任务应用程序

 

2.1。添加相关依赖

 

首先,我们可以使用spring-cloud-task-dependencies 添加依赖管理部分:

<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-task-dependencies</artifactId>
            <version>2.2.3.RELEASE</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
    </dependencies>
</dependencyManagement>

这种依赖管理通过导入范围管理依赖的版本。

 

我们需要添加以下依赖项:

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-task</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-task-core</artifactId>
</dependency>

这是spring-cloud-task-core的 Maven 中心的链接。

现在,要启动我们的 Spring Boot 应用程序,我们需要带有相关父级的 spring-boot-starter 。

我们将使用 Spring Data JPA 作为 ORM 工具,因此我们还需要为此添加依赖项:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-jpa</artifactId>
    <version>2.6.1</version>
</dependency>

此处提供了使用 Spring Data JPA 引导简单 Spring Boot 应用程序的详细信息。

 

我们可以在 Maven Central 上查看spring - boot- starter -parent的最新版本。

2.2. @EnableTask注解_

 

为了引导 Spring Cloud Task 的功能,我们需要添加@EnableTask注解:

@SpringBootApplication
@EnableTask
public class TaskDemo {
    // ...
}

注释在图片中带来了SimpleTaskConfiguration类,该类又注册了TaskRepository及其基础设施。默认情况下,内存映射用于存储TaskRepository的状态。

TaskRepository的主要信息在TaskExecution类中建模。此类的注意字段是taskNamestartTimeendTimeexitMessage。exitMessage存储退出可用的信息。

如果退出是由于应用程序的任何事件失败而导致的,则完整的异常堆栈跟踪将存储在这里。

 

Spring Boot 提供了一个接口ExitCodeExceptionMapper,它将未捕获的异常映射到允许仔细调试的退出代码。Cloud Task 将信息存储在数据源中以供将来分析。

2.3. 为TaskRepository配置数据源

 

一旦任务结束,存储TaskRepository的内存映射将消失,我们将丢失与 Task 事件相关的数据。为了存储在永久存储中,我们将使用 MySQL 作为 Spring Data JPA 的数据源。

数据源在application.yml文件中配置。要将 Spring Cloud Task 配置为使用提供的数据源作为TaskRepository的存储,我们需要创建一个扩展DefaultTaskConfigurer的类。

现在,我们可以将配置的数据源作为构造函数参数发送给超类的构造函数:

@Autowired
private DataSource dataSource;

public class HelloWorldTaskConfigurer extends DefaultTaskConfigurer{
    public HelloWorldTaskConfigurer(DataSource dataSource){
        super(dataSource);
    }
}

要使上述配置生效,我们需要使用@Autowired注释来注释DataSource的实例,并将该实例作为上面定义的HelloWorldTaskConfigurer bean的构造函数参数注入:

@Bean
public HelloWorldTaskConfigurer getTaskConfigurer() {
    return new HelloWorldTaskConfigurer(dataSource);
}

这样就完成了将TaskRepository存储到 MySQL 数据库的配置。

2.4. 执行

 

在 Spring Boot 中,我们可以在应用程序完成启动之前执行任何任务。我们可以使用ApplicationRunnerCommandLineRunner接口来创建一个简单的 Task。

我们需要实现这些接口的run方法,并将实现类声明为bean:

 

@Component
public static class HelloWorldApplicationRunner 
  implements ApplicationRunner {
 
    @Override
    public void run(ApplicationArguments arg0) throws Exception {
        System.out.println("Hello World from Spring Cloud Task!");
    }
}

现在,如果我们运行我们的应用程序,我们应该让我们的任务产生必要的输出,并在我们的 MySQL 数据库中创建所需的表来记录任务的事件数据。

3. Spring Cloud 任务的生命周期

 

一开始,我们在TaskRepository中创建一个条目。这表明所有 bean 都已准备好在 Application 中使用,并且 Runner 接口的run方法已准备好执行。

在run方法的执行完成或ApplicationContext事件发生任何失败时, TaskRepository将使用另一个条目进行更新。

在任务生命周期中,我们可以从TaskExecutionListener接口注册监听器。我们需要一个实现具有三个方法的接口的类—— onTaskEndonTaksFailedonTaskStartup在 Task 的各个事件中触发。

我们需要在TaskDemo类中声明实现类的bean:

@Bean
public TaskListener taskListener() {
    return new TaskListener();
}

4. 与 Spring Batch 集成

 

我们可以将 Spring Batch Job 作为 Task 执行,并使用 Spring Cloud Task 记录 Job 执行的事件。要启用此功能,我们需要添加与 Boot 和 Cloud 有关的 Batch 依赖项:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-batch</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-task-batch</artifactId>
</dependency>

这是spring-cloud-task-batch的 Maven 中心的链接。

要将作业配置为任务,我们需要在JobConfiguration类中注册 Job bean:

 

@Bean
public Job job2() {
    return jobBuilderFactory.get("job2")
      .start(stepBuilderFactory.get("job2step1")
      .tasklet(new Tasklet(){
          @Override
          public RepeatStatus execute(
            StepContribution contribution,
            ChunkContext chunkContext) throws Exception {
            System.out.println("This job is from Baeldung");
                return RepeatStatus.FINISHED;
          }
    }).build()).build();
}

我们需要用@EnableBatchProcessing注解来装饰TaskDemo类:

//..Other Annotation..
@EnableBatchProcessing
public class TaskDemo {
    // ...
}

@EnableBatchProcessing注解启用 Spring Batch 功能,具有设置批处理作业所需的基本配置。

现在,如果我们运行应用程序,@EnableBatchProcessing注解将触发 Spring Batch Job 执行,并且 Spring Cloud Task 将记录所有批处理作业的执行事件以及在springcloud数据库中执行的其他 Task。

5. 从 Stream 启动任务

 

我们可以从 Spring Cloud Stream 触发任务。为了达到这个目的,我们有@EnableTaskLaucnher注释。一次,我们使用 Spring Boot 应用程序添加注释,TaskSink 将可用:

@SpringBootApplication
@EnableTaskLauncher
public class StreamTaskSinkApplication {
    public static void main(String[] args) {
        SpringApplication.run(TaskSinkApplication.class, args);
    }
}

TaskSink从包含 GenericMessage 的流中接收消息,该GenericMessage包含TaskLaunchRequest作为有效负载。然后它触发任务启动请求中提供的基于坐标的任务。

要使TaskSink正常工作,我们需要配置一个实现TaskLauncher接口的 bean 。出于测试目的,我们在这里模拟实现:

@Bean
public TaskLauncher taskLauncher() {
    return mock(TaskLauncher.class);
}

这里需要注意的是,TaskLauncher接口只有在添加了spring-cloud-deployer-local依赖后才可用:

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-deployer-local</artifactId>
    <version>2.3.1.RELEASE</version>
</dependency>

我们可以通过调用Sink接口的输入来测试 Task 是否启动:

 

public class StreamTaskSinkApplicationTests {
   
    @Autowired
    private Sink sink; 
    
    //
}

现在,我们创建一个TaskLaunchRequest实例并将其作为GenericMessage< TaskLaunchRequest >对象的有效负载发送。然后我们可以调用Sink的输入通道,将GenericMessage对象保留在通道中。