对于最新稳定版本,请使用 spring-cloud-task 5.0.1!spring-doc.cadn.net.cn

功能

本部分将更详细地介绍 Spring Cloud Task,包括如何使用它、如何配置它以及适当的扩展点。spring-doc.cadn.net.cn

Spring Cloud 任务生命周期

在大多数情况下,现代云环境都是围绕那些不期望结束的进程的执行来设计的。如果它们结束,通常会被重启。虽然大多数平台都有某种方式可以运行一个在结束时不重启的进程,但该运行的结果通常不会以可消费的方式进行保留。Spring Cloud Task 提供了在环境中执行短生命周期进程并记录结果的能力。这样做允许围绕短生命周期进程构建微服务架构,同时通过通过消息集成任务,也支持更长时间运行的服务。spring-doc.cadn.net.cn

在云环境中这种功能很有用,同样的问题在传统部署模型中也会出现。当使用如 cron 的调度程序运行 Spring Boot 应用程序时,能够监控任务完成后应用程序的结果是有用的。spring-doc.cadn.net.cn

Spring Cloud Task 采取的方法是,一个 Spring Boot 应用程序可以有开始和 结束,并依然成功。批处理应用是进程被期望有结束(且通常生命周期较短)的一个例子, 这些过程可以发挥重要作用。spring-doc.cadn.net.cn

Spring Cloud Task 记录给定任务的生命周期事件。大多数长时间运行的过程,以大多数 Web 应用程序为代表,都不保存其生命周期事件。而 Spring Cloud Task 的任务核心正是如此。spring-doc.cadn.net.cn

生命周期由单个任务执行组成。这是配置为任务的Spring Boot应用程序(即,它具有Sprint Cloud Task依赖项)的一个物理执行。spring-doc.cadn.net.cn

在任务开始时,在任何 CommandLineRunnerApplicationRunner 的实现运行之前,会创建一个在 TaskRepository 中记录开始事件的条目。此事件通过 SmartLifecycle#start 被 Spring 框架触发,这向系统表明所有 beans 都已准备好使用,并在运行任何 CommandLineRunnerApplicationRunner 由 Spring Boot 提供的实现之前发生。spring-doc.cadn.net.cn

任务记录仅在成功启动上下文(ApplicationContext)时发生。如果上下文根本无法启动,该任务的运行将不被记录。

在完成来自Spring Boot的所有的*Runner#run调用,或在某个ApplicationContext(通过ApplicationFailedEvent指示)失败时,任务执行结果将更新到仓库中。spring-doc.cadn.net.cn

如果应用程序在任务完成时(所有*Runner#run方法均已调用且任务仓库已更新)需要将ApplicationContext关闭,则将属性spring.cloud.task.closecontextEnabled设置为true。

任务执行

存储在 TaskRepository 中的信息在 TaskExecution 类中建模,并 包含以下信息:spring-doc.cadn.net.cn

字段 描述

executionidspring-doc.cadn.net.cn

任务运行的唯一ID。spring-doc.cadn.net.cn

exitCodespring-doc.cadn.net.cn

ExitCodeExceptionMapper实现生成的退出代码。如果没有生成退出代码但抛出ApplicationFailedEvent,则设置为1。否则,假设为0。spring-doc.cadn.net.cn

taskNamespring-doc.cadn.net.cn

为该任务确定的名称,由配置的TaskNameResolver决定。spring-doc.cadn.net.cn

startTimespring-doc.cadn.net.cn

开始该任务的时间,如由SmartLifecycle#start调用所指示的。spring-doc.cadn.net.cn

endTimespring-doc.cadn.net.cn

完成该任务的时间,如由ApplicationReadyEvent所指示的。spring-doc.cadn.net.cn

exitMessagespring-doc.cadn.net.cn

在退出时可用的任何信息。这可以通过程序设置为一个 TaskExecutionListenerspring-doc.cadn.net.cn

errorMessagespring-doc.cadn.net.cn

如果异常导致任务结束(如由一个 ApplicationFailedEvent 所指示),则该异常的堆栈跟踪将存储在此处。spring-doc.cadn.net.cn

argumentsspring-doc.cadn.net.cn

一个作为传递到可执行文件的启动应用程序的命令行参数字符串的 Listspring-doc.cadn.net.cn

映射退出码

当任务完成时,它会尝试向操作系统返回一个退出码。如果我们查看我们原始示例,可以看到我们并未在应用程序中控制这一方面。因此,如果抛出异常,JVM 返回的代码可能对您调试并无帮助。spring-doc.cadn.net.cn

consequently,Spring Boot 提供了一个接口,ExitCodeExceptionMapper,让你 可以将未捕获的异常映射到退出码。这样做让你能够在退出码的层面表明发生了什么问题。此外,通过以这种方式映射退出码,Spring Cloud Task 会记录返回的退出码。spring-doc.cadn.net.cn

如果任务以SIG-INT或SIG-TERM终止,除非在代码中另有特别说明,否则退出代码为零。spring-doc.cadn.net.cn

在任务运行时,退出码会被存储为 null。 在任务完成后,会根据本节前面描述的指南存储适当的退出码。

配置

Spring Cloud Task 提供了如在 DefaultTaskConfigurerSimpleTaskConfiguration 类中定义的即开即用配置。本节将演示默认配置以及如何根据您的需求自定义 Spring Cloud Task。spring-doc.cadn.net.cn

数据源

Spring Cloud Task 使用数据源来存储任务执行的结果。默认情况下,我们提供一个内建的 H2 数据库实例,以提供一种简单的开发启动方法。然而,在生产环境中,你可能希望配置你自己的 DataSourcespring-doc.cadn.net.cn

如果您的应用程序只使用一个 DataSource,并且该 DataSource 同时作为您的业务 模式和任务存储库,您只需要提供任何 DataSource(最简单的方法是通过 Spring Boot 的配置约定)。此 DataSource 将由 Spring Cloud Task 用于存储库。spring-doc.cadn.net.cn

如果您的应用程序使用了多个 DataSource,就需要通过实现 TaskConfigurer 来配置任务 仓库的适当 DataSourcespring-doc.cadn.net.cn

表前缀

TaskRepository 的一个可修改属性是任务表的前缀。默认情况下,所有任务表都以 TASK_ 为前缀。TASK_EXECUTIONTASK_EXECUTION_PARAMS 是两个示例。然而,有潜在原因需要修改此前缀。如果模式名需要加到表名前面,或者在同一模式中需要多个任务表集,则必须更改表前缀。可以通过将 spring.cloud.task.tablePrefix 设置为你需要的前缀来实现,如下所示:spring-doc.cadn.net.cn

spring.cloud.task.tablePrefix=yourPrefixspring-doc.cadn.net.cn

通过使用 spring.cloud.task.tablePrefix,用户需承担创建符合任务表模式标准但根据其业务需求进行修改的任务表的职责。 您可以利用 Spring Cloud Task 模式 DDL 作为创建您自己的 Task DDL 的参考,如在 此处 所示。spring-doc.cadn.net.cn

启用/禁用表格初始化

在创建任务表且不希望Spring Cloud Task在任务启动时创建的情况下,将spring.cloud.task.initialize-enabled属性设置为false,如下所示:spring-doc.cadn.net.cn

spring.cloud.task.initialize-enabled=falsespring-doc.cadn.net.cn

它默认值为 truespring-doc.cadn.net.cn

属性 spring.cloud.task.initialize.enable 已被弃用。

外部生成的任务ID

在某些情况下,您可能希望允许从请求任务到基础设施实际启动任务之间的时间差。Spring Cloud Task 允许您在请求任务时创建一个TaskExecution,然后将生成的TaskExecution的执行ID传递给任务,以便任务可以通过其生命周期更新TaskExecutionspring-doc.cadn.net.cn

一个TaskExecution可以通过在对createTaskExecution方法的调用创建,该调用是在一个实现了TaskRepository并引用了持有TaskExecution对象的数据存储的实例上进行的。spring-doc.cadn.net.cn

为了将您的任务配置为使用生成的 TaskExecutionId,请添加以下属性:spring-doc.cadn.net.cn

spring.cloud.task.executionid=yourtaskIdspring-doc.cadn.net.cn

外部任务ID

Spring Cloud Task 允许为每个 TaskExecution 存储一个外部任务ID。为了将您的任务配置为使用生成的 TaskExecutionId,请添加以下属性:spring-doc.cadn.net.cn

spring.cloud.task.external-execution-id=<externalTaskId>spring-doc.cadn.net.cn

父任务ID

Spring Cloud Task 允许为每个 TaskExecution 存储一个父任务ID。例如,一个执行其他任务或多个任务的任务,你想要记录是哪个任务启动了每个子任务。为了配置你的任务在子任务中设置一个父 TaskExecutionId,请在子任务中添加以下属性:spring-doc.cadn.net.cn

spring.cloud.task.parent-execution-id=<parentExecutionTaskId>spring-doc.cadn.net.cn

任务配置器

The TaskConfigurer is a strategy interface that lets you customize the way components of Spring Cloud Task are configured. By default, we provide the DefaultTaskConfigurer that provides logical defaults: Map-based in-memory components (useful for development if no DataSource is provided) and JDBC based components (useful if there is a DataSource available).spring-doc.cadn.net.cn

The TaskConfigurer lets you configure three main components:spring-doc.cadn.net.cn

组件 描述 默认(由 DefaultTaskConfigurer 提供)

TaskRepositoryspring-doc.cadn.net.cn

The implementation of the TaskRepository to be used.spring-doc.cadn.net.cn

SimpleTaskRepositoryspring-doc.cadn.net.cn

TaskExplorerspring-doc.cadn.net.cn

The implementation of the TaskExplorer(一个用于只读访问任务 仓库的组件)to be used.spring-doc.cadn.net.cn

SimpleTaskExplorerspring-doc.cadn.net.cn

PlatformTransactionManagerspring-doc.cadn.net.cn

一个用于在运行更新任务时使用的事务管理器。spring-doc.cadn.net.cn

JdbcTransactionManager 如果使用了 DataSourceResourcelessTransactionManager 如果没有使用。spring-doc.cadn.net.cn

You can customize any of the components described in the preceding table by creating a custom implementation of the TaskConfigurer interface. 通常,通过扩展 DefaultTaskConfigurer(如果未找到TaskConfigurer则提供)并重写所需的getter方法就足够。但是,从零开始实现可能也是必需的。spring-doc.cadn.net.cn

用户不应直接使用从 TaskConfigurer 提供的获取器(getter)方法, 除非他们将其用作要暴露为 Spring Beans 的实现。

任务执行监听器

TaskExecutionListener 可让您注册在任务生命周期中特定事件的监听器。为此,创建一个实现 TaskExecutionListener 接口的类。实现 TaskExecutionListener 接口的类会接收到以下事件:spring-doc.cadn.net.cn

  • onTaskStartup: 在将 TaskExecution 存储到 TaskRepository 之前。spring-doc.cadn.net.cn

  • onTaskEnd: 在更新 TaskExecution 条目(在 TaskRepository 中) 并标记任务的最终状态之前。spring-doc.cadn.net.cn

  • onTaskFailed: 在 onTaskEnd 方法被调用之前,当任务抛出未处理的异常时。spring-doc.cadn.net.cn

Spring Cloud Task 也允许你通过使用以下方法注解,向 bean 内部方法添加 TaskExecution 监听器spring-doc.cadn.net.cn

以下示例展示了三个注解的使用:spring-doc.cadn.net.cn

 public class MyBean {

	@BeforeTask
	public void methodA(TaskExecution taskExecution) {
	}

	@AfterTask
	public void methodB(TaskExecution taskExecution) {
	}

	@FailedTask
	public void methodC(TaskExecution taskExecution, Throwable throwable) {
	}
}
Inserting an ApplicationListener earlier in the chain than TaskLifecycleListener exists may cause unexpected effects.

任务执行监听器抛出的异常

If 一个异常被一个 TaskExecutionListener 事件处理器抛出,那么该事件处理器的所有监听器处理将停止。例如,如果有三个 onTaskStartup 监听器,当第一个 onTaskStartup 事件处理器抛出异常时,其他两个 onTaskStartup 方法不会被调用。然而,该事件的其他事件处理器(onTaskEndonTaskFailed)会被调用。spring-doc.cadn.net.cn

当在 TaskExecutionListener 事件处理程序中抛出异常时,返回的退出码是 ExitCodeEvent 报告的退出码。 如果未发出 ExitCodeEvent,则评估所抛出的异常是否为类型 ExitCodeGenerator。 如果是,则返回从 ExitCodeGenerator 获取的退出码;否则返回 1spring-doc.cadn.net.cn

onTaskStartup 方法中如果抛出异常,应用程序的退出代码将为 1。 如果在 onTaskEndonTaskFailed 方法中抛出异常,应用程序的退出代码将根据上述规则确定。spring-doc.cadn.net.cn

onTaskStartuponTaskEndonTaskFailed 引发异常的情况下,无法使用 ExitCodeExceptionMapper 重写应用程序的退出代码。

退出信息

您可以设置一个任务退出消息的方式是通过使用一个TaskExecutionListener。这是通过设置TaskExecution’s exitMessage,然后将其传递给TaskExecutionListener来完成的。以下示例显示了一个带有@AfterTask ExecutionListener注解的方法 :spring-doc.cadn.net.cn

@AfterTask
public void afterMe(TaskExecution taskExecution) {
    taskExecution.setExitMessage("AFTER EXIT MESSAGE");
}

一个 ExitMessage 可以在任何监听器事件 (onTaskStartup, onTaskFailed,和 onTaskEnd) 上设置。三个监听器的优先级顺序如下:spring-doc.cadn.net.cn

例如,如果你将 exitMessage 设置为 onTaskStartuponTaskFailed 监听器的参数,且任务在不失败的情况下结束,那么 exitMessageonTaskStartup 会存储到仓库中。否则,如果发生失败,那么 exitMessageonTaskFailed 会被存储。另外,如果你将 exitMessage 与一个 onTaskEnd 监听器设置,那么 exitMessageonTaskEnd 会取代 onTaskStartuponTaskFailed 的退出消息。spring-doc.cadn.net.cn

限制 Spring Cloud Task 实例

Spring Cloud Task 让你确保同一时间只运行一个具有给定任务名称的任务。为此,你需要建立一个任务名称,并为每个任务执行设置spring.cloud.task.single-instance-enabled=true。当第一个任务执行在运行时,任何其他时间尝试使用相同的任务名称spring.cloud.task.single-instance-enabled=true运行任务时,任务会抛出以下错误消息:Task with name "application" is already running. 默认值对于spring.cloud.task.single-instance-enabledfalse。以下示例展示了如何将spring.cloud.task.single-instance-enabled设置为truespring-doc.cadn.net.cn

spring.cloud.task.single-instance-enabled=true or falsespring-doc.cadn.net.cn

要使用此功能,您必须将以下 Spring 集成依赖项添加到您的 应用程序:spring-doc.cadn.net.cn

<dependency>
    <groupId>org.springframework.integration</groupId>
    <artifactId>spring-integration-core</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.integration</groupId>
    <artifactId>spring-integration-jdbc</artifactId>
</dependency>
如果该功能已启用且另一个具有相同任务名称的任务正在运行,则应用程序的退出代码将为1。

单例使用用于 Spring AOT 与原生编译

要使用 Spring Cloud Task 的单实例功能(在创建原生编译应用程序时),需要在构建时启用该功能。 为此,请添加 process-aot 执行并设置 JVM 参数为 0,如下所示:spring-doc.cadn.net.cn

<plugin>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-maven-plugin</artifactId>
    <executions>
        <execution>
            <id>process-aot</id>
            <goals>
                <goal>process-aot</goal>
            </goals>
            <configuration>
                <jvmArguments>
                    -Dspring.cloud.task.single-instance-enabled=true
                </jvmArguments>
            </configuration>
        </execution>
    </executions>
</plugin>

启用 ApplicationRunner 和 CommandLineRunner 的 Observations

To Enable Task Observations for ApplicationRunnerCommandLineRunner set spring.cloud.task.observation.enabled to true.spring-doc.cadn.net.cn

一个示例任务应用程序使用观察功能,可以使用SimpleMeterRegistry,可在此处找到。spring-doc.cadn.net.cn

禁用 Spring Cloud Task 自动配置

在Spring Cloud Task不应为实现自动配置的情况下,可以禁用Task的自动配置。 这可以通过在您的Task应用程序中添加以下注解来完成:spring-doc.cadn.net.cn

@EnableAutoConfiguration(exclude={SimpleTaskAutoConfiguration.class})

你也可以通过将spring.cloud.task.autoconfiguration.enabled属性设置为false来禁用任务自动配置。spring-doc.cadn.net.cn

关闭上下文

如果应用程序需要在任务完成后关闭 ApplicationContext(所有 *Runner#run 方法都已调用且任务 仓库已更新),请将属性 spring.cloud.task.closecontextEnabled 设置为 truespring-doc.cadn.net.cn

另一个需要关闭上下文的情况是在任务执行完成后,但应用程序并未终止。在这种情况下,由于分配了线程(例如:使用TaskExecutor),上下文会被保持打开。在这种情况下,启动任务时将spring.cloud.task.closecontextEnabled属性设置为true。这样在任务完成后将关闭应用程序的上下文,从而允许应用程序终止。spring-doc.cadn.net.cn

启用任务指标

Spring Cloud Task 集成 Micrometer,并为它执行的 Tasks 创建观测数据。 要启用 Task Observability 集成,你必须在你的任务应用程序中添加 spring-boot-starter-actuator,你首选的注册表实现(如果你希望发布指标),以及 micrometer-tracing(如果你希望发布追踪数据)。 一个使用 Influx 启用任务可观测性和指标的 Maven 依赖集例如:spring-doc.cadn.net.cn

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
    <groupId>io.micrometer</groupId>
    <artifactId>micrometer-registry-influx</artifactId>
    <scope>runtime</scope>
</dependency>

Spring 任务与 Spring Cloud 任务属性

术语 task 在行业中经常作为单词使用。例如,Spring Boot 提供了 spring.task,而 Spring Cloud Task 提供了 spring.cloud.task 属性。 这在过去引起了一些混淆,即这两组属性是否直接相关。然而,它们代表了 Spring 生态系统中提供的两个不同的功能集。spring-doc.cadn.net.cn