Features
本节将更详细地介绍 Spring Cloud Task,包括如何使用、如何配置它以及合适的扩展点。
The lifecycle of a Spring Cloud Task
在大多数情况下,现代云环境是围绕执行预期不会结束的进程而设计的。如果它们结束,通常会重新启动它们。虽然大多数平台确实有一定方式可以运行一个在结束时不会重新启动的进程,但该运行的结果通常不会以可消耗的方式维护。Spring Cloud Task 提供了在环境中执行短期进程并记录结果的能力。通过消息集成任务,这样做允许围绕短期进程以及更长时间运行的服务构建微服务架构。
虽然此功能在云环境中很有用,但同样的问题也可能出现在传统的部署模型中。在使用诸如 cron 之类的调度程序运行 Spring Boot 应用程序时,能够在完成应用程序后监控其结果会很有用。
Spring Cloud Task 采取一种方法,即 Spring Boot 应用程序可以有开始和结束,并且仍然成功。批量应用程序就是一个示例,说明预期结束(并且通常是短期的)的进程如何派上用场。
Spring Cloud Task 记录给定任务的生命周期事件。大多数长时间运行的进程(大多数 web 应用程序的典型特征)不会保存它们的生命周期事件。Spring Cloud Task 核心中的任务会保存。
生命周期包括一个单独的任务执行。这是配置为任务(即它具有 Sprint Cloud Task 依赖项)的 Spring Boot 应用程序的物理执行。
在任务开始时,在运行任何 CommandLineRunner
或 ApplicationRunner
实现之前,将创建 TaskRepository
中记录开始事件的条目。此事件通过 Spring Framework 触发 SmartLifecycle#start
触发。这向系统指示所有 bean 均已准备就绪,并且在运行 Spring Boot 提供的任何 CommandLineRunner
或 ApplicationRunner
实现之前。
任务的记录只在 |
完成 Spring Boot 或 ApplicationContext
的所有 *Runner#run
调用(由 ApplicationFailedEvent
指示)后,任务执行将在存储库中更新结果。
如果应用程序要求任务完成后关闭 |
The TaskExecution
存储在 TaskRepository
中的信息在 TaskExecution
类中建模,并包含以下信息:
Field | Description |
---|---|
|
该任务运行的唯一 ID。 |
|
从 |
|
任务的名称,由配置的 |
|
任务的开始时间,由 |
|
任务完成的时间,由 |
|
退出时可用的任何信息。这可以通过 |
|
如果异常是任务结束的原因(如 |
|
字符串命令行参数的 |
Mapping Exit Codes
任务完成后,它会尝试向操作系统返回退出代码。如果我们看一下我们的 original example,我们可以看到我们无法控制我们应用程序的该方面。因此,如果抛出异常,JVM 会返回一个代码,但该代码对于你的调试来说可能有用或无用。
因此,Spring Boot 提供了一个界面 ExitCodeExceptionMapper
,它允许你将未捕获的异常映射到退出代码。这样做让你能够以退出代码的级别指示出现什么问题。此外,通过这种方式映射退出代码,Spring Cloud Task 记录返回的退出代码。
如果任务以 SIG-INT 或 SIG-TERM 终止,则退出代码为零,除非代码中另有指定。
在任务运行期间,退出代码作为 null 存储在存储库中。任务完成后,将根据本节前面描述的准则存储适当的退出代码。 |
Configuration
Spring Cloud Task 提供了开箱即用的配置,如 DefaultTaskConfigurer
和 SimpleTaskConfiguration
类中定义的配置。本节将介绍默认值以及如何根据需要自定义 Spring Cloud Task。
DataSource
Spring Cloud Task 使用数据源存储任务执行的结果。默认情况下,我们提供 H2 的内存中实例,以提供一种简单的引导开发方法。但是,在生产环境中,你可能希望配置自己的 DataSource
。
如果你的应用只使用一个 DataSource
,既可以用作业务模式,又可以用作任务存储库,那么你只需提供一个 DataSource
(最简单的方式是通过 Spring Boot 的配置约定)。这个 DataSource
会被 Spring Cloud Task 自动用作存储库。
如果你的应用使用多个 DataSource
,则需要使用合适的 DataSource
来配置任务存储库。这种自定义可以通过 TaskConfigurer
的实现来完成。
Table Prefix
TaskRepository
可修改的属性之一是任务表的表前缀。默认情况下,所有前缀都是 TASK_
。TASK_EXECUTION
和 TASK_EXECUTION_PARAMS
就是两个例子。不过,可能出于多种原因需要修改此前缀。如果需要将模式名称添加到表名之前,或者在同一模式中需要多组任务表,你必须更改表前缀。你可以通过将 spring.cloud.task.tablePrefix
设置为所需的表前缀来完成此操作,如下所示:
spring.cloud.task.tablePrefix=yourPrefix
通过使用 spring.cloud.task.tablePrefix
,用户承担责任来创建符合任务表架构标准的任务表,但会做出用户业务需要的一些修改。在创建自己的任务 DDL 时,您可以将 Spring Cloud 任务架构 DDL 用作指南,如 here 所示。
Enable/Disable table initialization
如果你要创建任务表,但不希望 Spring Cloud Task 在任务启动时创建这些表,请将 spring.cloud.task.initialize-enabled
属性设置为 false
,如下所示:
spring.cloud.task.initialize-enabled=false
默认值为 true
。
属性 |
Externally Generated Task ID
在某些情况下,你可能希望允许在请求任务以及基础架构实际启动任务之间的时间差。Spring Cloud Task 让你可以在请求任务时创建 TaskExecution
。然后,将生成 TaskExecution
的执行 ID 传递给任务,以便它可以在任务的生命周期中更新 TaskExecution
。
可以通过调用引用存储 TaskExecution
对象的数据存储的 TaskRepository
实现中的 createTaskExecution
方法来创建一个 TaskExecution
。
为了配置你的任务以使用生成的 TaskExecutionId
,添加如下属性:
spring.cloud.task.executionid=yourtaskId
External Task Id
Spring Cloud Task 让你可以为每个 TaskExecution
存储一个外部任务 ID。为了配置你的任务以使用生成的 TaskExecutionId
,添加如下属性:
spring.cloud.task.external-execution-id=<externalTaskId>
Parent Task Id
Spring Cloud Task 让你可以为每个 TaskExecution
存储一个父任务 ID。例如,执行另一个任务或任务的任务,并且你想要记录哪个任务启动了各个子任务。为了配置你的任务以设置父 TaskExecutionId
,请在子任务中添加如下属性:
spring.cloud.task.parent-execution-id=<parentExecutionTaskId>
TaskConfigurer
TaskConfigurer
是一个策略接口,让你可以自定义配置 Spring Cloud Task 组件的方法。默认情况下,我们提供提供的 DefaultTaskConfigurer
,它提供逻辑默认值:基于 Map
的内存组件(如果未提供 DataSource
,则对开发很有用)和基于 JDBC 的组件(如果 DataSource
可用,则很有用)。
TaskConfigurer
让你可以配置三个主要组件:
Component | Description | Default (provided by DefaultTaskConfigurer ) |
---|---|---|
|
要使用的 |
|
|
用于实现 |
|
|
运行任务更新时要使用的交易管理器。 |
如果使用 |
你可以通过创建 TaskConfigurer
接口的自定义实现来自定义前表中描述的任何组件。通常,扩展 DefaultTaskConfigurer
(在找不到 TaskConfigurer
时提供)并重写所需的 getter 就可以了。不过,这可能还需要从头开始实现你自己的任务。
除非用户正在使用它来提供要作为 Spring Bean 公开的实现,否则不应直接使用 |
Task Execution Listener
TaskExecutionListener
让你可以为任务生命周期中发生的特定事件注册侦听器。要进行此操作,请创建一个实现 TaskExecutionListener
接口的类。实现 TaskExecutionListener
接口的类会收到以下事件的通知:
-
onTaskStartup
:在TaskRepository
中存储TaskExecution
之前。 -
onTaskEnd
:在TaskRepository
中更新TaskExecution
条目之前,并标记任务的最终状态。 -
onTaskFailed
:在任务抛出未处理异常时调用onTaskEnd
方法之前。
Spring Cloud Task 也允许您使用以下方法注释将 TaskExecution
事件侦听器添加到 bean 中的方法:
-
@BeforeTask
:在TaskRepository
中存储TaskExecution
之前。 -
@AfterTask
:在TaskRepository
中更新TaskExecution
条目之前,并标记任务的最终状态。 -
@FailedTask
:在任务抛出未处理异常时调用@AfterTask
方法之前。
以下示例展示了三种注释的用法:
public class MyBean {
@BeforeTask
public void methodA(TaskExecution taskExecution) {
}
@AfterTask
public void methodB(TaskExecution taskExecution) {
}
@FailedTask
public void methodC(TaskExecution taskExecution, Throwable throwable) {
}
}
在链中插入早于 |
Exceptions Thrown by Task Execution Listener
如果 TaskExecutionListener
事件处理程序引发异常,则该事件处理程序的所有侦听器处理将停止。例如,如果三个 onTaskStartup
侦听器已经启动,并且第一个 onTaskStartup
事件处理程序引发异常,则不会调用其他两个 onTaskStartup
方法。但是,TaskExecutionListeners
的其他事件处理程序(onTaskEnd
和 onTaskFailed
)将被调用。
由 TaskExecutionListener`事件处理程序抛出异常时返回的退出代码是 ExitCodeEvent 报告的退出代码。如果没有发出 `ExitCodeEvent
,则会评估抛出的异常以查看它是否为 ExitCodeGenerator 类型。如果是,则它返回来自 ExitCodeGenerator
的退出代码。否则,返回 1
。
如果在 onTaskStartup
方法中引发异常,则该应用程序的退出代码将为 1
。如果在 onTaskEnd
或 onTaskFailed
方法中引发异常,则该应用程序的退出代码将是使用上述规则确立的代码。
如果在 |
Exit Messages
您可以使用 TaskExecutionListener
以编程方式设置任务的退出消息。这是通过设置 TaskExecution’s
exitMessage
完成的,然后将其传递给 TaskExecutionListener
。以下示例展示了使用 @AfterTask
ExecutionListener
注释的方法:
@AfterTask
public void afterMe(TaskExecution taskExecution) {
taskExecution.setExitMessage("AFTER EXIT MESSAGE");
}
可以在任何侦听器事件(onTaskStartup
、onTaskFailed
和 onTaskEnd
)设置 ExitMessage
。三个侦听器的优先级顺序如下:
-
onTaskEnd
-
onTaskFailed
-
onTaskStartup
例如,如果您为 onTaskStartup
和 onTaskFailed
侦听器设置了 exitMessage
,并且任务在没有失败的情况下结束,则来自 onTaskStartup
的 exitMessage
将存储在存储库中。否则,如果发生故障,则来自 onTaskFailed
的 exitMessage
将被存储。此外,如果您使用 onTaskEnd
侦听器设置了 exitMessage
,则来自 onTaskEnd
的 exitMessage
将取代来自 onTaskStartup
和 onTaskFailed
的退出消息。
Restricting Spring Cloud Task Instances
Spring Cloud Task 允许您确定一次只能运行一个具有给定任务名称的任务。为此,您需要为每个任务执行建立 features-task-name 并在 cloud-task 中设置 spring.cloud.task.single-instance-enabled=true
。虽然第一个任务执行正在运行,但您尝试重新运行具有相同 features-task-name 和 spring.cloud.task.single-instance-enabled=true
的任务的任何其他时间,则该任务将失败,并出现以下错误消息:Task with name "application" is alreadyrunning.
spring.cloud.task.single-instance-enabled
的默认值为 false
。以下示例展示了如何将 spring.cloud.task.single-instance-enabled
设置为 true
:
spring.cloud.task.single-instance-enabled=true or false
要使用此功能,您必须将以下 Spring Integration 依赖项添加到应用程序:
<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。 |
Single Instance Usage for Spring AOT And Native Compilation
在创建原生编译应用程序时要使用 Spring Cloud Task 的单实例功能,您需要在构建时启用该功能。为此,请添加 process-aot 执行,并按照以下步骤将 spring.cloud.task.single-step-instance-enabled=true
设置为 JVM 参数:
<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>
Enabling Observations for ApplicationRunner and CommandLineRunner
要为 ApplicationRunner
或 CommandLineRunner
启用任务观察,请将 spring.cloud.task.observation.enabled
设置为 true。
带观测功能的示例任务应用程序允许使用 SimpleMeterRegistry
可在 here 中找到。
Disabling Spring Cloud Task Auto Configuration
如果 Spring Cloud Task 不应针对某个实现进行自动配置,则可以禁用任务的自动配置。这可以通过将以下注释添加到您的任务应用程序来实现:
@EnableAutoConfiguration(exclude={SimpleTaskAutoConfiguration.class})
您还可以通过将 spring.cloud.task.autoconfiguration.enabled
属性设置为 false
来禁用 Task 自动配置。
Closing the Context
如果应用程序需要在任务完成后关闭 ApplicationContext
(所有 *Runner#run
方法都已调用并且任务存储库已更新),请将属性 spring.cloud.task.closecontextEnabled
设置为 true
。
关闭上下文的另一个情况是当任务执行完成但应用程序未终止时。在这些情况下,上下会保持开启状态,因为已分配了一个线程(例如:如果您正在使用 TaskExecutor)。在这些情况下,请在启动任务时将 spring.cloud.task.closecontextEnabled
属性设置为 true
。这将在任务完成后关闭应用程序的上下文。从而允许应用程序终止。
Enable Task Metrics
Spring Cloud Task 与 Micrometer 集成,并为它执行的任务创建观察。要启用任务可观察性集成,您必须将 spring-boot-starter-actuator
、您首选的注册表实现(如果您要发布指标)和 micrometer-tracing(如果您要发布跟踪数据)添加到您的任务应用程序。使用 Influx 启用任务可观察性和指标的一组示例 Maven 依赖项如下:
<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>