> For the complete documentation index, see [llms.txt](https://cxz.gitbook.io/spring-cloud-date-flow/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://cxz.gitbook.io/spring-cloud-date-flow/tasks/task-sheng-ming-zhou-qi.md).

# Task 生命周期

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

1. [创建 Task Applications](https://docs.spring.io/spring-cloud-dataflow/docs/2.1.0.RELEASE/reference/htmlsingle/#spring-cloud-dataflow-create-task-apps)
2. [注册 Task Applications](https://docs.spring.io/spring-cloud-dataflow/docs/2.1.0.RELEASE/reference/htmlsingle/#spring-cloud-dataflow-register-task-apps)
3. [创建 Task Definition](https://docs.spring.io/spring-cloud-dataflow/docs/2.1.0.RELEASE/reference/htmlsingle/#spring-cloud-dataflow-create-task-definition)
4. [启动 Task](https://docs.spring.io/spring-cloud-dataflow/docs/2.1.0.RELEASE/reference/htmlsingle/#spring-cloud-dataflow-task-launch)
5. [检查 Task执行](https://docs.spring.io/spring-cloud-dataflow/docs/2.1.0.RELEASE/reference/htmlsingle/#spring-cloud-dataflow-task-review-executions)
6. [销毁 Task Definition](https://docs.spring.io/spring-cloud-dataflow/docs/2.1.0.RELEASE/reference/htmlsingle/#spring-cloud-dataflow-task-definition-destroying)

## 1. 创建 Task Applications

虽然Spring Cloud Task确实提供了许多开箱即用的应用程序（在[spring-cloud-task-app-starters](https://github.com/spring-cloud-task-app-starters)），但大多数任务应用程序都需要自定义开发。要创建自定义任务应用程序：

1. 使用[Spring Initializer](https://start.spring.io/)创建一个新项目，确保选择以下启动器：
   1. Cloud Task：依赖是基于`spring-cloud-starter-task`。
   2. JDBC：依赖是基于`spring-jdbc`。
   3. Select your database dependency：选择Data Flow Stream 当前使用的数据库依赖关系。例如：`H2`。
2. 在新项目中，创建一个新的 Class 作为主类，如下所示：

   ```java
   @EnableTask
   @SpringBootApplication
   public class MyTask {
       public static void main(String[] args) {
   		SpringApplication.run(MyTask.class, args);
   	}
   }
   ```
3. 您的应用程序中需要一个或多个`CommandLineRunner`或`ApplicationRunner`实现，才可以使用这个类。您既可以实现自己的，也可以使用Spring Boot提供的。
4. 使用Spring Boot将应用程序打包到一个über jar中是依照  [Spring Boot conventions](https://docs.spring.io/spring-boot/docs/2.1.1.RELEASE/reference/html/getting-started-first-application.html#getting-started-first-application-executable-jar) 标准。打包的 Applicaions 可以注册和部署，如下所示

### **1.1. Task 数据库配置**

{% hint style="warning" %}
启动 Tasp Applications 时，请确保Spring Cloud Data Flow使用的数据库驱动程序在 Applications 中也同时进行了配置。例如，如果您的Spring Cloud Data Flow设置为使用Postgresql，请确保Task Applications 也配置了Postgresql依赖。
{% endhint %}

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

## 2 注册 Task Applications

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

```bash
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。例如：

```yaml
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`指定属性文件的位置，如下所示：

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

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

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

| Artifact Type | Stable Release                                                                                                               | SNAPSHOT Release                                                                                                                                     |
| ------------- | ---------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------- |
| Maven         | [dataflow.spring.io/Dearborn-SR1-task-applications-maven](https://dataflow.spring.io/Dearborn-SR1-task-applications-maven)   | [dataflow.spring.io/Dearborn-BUI​​LD-SNAPSHOT-task-applications-maven](https://dataflow.spring.io/Dearborn-BUILD-SNAPSHOT-task-applications-maven)   |
| Docker        | [dataflow.spring.io/Dearborn-SR1-task-applications-docker](https://dataflow.spring.io/Dearborn-SR1-task-applications-docker) | [dataflow.spring.io/Dearborn-BUI​​LD-SNAPSHOT-task-applications-docker](https://dataflow.spring.io/Dearborn-BUILD-SNAPSHOT-task-applications-docker) |

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

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

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

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

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

## 3. 创建 Task Definition

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

```bash
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`命令，如下面的示例所示:

```bash
dataflow:>task launch mytask
Launched task 'mytask'
```

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

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

{% hint style="info" %}
参数需要使用`space`分隔值。
{% endhint %}

可以通过使用`——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](https://docs.spring.io/spring-cloud-dataflow/docs/2.1.0.RELEASE/reference/htmlsingle/#spring-cloud-dataflow-stream-app-whitelisting) 一节中进行更多讨论。如果使用 [registered application property metadata](https://docs.spring.io/spring-cloud-dataflow/docs/2.1.0.RELEASE/reference/htmlsingle/#spring-cloud-dataflow-stream-app-metadata-artifact) ，则可以使用shell中的 `tab` 功能获取候选属性名称列表，输入`--` 后按`tab`。

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

{% hint style="info" %}
&#x20; `<appType> 支持的配置为 task`
{% endhint %}

### **4.2. 公共 Application properties**

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

例如，通过使用以下选项启动 Data Flow server ，可以将所有已启动的Applications 配置属性`prop1`和`prop2`:

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

将导致属性，`prop1=value1`并`prop2=value2`传递给所有已启动的Applications。

{% hint style="info" %}
此机制配置的属性优先级低于 Task 部署时的属性。如果在Task 启动时指定具有相同键的属性，则会被部署时属性值覆盖。
{% endhint %}

### 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>`指当前的部署模式：`local`，`cloudfoundry`或`kubernetes`。

每平台的 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`命令，如以下示例所示：

```bash
dataflow:>task destroy mytask
Destroyed task 'mytask'
```

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

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

或者使用force命令：

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

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

{% hint style="warning" %}
Destroying  命令不会使运行中的 Task 停止，但是，它会从数据库中删除 task definition
{% endhint %}

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

### 4.8. Validating a Task

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

```bash
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 的会如何。

```bash
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 是错误的。
