Task 生命周期

在深入了解创建任务的细节之前,我们需要了解Spring Cloud Data Flow环境中任务的典型生命周期:

1. 创建 Task Applications

虽然Spring Cloud Task确实提供了许多开箱即用的应用程序(在spring-cloud-task-app-starters),但大多数任务应用程序都需要自定义开发。要创建自定义任务应用程序:

  1. 使用Spring Initializer创建一个新项目,确保选择以下启动器:

    1. Cloud Task:依赖是基于spring-cloud-starter-task

    2. JDBC:依赖是基于spring-jdbc

    3. Select your database dependency:选择Data Flow Stream 当前使用的数据库依赖关系。例如:H2

  2. 在新项目中,创建一个新的 Class 作为主类,如下所示:

    @EnableTask
    @SpringBootApplication
    public class MyTask {
        public static void main(String[] args) {
    		SpringApplication.run(MyTask.class, args);
    	}
    }
  3. 您的应用程序中需要一个或多个CommandLineRunnerApplicationRunner实现,才可以使用这个类。您既可以实现自己的,也可以使用Spring Boot提供的。

  4. 使用Spring Boot将应用程序打包到一个über jar中是依照 Spring Boot conventions 标准。打包的 Applicaions 可以注册和部署,如下所示

1.1. Task 数据库配置

启动 Tasp Applications 时,请确保Spring Cloud Data Flow使用的数据库驱动程序在 Applications 中也同时进行了配置。例如,如果您的Spring Cloud Data Flow设置为使用Postgresql,请确保Task Applications 也配置了Postgresql依赖。

当您在外部运行 Task (即从命令行),并且希望Spring Cloud Data Flow 在其UI中显示任务执行时,请确保两者使用的是同一个数据源。默认情况下,Spring Cloud Task 使用一个本地H2实例,并将执行记录到 Spring Cloud Data Flow 使用的数据库中。

2 注册 Task Applications

您可以在Spring Cloud Data Flow Shell 中使用 app register命令向App Registry注册 Task Applications 。您必须提供一个唯一的 Name 和一个可以解析为 Applications 的URI。对于 Type ,请指定为"task"。下面的列表显示了三个例子:

dataflow:>app register --name task1 --type task --uri maven://com.example:mytask:1.0.2

dataflow:>app register --name task2 --type task --uri file:///Users/example/mytask-1.0.2.jar

dataflow:>app register --name task3 --type task --uri https://example.com/mytask-1.0.2.jar

maven模式下提供URI时,格式应符合以下要求:

maven://<groupId>:<artifactId>[:<extension>[:<classifier>]]:<version>

如果您想一次注册多个应用程序,可以将它们存储在属性文件中,其中Key的格式为<type>.<name>,值为URI。例如:

task.foo=file:///tmp/foo-1.2.1.BUILD-SNAPSHOT.jar
task.bar=file:///tmp/bar-1.2.1.BUILD-SNAPSHOT.jar

然后,您可以使用app import命令并使用通过--uri指定属性文件的位置,如下所示:

app import --uri file:///tmp/task-apps.properties

为了方便起见,我们为所有开箱即用的 Task Applications Starts 提供了带有Applications URI(maven和docker都适用)的静态文件。您可以指向此文件并批量导入所有 Applications URI。否则,如本章前面所述,您可以单独注册它们,或者拥有您自己的自定义属性文件,其中只包含所需的 Applications URI。建议在自定义文件中将Applications 集中在列表中。

下表列出了可用的静态属性文件:

例如,如果你想批量注册所有开箱即用的Task Applications ,你可以使用以下命令:

dataflow:>app import \
--uri https://dataflow.spring.io/Dearborn-SR1-task-applications-maven

您还可以设置--local选项(默认情况下为TRUE)以指示是否应在shell进程本身内解析属性文件。如要从 Data Flow Server 解析位置,请指定--localfalse

使用app register或时app import,如果Task Applications 提供了一个已经注册过的 Name 和 Version ,则默认情况下不会覆盖它。如果要更换其他uri或者uri-metadata位置覆盖已经注册过的Task Applications,请设置--force选项。

在某些情况下,资源在服务器端解析。在其他情况下,URI被传递给运行时容器实例,并在其中解析它。有关详细信息,请参阅 Data Flow Server 的文档。

3. 创建 Task Definition

通过提供应用于 Task 的 --definition 执行的参数,可以从Task Applications 创建 Task Definition 。可以通过 RESTful API 或 shell 创建Task Definition 。要使用 shell 创建 Task Definition ,可以使用task create命令创建Task Definition,如下例所示:

dataflow:>task create mytask --definition "timestamp --format=\"yyyy\""
Created new task 'mytask'

Task Definition 的列表可以通过RESTful API或shell获得。要使用shell获取 Task Definition 列表,请使用task list命令。

4. 启动 Task

可以通过RESTful API或shell启动一个临时任务。要通过shell启动一个的任务,可以使用task launch命令,如下面的示例所示:

dataflow:>task launch mytask
Launched task 'mytask'

当 Task 启动时,可以在启动时设置arguments作为命令行参数传递给Task Applications 任何属性,如下:

dataflow:>task launch mytask --arguments "--server.port=8080 --custom=value"

参数需要使用space分隔值。

可以通过使用——properties属性对TaskLauncher进行配置。该属性的格式是以逗号分隔的字符串,前缀为app..。作为Applications 属性传递给 TaskLauncher。如何将它们如何传递到 Task Applications 是取决于如何部署实现的。如果属性的前缀是deployer而不是app,那么它将作为部署时的属性传递给TaskLauncher

dataflow:>task launch mytask --properties "deployer.timestamp.custom1=value1,app.timestamp.custom2=value2"

4.1. Application properties

每个 Applications 都可以自定义配置 peoperties。例如,timestamp可以设置 format 属性进行格式化输出的默认值配置。

dataflow:> task create \
--definition "timestamp --format=\"yyyy\"" \
--name printTimeStamp

这个timestamp配置方式实际上和timestamp.format配置相同 。Data Flow 新增简写形式方式format而未使用timestamp.format。同样也可以使用longhand版本,如以下示例所示:

dataflow:> task create \
--definition "timestamp --timestamp.format=\"yyyy\"" \
--name printTimeStamp

这个简写行为将在 Whitelisting application properties 一节中进行更多讨论。如果使用 registered application property metadata ,则可以使用shell中的 tab 功能获取候选属性名称列表,输入-- 后按tab

shell为应用程序属性提供了Tab补全。shell命令 app info --name <appName> --type <appType> 可以提示所有支持的文档。

<appType> 支持的配置为 task

4.2. 公共 Application properties

除了通过 DSL 进行配置之外,Spring Cloud Data Flow 还提供了一种机制,用于为其启动的所有Task Applications 设置公共属性。可以通过添加spring.cloud.dataflow.applicationProperties.task来完成。在通过Data Flow Server 服务启动 Applications 时,会将所有属性传递给启动实例。

例如,通过使用以下选项启动 Data Flow server ,可以将所有已启动的Applications 配置属性prop1prop2:

--spring.cloud.dataflow.applicationProperties.task.prop1=value1
--spring.cloud.dataflow.applicationProperties.task.prop2=value2

将导致属性,prop1=value1prop2=value2传递给所有已启动的Applications。

此机制配置的属性优先级低于 Task 部署时的属性。如果在Task 启动时指定具有相同键的属性,则会被部署时属性值覆盖。

4.5. Task 启动时的最大并发限制

Spring Cloud Data Flow允许用户为每个平台限制最大并发运行Task 数,以防止IaaS /硬件资源饱和。默认情况下,所有平台的限制都被设置为20。如果平台实例上并发运行的 Task 数量大于或等于限制,则下一个任务启动请求会失败,并将通过RESTful API、Shell或UI返回一条错误消息。可以通过设置相应的部署属性配置spring.cloud.dataflow.task.platform.<platform-type>.accounts[<account-name>].maximum-concurrent-tasks 来为平台实例配置此限制,其中<account-name>是平台名称(如果没有则为默认值 default)。<platform-type>指当前的部署模式:localcloudfoundrykubernetes

每平台的 TaskLauncher 实现可以通过查询底层平台(如果可行)的运行时状态来确定当前正在执行的 Task 的数量。每个平台都有不同的方式来区分 Task

例如,在本地主机上启动任务使用LocalTaskLauncher。LocalTask​​Launcher 为每个启动的请求创建一个进程,并在内存中跟踪这些进程。在这种情况下,我们不会查询底层操作系统,因为这种识别 Task 的方式是不可行的。

对于Cloud Foundry,Task 是其部署模型所支持的核心。所有 Task 的运行中,完成或失败状态均可通过API直接获得。这意味着对应帐户或组织的空间下,每个正在运行的 Task 容器都会统计进入运行中的计数器中,无论它是使用Spring Cloud Data Flow启动还是CloudFoundryTaskLauncher直接调用。

对于Kubernetes,通过KubernetesTaskLauncher启动一个任务,如果成功,将会运行一个pod,我们希望它能够返最终完成或者失败的状态。但是在这种环境中,通常下没有简单的方法来识别和 Task 相对应的pod。出于这个原因,我们只统计由KubernetesTaskLauncher启动的pod。Task 启动器在pod的元数据中可以设计标签task-name,因此我们会根据此标签的内容过滤所有正在运行的pod。

4.6. Reviewing Task Executions

一旦启动Task ,它的状态就会在数据库中存储下来。其中包括:

  • Task Name

  • Start Time

  • End Time

  • Exit Code

  • Exit Message

  • Last Updated Time

  • Parameters

用户可以通过 RESTful API 或 shell 检查任务执行的状态。要通过shell显示最新的任务执行情况,请使用task execution list命令。

如果要指定获取一个 task definition 的执行列表,请添加--name参数指定名称task execution list --name foo。要查询任务执行的详细信息,请使用task execution status 并且指定Task id,task execution status --id 549

4.7. Destroying a Task Definition

销毁 Task Definition 会从对应的数据库中删除该定义。这可以通过RESTful API或shell来完成。要通过shell销毁Task ,请使用该task destroy命令,如以下示例所示:

dataflow:>task destroy mytask
Destroyed task 'mytask'

要通过shell销毁所有任务,请使用task all destroy以下示例中所示的命令:

dataflow:>task all destroy
Really destroy all tasks? [y, n]: y
All tasks destroyed

或者使用force命令:

dataflow:>task all destroy --force
All tasks destroyed

任务的启动以及执行信息仍会保存在数据库中。

Destroying 命令不会使运行中的 Task 停止,但是,它会从数据库中删除 task definition

Task destroy <task-name>仅删除定义,而不会删除部署在Cloud Foundry上的 Task 。要实现这一点的唯一方法是通过CLI分为两个步骤。首先,使用cf apps命令获取Task 列表。识别要删除的 Task ,并运行cf delete 命令。

4.8. Validating a Task

有时,在注册 Applications 时,task definition 中会包含一个或多个Application ,其中包含无效的URI。这可能是由于在 app 注册时输入的URI无效,或者 app 已经从存储库中移除。要验证 Task 中包含的所有Applications URL是否用,应使用validate命令。例如:

dataflow:>task validate time-stamp
╔══════════╤═══════════════╗
║Task Name │Task Definition║
╠══════════╪═══════════════╣
║time-stamp│timestamp      
╚══════════╧═══════════════╝


time-stamp is a valid task.
╔═══════════════╤═════════════════╗
   App Name    │Validation Status║
╠═══════════════╪═════════════════╣
║task:timestamp │valid            
╚═══════════════╧═════════════════╝

在上面的示例中,我们验证 Task time-stamp 。我们看到task:timestamp Applications 是有效的。现在让我们看看如果我们有一个带有无效URI的注册 Applications 的会如何。

dataflow:>task validate bad-timestamp
╔═════════════╤═══════════════╗
  Task Name  │Task Definition║
╠═════════════╪═══════════════╣
║bad-timestamp│badtimestamp   
╚═════════════╧═══════════════╝


bad-timestamp is an invalid task.
╔══════════════════╤═════════════════╗
     App Name     │Validation Status║
╠══════════════════╪═════════════════╣
║task:badtimestamp │invalid          
╚══════════════════╧═════════════════╝

在这种情况下,Spring Cloud Data Flow 提示 invalid,因为task:badtimestamp 的 URI 是错误的。

Last updated