Spring Cloud Data Flow参考指南(四)_应用程序

18.1.1. 注册支持的应用程序和任务

为方便起见,我们提供了带有应用程序 URI(适用于 Maven 和 Docker)的静态文件。 适用于所有现成的流和任务或批处理应用启动器。您可以指向此文件并导入 批量使用所有应用程序 URI。否则,如前所述,您可以单独注册它们或拥有自己的 自定义属性文件,其中仅包含所需的应用程序 URI。但是,我们建议有一个“专注的” 自定义属性文件中所需应用程序 URI 的列表。

春云流应用入门

下表包含指向基于 Spring Cloud Stream 2.1.x 的可用 Stream 应用程序启动器的链接 和 Spring Boot 2.1.x:​​dataflow.spring.io​

工件类型

稳定发布

快照发布

兔子MQ + Maven

dataflow.spring.io/rabbitmq-maven-latest

dataflow.spring.io/Einstein-BUILD-SNAPSHOT-stream-applications-rabbit-maven

RabbitMQ + Docker

dataflow.spring.io/rabbitmq-docker-latest

dataflow.spring.io/Einstein-BUILD-SNAPSHOT-stream-applications-rabbit-docker

Apache Kafka + Maven

dataflow.spring.io/kafka-maven-latest

dataflow.spring.io/Einstein-BUILD-SNAPSHOT-stream-applications-kafka-maven

Apache Kafka + Docker

dataflow.spring.io/kafka-docker-latest

dataflow.spring.io/Einstein-BUILD-SNAPSHOT-stream-applications-kafka-docker

默认情况下,应用初学者执行器终结点是安全的。可以通过使用属性部署流来禁用安全性。 在 Kubernetes 上,请参阅活动性和就绪性探测​部分,了解如何配置 执行器端点的安全性。​​app.*.spring.autoconfigure.exclude=org.springframework.boot.autoconfigure.security.servlet.SecurityAutoConfiguration​

从Spring Cloud Stream 2.1 GA版本开始,我们现在与Spring Cloud Function具有强大的互操作性。 编程模型。在此基础上,通过爱因斯坦发布列车,现在可以选择一些Stream App。 初学者,并使用函数式编程模型将它们组合到单个应用程序中。查看“组合函数支持 Spring Cloud Data Flow“博客,通过示例了解有关开发人员和编排体验的更多信息。

春季云任务应用程序启动器

下表包括基于 Spring Cloud Task 2.1.x 和 Spring Boot 2.1.x 的可用任务应用程序启动器:

工件类型

稳定发布

快照发布

马文

dataflow.spring.io/task-maven-latest

dataflow.spring.io/Elston-BUILD-SNAPSHOT-task-applications-maven

码头工人

dataflow.spring.io/task-docker-latest

dataflow.spring.io/Elston-BUILD-SNAPSHOT-task-applications-docker

您可以在任务应用程序初学者项目页面中找到有关可用任务启动器的详细信息,以及 相关参考文档。有关可用流初学者的详细信息,请查看流应用程序初学者项目页面和相关参考文档。

例如,如果要批量注册使用 Kafka 绑定程序生成的所有现成流应用程序,可以使用以下命令:

$ dataflow:>app import --uri https://dataflow.spring.io/kafka-maven-latest

或者,您可以使用 Rabbit 绑定程序注册所有流应用程序,如下所示:

$ dataflow:>app import --uri https://dataflow.spring.io/rabbitmq-maven-latest

您还可以传递选项(默认情况下)以指示是否 属性文件位置应在外壳进程本身内解析。如果位置应该 从数据流服务器进程中解析,指定。​​--local​​​​true​​​​--local false​


使用任一 or 时,如果应用程序已注册到 默认情况下,所提供的名称、类型和版本不会被覆盖。如果您想覆盖 预先存在的应用程序或坐标,包括选项。​​app register​​​​app import​​​​uri​​​​metadata-uri​​​​--force​



但请注意,下载后,应用程序可能会根据资源在本地缓存在数据流服务器上 位置。如果资源位置没有更改(即使实际资源字节可能不同),则 不会重新下载。另一方面,使用资源时,使用常量位置仍可能规避 缓存(如果使用版本)。​​maven://​​​​-SNAPSHOT​



此外,如果流已经部署并使用已注册应用程序的某个版本,则(强制)重新注册 在再次部署流之前,其他应用程序不起作用。


在某些情况下,资源在服务器端解析。在其他情况下, URI 将传递到运行时容器实例,并在其中解析。看 有关更多详细信息,请参阅每个数据流服务器的特定文档。

18.1.2. 创建自定义应用程序

虽然数据流包括源、处理器、接收器应用程序,但您可以扩展这些应用程序或编写自定义Spring Cloud Stream应用程序。

Spring Cloud Stream文档中详细介绍了使用 SpringInitializr 创建 SpringCloud Stream 应用程序的过程。 可以在一个应用程序中包含多个绑定程序。 如果这样做,请参阅 [passing_producer_consumer_properties] 中的说明,了解如何配置它们。

为了支持允许属性,在Spring Cloud Data Flow中运行的Spring Cloud Stream应用程序可以包含Spring Bootas一个可选的依赖项,如以下示例所示:​​configuration-processor​

<dependencies>
<!-- other dependencies -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
</dependencies>

注:请确保包含在 POM 中。 该插件是创建注册到 Spring Cloud Data Flow 的可执行 jar 所必需的。 Spring Initialzr 在生成的 POM 中包含插件。​​spring-boot-maven-plugin​

创建自定义应用程序后,可以注册它,如注册流应用程序中所述。

18.2. 创建流

Spring Cloud Data Flow Server 公开了一个完整的 RESTful API,用于管理流定义的生命周期,但最简单的方法是通过 Spring Cloud Data Flow shell。入门部分介绍如何启动外壳。

新流是在流定义的帮助下创建的。这些定义是从一个简单的DSL构建的。例如,考虑如果我们运行以下 shell 命令会发生什么:

dataflow:> stream create --definition "time | log" --name ticktock

这将定义一个名为基于 DSL 表达式的流。DSL 使用“管道”符号 () 将源连接到接收器。​​ticktock​​​​time | log​​​​|​

该命令显示有关流的有用信息,如以下示例所示(及其输出):​​stream info​

dataflow:>stream info ticktock
╔═══════════╤═════════════════╤══════════╗
║Stream Name│Stream Definition│ Status ║
╠═══════════╪═════════════════╪══════════╣
║ticktock │time | log │undeployed║
╚═══════════╧═════════════════╧══════════╝

18.2.1. 流应用程序属性

应用程序属性是与流中的每个应用程序关联的属性。部署应用程序时,应用程序属性将通过以下方式应用于应用程序 命令行参数或环境变量,具体取决于基础部署实现。

以可以在创建流时定义应用程序属性:

dataflow:> stream create --definition "time | log" --name ticktock

命令行管理程序命令显示应用程序的公开应用程序属性。 有关公开属性的详细信息,请参阅应用程序元数据。​​app info --name <appName> --type <appType>​

下面的清单显示了应用程序的公开属性:​​time​

dataflow:> app info --name time --type source
╔══════════════════════════════╤══════════════════════════════╤══════════════════════════════╤══════════════════════════════╗
║ Option Name │ Description │ Default │ Type ║
╠══════════════════════════════╪══════════════════════════════╪══════════════════════════════╪══════════════════════════════╣
║trigger.time-unit │The TimeUnit to apply to delay│<none> │java.util.concurrent.TimeUnit ║
║ │values. │ │ ║
║trigger.fixed-delay │Fixed delay for periodic │1 │java.lang.Integer ║
║ │triggers. │ │ ║
║trigger.cron │Cron expression value for the │<none> │java.lang.String ║
║ │Cron Trigger. │ │ ║
║trigger.initial-delay │Initial delay for periodic │0 │java.lang.Integer ║
║ │triggers. │ │ ║
║trigger.max-messages │Maximum messages per poll, -1 │1 │java.lang.Long ║
║ │means infinity. │ │ ║
║trigger.date-format │Format for the date value. │<none> │java.lang.String ║
╚══════════════════════════════╧══════════════════════════════╧══════════════════════════════╧══════════════════════════════╝

下面的清单显示了应用程序的公开属性:​​log​

dataflow:> app info --name log --type sink
╔══════════════════════════════╤══════════════════════════════╤══════════════════════════════╤══════════════════════════════╗
║ Option Name │ Description │ Default │ Type ║
╠══════════════════════════════╪══════════════════════════════╪══════════════════════════════╪══════════════════════════════╣
║log.name │The name of the logger to use.│<none> │java.lang.String ║
║log.level │The level at which to log │<none> │org.springframework.integratio║
║ │messages. │ │n.handler.LoggingHandler$Level║
║log.expression │A SpEL expression (against the│payload │java.lang.String ║
║ │incoming message) to evaluate │ │ ║
║ │as the logged message. │ │ ║
╚══════════════════════════════╧══════════════════════════════╧══════════════════════════════╧══════════════════════════════╝

您可以在创建时指定 andapps 的应用程序属性,如下所示:​​time​​​​log​​​​stream​

dataflow:> stream create --definition "time --fixed-delay=5 | log --level=WARN" --name ticktock

请注意,在前面的示例中,为 theandapplications 定义的 and 属性是 shell 完成提供的“短格式”属性名称。 这些“短格式”属性名称仅适用于公开的属性。在所有其他情况下,应仅使用完全限定的属性名称。​​fixed-delay​​​​level​​​​time​​​​log​

18.2.2. 常用应用程序属性

除了通过DSL进行配置之外,Spring Cloud Data Flow还提供了将通用属性设置为所有 它启动的流应用程序。 这可以通过添加前缀为启动时的属性来完成 服务器。 执行此操作时,服务器会将所有属性(不带前缀)传递给它启动的实例。​​spring.cloud.dataflow.applicationProperties.stream​

例如,所有启动的应用程序都可以配置为使用特定的 Kafka 代理,方法是启动 具有以下选项的数据流服务器:

--spring.cloud.dataflow.applicationProperties.stream.spring.cloud.stream.kafka.binder.brokers=192.168.1.100:9092
--spring.cloud.dataflow.applicationProperties.stream.spring.cloud.stream.kafka.binder.zkNodes=192.168.1.100:2181

这样做会导致和属性 将传递给所有启动的应用程序。​​spring.cloud.stream.kafka.binder.brokers​​​​spring.cloud.stream.kafka.binder.zkNodes​

使用此机制配置的属性的优先级低于流部署属性。 如果在流部署时指定了具有相同键的属性(例如,重写公共属性),则会重写它们。​​app.http.spring.cloud.stream.kafka.binder.brokers​

18.3. 部署流

本节介绍当 Spring 云数据流服务器负责部署流时如何部署流。它涵盖了使用船长服务部署和升级流。有关如何设置部署属性的说明适用于流部署的两种方法。

考虑流定义:​​ticktock​

dataflow:> stream create --definition "time | log" --name ticktock

若要部署流,请使用以下 shell 命令:

dataflow:> stream deploy --name ticktock

数据流服务器将应用程序的解析和部署委托给船长。​​time​​​​log​

该命令显示有关流的有用信息,包括部署属性:​​stream info​

dataflow:>stream info --name ticktock
╔═══════════╤═════════════════╤═════════╗
║Stream Name│Stream Definition│ Status ║
╠═══════════╪═════════════════╪═════════╣
║ticktock │time | log │deploying║
╚═══════════╧═════════════════╧═════════╝

Stream Deployment properties: {
"log" : {
"resource" : "maven://org.springframework.cloud.stream.app:log-sink-rabbit",
"spring.cloud.deployer.group" : "ticktock",
"version" : "2.0.1.RELEASE"
},
"time" : {
"resource" : "maven://org.springframework.cloud.stream.app:time-source-rabbit",
"spring.cloud.deployer.group" : "ticktock",
"version" : "2.0.1.RELEASE"
}
}

命令有一个重要的可选命令参数(调用)。 船长可以配置为部署到多个平台。 Skipper 预先配置了一个名为的平台,该平台将应用程序部署到运行 Skipper 的本地计算机。 命令行参数的默认值为。 如果您通常部署到一个平台,则在安装 Skipper 时,您可以覆盖平台的配置。 否则,将 tto 指定为命令返回的值之一。​​--platformName​​​​stream deploy​​​​default​​​​--platformName​​​​default​​​​default​​​​platformName​​​​stream platform-list​

在前面的示例中,时间源每秒将当前时间作为消息发送,日志接收器使用日志记录框架将其输出。 你可以尾部日志(它有后缀)。日志文件位于数据流服务器的日志输出中显示的目录中,如以下清单所示:​​stdout​​​​<instance>​

$ tail -f /var/folders/wn/8jxm_tbd1vj28c8vj37n900m0000gn/T/spring-cloud-dataflow-912434582726479179/ticktock-1464788481708/ticktock.log/stdout_0.log
2016-06-01 09:45:11.250 INFO 79194 --- [ kafka-binder-] log.sink : 06/01/16 09:45:11
2016-06-01 09:45:12.250 INFO 79194 --- [ kafka-binder-] log.sink : 06/01/16 09:45:12
2016-06-01 09:45:13.251 INFO 79194 --- [ kafka-binder-] log.sink : 06/01/16 09:45:13

您还可以通过在创建流时传递标志来一步创建和部署流,如下所示:​​--deploy​

dataflow:> stream create --definition "time | log" --name ticktock --deploy

但是,在实际用例中,一步创建和部署流并不常见。 原因是,当您使用命令时,您可以传入定义如何将应用程序映射到平台上的属性(例如,要使用的容器的内存大小是多少、要运行的每个应用程序的数量以及是否启用数据分区功能)。 属性还可以重写创建流时设置的应用程序属性。 接下来的部分将详细介绍此功能。​​stream deploy​

18.3.1. 部署属性

部署流时,可以指定可以控制如何部署和配置应用程序的属性。有关详细信息,请参阅微型网站的“部署属性”部分。

18.4. 销毁流

您可以通过从 shell 发出命令来删除流,如下所示:​​stream destroy​

dataflow:> stream destroy --name ticktock

如果已部署流,则会在删除流定义之前取消部署该流。

18.5. 取消部署流

通常,您希望停止流,但保留名称和定义以供将来使用。在这种情况下,您可以按名称流式传输:​​undeploy​

dataflow:> stream undeploy --name ticktock
dataflow:> stream deploy --name ticktock

您可以稍后发出命令以重新启动它:​​deploy​

dataflow:> stream deploy --name ticktock

18.6. 验证流

有时,流定义中包含的应用程序在其注册中包含无效的 URI。 这可能是由于在应用程序注册时输入了无效的 URI,或者从要从中提取应用程序的存储库中删除了应用程序。 要验证流中包含的所有应用程序是否可解析,用户可以使用以下命令:​​validate​

dataflow:>stream validate ticktock
╔═══════════╤═════════════════╗
║Stream Name│Stream Definition║
╠═══════════╪═════════════════╣
║ticktock │time | log ║
╚═══════════╧═════════════════╝


ticktock is a valid stream.
╔═══════════╤═════════════════╗
║ App Name │Validation Status║
╠═══════════╪═════════════════╣
║source:time│valid ║
║sink:log │valid ║
╚═══════════╧═════════════════╝

在前面的示例中,用户验证了他们的 ticktock 流。这两个理论都是有效的。 现在我们可以看到如果我们有一个流定义,其中包含具有无效 URI 的已注册应用程序会发生什么:​​source:time​​​​sink:log​

dataflow:>stream validate bad-ticktock
╔════════════╤═════════════════╗
║Stream Name │Stream Definition║
╠════════════╪═════════════════╣
║bad-ticktock│bad-time | log ║
╚════════════╧═════════════════╝


bad-ticktock is an invalid stream.
╔═══════════════╤═════════════════╗
║ App Name │Validation Status║
╠═══════════════╪═════════════════╣
║source:bad-time│invalid ║
║sink:log │valid ║
╚═══════════════╧═════════════════╝

在这种情况下,Spring Cloud 数据流声明流无效,因为具有无效的 URI。​​source:bad-time​

18.7. 更新流

若要更新流,请使用命令,该命令将 bothoras 作为命令参数。 船长有一个重要的新顶级前缀: 以下命令部署流(以及部署时注册的版本):​​stream update​​​​--properties​​​​--propertiesFile​​​​version​​​​http | log​​​​log​​​​1.1.0.RELEASE​

dataflow:> stream create --name httptest --definition "http --server.port=9000 | log"
dataflow:> stream deploy --name httptest
dataflow:>stream info httptest
╔══════════════════════════════╤══════════════════════════════╤════════════════════════════╗
║ Name │ DSL │ Status ║
╠══════════════════════════════╪══════════════════════════════╪════════════════════════════╣
║httptest │http --server.port=9000 | log │deploying ║
╚══════════════════════════════╧══════════════════════════════╧════════════════════════════╝

Stream Deployment properties: {
"log" : {
"spring.cloud.deployer.indexed" : "true",
"spring.cloud.deployer.group" : "httptest",
"maven://org.springframework.cloud.stream.app:log-sink-rabbit" : "1.1.0.RELEASE"
},
"http" : {
"spring.cloud.deployer.group" : "httptest",
"maven://org.springframework.cloud.stream.app:http-source-rabbit" : "1.1.0.RELEASE"
}
}

然后,以下命令更新流以使用日志应用程序的版本。 在使用特定版本的应用程序更新流之前,我们需要确保应用程序已注册到该版本:​​1.2.0.RELEASE​

dataflow:>app register --name log --type sink --uri maven://org.springframework.cloud.stream.app:log-sink-rabbit:1.2.0.RELEASE
Successfully registered application 'sink:log'

然后我们可以更新应用程序:

dataflow:>stream update --name httptest --properties version.log=1.2.0.RELEASE

只能将预注册的应用程序版本用于、、或流。​​deploy​​​​update​​​​rollback​

为了验证部署属性和更新的版本,我们可以使用,如以下示例所示(及其输出):​​stream info​

dataflow:>stream info httptest
╔══════════════════════════════╤══════════════════════════════╤════════════════════════════╗
║ Name │ DSL │ Status ║
╠══════════════════════════════╪══════════════════════════════╪════════════════════════════╣
║httptest │http --server.port=9000 | log │deploying ║
╚══════════════════════════════╧══════════════════════════════╧════════════════════════════╝

Stream Deployment properties: {
"log" : {
"spring.cloud.deployer.indexed" : "true",
"spring.cloud.deployer.count" : "1",
"spring.cloud.deployer.group" : "httptest",
"maven://org.springframework.cloud.stream.app:log-sink-rabbit" : "1.2.0.RELEASE"
},
"http" : {
"spring.cloud.deployer.group" : "httptest",
"maven://org.springframework.cloud.stream.app:http-source-rabbit" : "1.1.0.RELEASE"
}
}

18.8. 强制更新流

升级流时,可以使用该选项部署当前部署的应用程序的新实例,即使没有更改任何应用程序或部署属性也是如此。 当应用程序本身在启动时获取配置信息时(例如,从 Spring Cloud Config Server 获取)时,需要此行为。 您可以使用该选项指定要强制升级的应用程序。 如果未指定任何应用程序名称,则会强制升级所有应用程序。 您可以指定 theandoptions 和 theoroptions。​​--force​​​​--app-names​​​​--force​​​​--app-names​​​​--properties​​​​--propertiesFile​

18.9. 流版本

船长保留已部署流的历史记录。 更新流后,会有流的第二个版本。 您可以使用以下命令查询版本的历史记录:​​stream history --name <name-of-stream>​

dataflow:>stream history --name httptest
╔═══════╤════════════════════════════╤════════╤════════════╤═══════════════╤════════════════╗
║Version│ Last updated │ Status │Package Name│Package Version│ Description ║
╠═══════╪════════════════════════════╪════════╪════════════╪═══════════════╪════════════════╣
║2 │Mon Nov 27 22:41:16 EST 2017│DEPLOYED│httptest │1.0.0 │Upgrade complete║
║1 │Mon Nov 27 22:40:41 EST 2017│DELETED │httptest │1.0.0 │Delete complete ║
╚═══════╧════════════════════════════╧════════╧════════════╧═══════════════╧════════════════╝

18.10. 流清单

Skipper 会在替换所有值后保留所有应用程序、其应用程序属性及其部署属性的“清单”。 这表示部署到平台的内容的最终状态。 可以使用以下命令查看任何版本的 Stream 的清单:

stream manifest --name <name-of-stream> --releaseVersion <optional-version>

如果未指定,则返回最新版本的清单。​​--releaseVersion​

以下示例显示了清单的用法:

dataflow:>stream manifest --name httptest

使用该命令将产生以下输出:

# Source: log.yml
apiVersion: skipper.spring.io/v1
kind: SpringCloudDeployerApplication
metadata:
name: log
spec:
resource: maven://org.springframework.cloud.stream.app:log-sink-rabbit
version: 1.2.0.RELEASE
applicationProperties:
spring.cloud.dataflow.stream.app.label: log
spring.cloud.stream.bindings.input.group: httptest
spring.cloud.dataflow.stream.name: httptest
spring.cloud.dataflow.stream.app.type: sink
spring.cloud.stream.bindings.input.destination: httptest.http
deploymentProperties:
spring.cloud.deployer.indexed: true
spring.cloud.deployer.group: httptest
spring.cloud.deployer.count: 1

---
# Source: http.yml
apiVersion: skipper.spring.io/v1
kind: SpringCloudDeployerApplication
metadata:
name: http
spec:
resource: maven://org.springframework.cloud.stream.app:http-source-rabbit
version: 1.2.0.RELEASE
applicationProperties:
spring.cloud.dataflow.stream.app.label: http
spring.cloud.stream.bindings.output.producer.requiredGroups: httptest
server.port: 9000
spring.cloud.stream.bindings.output.destination: httptest.http
spring.cloud.dataflow.stream.name: httptest
spring.cloud.dataflow.stream.app.type: source
deploymentProperties:
spring.cloud.deployer.group: httptest

大多数部署和应用程序属性由数据流设置,以使应用程序能够相互通信,并发送带有标识标签的应用程序指标。

18.11. 回滚流

您可以使用以下命令回滚到流的先前版本:​​stream rollback​

dataflow:>stream rollback --name httptest

可选命令参数添加流的版本。 如果未指定,则回滚操作将转到以前的流版本。​​--releaseVersion​

18.12. 应用程序计数

应用程序计数是系统的动态属性,用于指定应用程序的实例数。有关详细信息,请参阅微型网站的“应用程序计数”部分。

18.13. 船长的升级策略

船长有一个简单的“红/黑”升级策略。它部署新版本的应用程序,使用与当前运行的版本一样多的实例,并检查应用程序的终结点。 如果新应用程序的运行状况良好,则取消部署以前的应用程序。 如果新应用程序的运行状况不佳,则会取消部署所有新应用程序,并且认为升级不成功。​​/health​

升级策略不是滚动升级,因此,如果应用程序的五个实例正在运行,那么在阳光明媚的日子里,在取消部署旧版本之前,五个新应用程序也在运行。

19. 流 DSL

本部分介绍流DSL 简介中未涵盖的流 DSL 的其他功能。

19.1. 点按直播

可以在流中的各种创建者端点上创建分流器。有关详细信息,请参阅微型网站的“点击流”部分。

19.2. 在流中使用标签

当流由多个具有相同名称的应用程序组成时,必须使用标签限定它们。 有关详细信息,请参阅微型网站的标签应用部分。

19.3. 指定目的地

可以使用命名目标,而不是引用源或接收器应用程序。 有关详细信息,请参阅微型网站的“命名目标”部分。

19.4. 扇入和扇出

通过使用命名目标,您可以支持扇入和扇出用例。 有关详细信息,请参阅微型网站的扇入和扇出部分。

20. 流 Java DSL

您可以使用模块提供的基于 Java 的 DSL 来创建和部署流,而不是使用 shell 来创建和部署流。 有关详细信息,请参阅微型站点的Java DSL部分。​​spring-cloud-dataflow-rest-client​

21. 使用多个活页夹配置流式传输应用程序

在某些情况下,当需要连接到不同的消息传递时,流可以将其应用程序绑定到多个 Spring 云流绑定器 中间件配置。在这些情况下,应确保使用其绑定器正确配置应用程序 配置。例如,同时支持 Kafka 和 Rabbit 绑定器的多绑定器转换器是以中的处理器:

http | multibindertransform --expression=payload.toUpperCase() | log

在前面的示例中,您将编写自己的应用程序。​​multibindertransform​

在此流中,每个应用程序都通过以下方式连接到消息传递中间件:

  1. HTTP 源将事件发送到 RabbitMQ ()。rabbit1
  2. Multi-Binder Transformer处理器从RabbitMQ()接收事件,并将处理后的事件发送到Kafka()。rabbit1kafka1
  3. 日志接收器接收来自 Kafka () 的事件。kafka1

在这里,是春云流应用程序属性中给出的活页夹名称。 基于此设置,应用程序在其类路径中具有以下具有适当配置的绑定程序:​​rabbit1​​​​kafka1​

  • HTTP:兔子活页夹
  • 变换:卡夫卡和兔子活页夹
  • Log: Kafka binder

可以在应用程序本身中设置配置属性。 如果没有,则可以在部署流时通过属性传递它们:​​spring-cloud-stream​​​​binder​​​​deployment​

dataflow:>stream create --definition "http | multibindertransform --expression=payload.toUpperCase() | log" --name mystream

dataflow:>stream deploy mystream --properties "app.http.spring.cloud.stream.bindings.output.binder=rabbit1,app.multibindertransform.spring.cloud.stream.bindings.input.binder=rabbit1,
app.multibindertransform.spring.cloud.stream.bindings.output.binder=kafka1,app.log.spring.cloud.stream.bindings.input.binder=kafka1"

可以通过部署属性指定任何绑定程序配置属性来覆盖这些属性。

22. 功能组成

函数组合允许您将功能逻辑动态附加到现有事件流应用程序。有关更多详细信息,请参阅微型网站的“函数组合”部分。

23. 功能应用

随着Spring Cloud Stream 3.x添加功能支持,你可以通过分别实现Java Util和接口来构建和应用程序。 有关此功能的更多信息,请参阅 SCDF 站点的功能应用程序配方。SourceSinkProcessorSupplierConsumerFunction

24. 例子

本章包括以下示例:

  • 简单的流处理
  • 有状态流处理
  • 其他源和接收器应用程序类型

您可以在“示例”一章中找到指向更多示例的链接。

24.1. 简单的流处理

作为简单处理步骤的示例,我们可以使用以定义将 HTTP 发布数据的有效负载转换为大写:

http | transform --expression=payload.toUpperCase() | log

要创建此流,请在命令行管理程序中输入以下命令:

dataflow:> stream create --definition "http --server.port=9000 | transform --expression=payload.toUpperCase() | log" --name mystream --deploy

以下示例使用 shell 命令发布一些数据:

dataflow:> http post --target http://localhost:9000 --data "hello"

前面的示例在日志中生成大写,如下所示:​​HELLO​

2016-06-01 09:54:37.749  INFO 80083 --- [  kafka-binder-] log.sink    : HELLO

24.2. 有状态流处理

为了演示数据分区功能,下面的清单部署了一个使用 Kafka 作为绑定器的流:

dataflow:>stream create --name words --definition "http --server.port=9900 | splitter --expression=payload.split(' ') | log"
Created new stream 'words'

dataflow:>stream deploy words --properties "app.splitter.producer.partitionKeyExpression=payload,deployer.log.count=2"
Deployed stream 'words'

dataflow:>http post --target http://localhost:9900 --data "How much wood would a woodchuck chuck if a woodchuck could chuck wood"
> POST (text/plain;Charset=UTF-8) http://localhost:9900 How much wood would a woodchuck chuck if a woodchuck could chuck wood
> 202 ACCEPTED


dataflow:>runtime apps
╔════════════════════╤═══════════╤═══════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════╗
║App Id / Instance Id│Unit Status│ No. of Instances / Attributes ║
╠════════════════════╪═══════════╪═══════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════╣
║words.log-v1 │ deployed │ 2 ║
╟┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┼┈┈┈┈┈┈┈┈┈┈┈┼┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈╢
║ │ │ guid = 24166 ║
║ │ │ pid = 33097 ║
║ │ │ port = 24166 ║
║words.log-v1-0 │ deployed │ stderr = /var/folders/js/7b_pn0t575l790x7j61slyxc0000gn/T/spring-cloud-deployer-6467595568759190742/words-1542803461063/words.log-v1/stderr_0.log ║
║ │ │ stdout = /var/folders/js/7b_pn0t575l790x7j61slyxc0000gn/T/spring-cloud-deployer-6467595568759190742/words-1542803461063/words.log-v1/stdout_0.log ║
║ │ │ url = https://192.168.0.102:24166 ║
║ │ │working.dir = /var/folders/js/7b_pn0t575l790x7j61slyxc0000gn/T/spring-cloud-deployer-6467595568759190742/words-1542803461063/words.log-v1 ║
╟┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┼┈┈┈┈┈┈┈┈┈┈┈┼┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈╢
║ │ │ guid = 41269 ║
║ │ │ pid = 33098 ║
║ │ │ port = 41269 ║
║words.log-v1-1 │ deployed │ stderr = /var/folders/js/7b_pn0t575l790x7j61slyxc0000gn/T/spring-cloud-deployer-6467595568759190742/words-1542803461063/words.log-v1/stderr_1.log ║
║ │ │ stdout = /var/folders/js/7b_pn0t575l790x7j61slyxc0000gn/T/spring-cloud-deployer-6467595568759190742/words-1542803461063/words.log-v1/stdout_1.log ║
║ │ │ url = https://192.168.0.102:41269 ║
║ │ │working.dir = /var/folders/js/7b_pn0t575l790x7j61slyxc0000gn/T/spring-cloud-deployer-6467595568759190742/words-1542803461063/words.log-v1 ║
╟────────────────────┼───────────┼───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╢
║words.http-v1 │ deployed │ 1 ║
╟┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┼┈┈┈┈┈┈┈┈┈┈┈┼┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈╢
║ │ │ guid = 9900 ║
║ │ │ pid = 33094 ║
║ │ │ port = 9900 ║
║words.http-v1-0 │ deployed │ stderr = /var/folders/js/7b_pn0t575l790x7j61slyxc0000gn/T/spring-cloud-deployer-6467595568759190742/words-1542803461054/words.http-v1/stderr_0.log ║
║ │ │ stdout = /var/folders/js/7b_pn0t575l790x7j61slyxc0000gn/T/spring-cloud-deployer-6467595568759190742/words-1542803461054/words.http-v1/stdout_0.log ║
║ │ │ url = https://192.168.0.102:9900 ║
║ │ │working.dir = /var/folders/js/7b_pn0t575l790x7j61slyxc0000gn/T/spring-cloud-deployer-6467595568759190742/words-1542803461054/words.http-v1 ║
╟────────────────────┼───────────┼───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╢
║words.splitter-v1 │ deployed │ 1 ║
╟┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┼┈┈┈┈┈┈┈┈┈┈┈┼┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈╢
║ │ │ guid = 33963 ║
║ │ │ pid = 33093 ║
║ │ │ port = 33963 ║
║words.splitter-v1-0 │ deployed │ stderr = /var/folders/js/7b_pn0t575l790x7j61slyxc0000gn/T/spring-cloud-deployer-6467595568759190742/words-1542803437542/words.splitter-v1/stderr_0.log║
║ │ │ stdout = /var/folders/js/7b_pn0t575l790x7j61slyxc0000gn/T/spring-cloud-deployer-6467595568759190742/words-1542803437542/words.splitter-v1/stdout_0.log║
║ │ │ url = https://192.168.0.102:33963 ║
║ │ │working.dir = /var/folders/js/7b_pn0t575l790x7j61slyxc0000gn/T/spring-cloud-deployer-6467595568759190742/words-1542803437542/words.splitter-v1 ║
╚════════════════════╧═══════════╧═══════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════╝

查看日志时,应会看到以下内容:​​words.log-v1-0​

2016-06-05 18:35:47.047  INFO 58638 --- [  kafka-binder-] log.sink                                 : How
2016-06-05 18:35:47.066 INFO 58638 --- [ kafka-binder-] log.sink : chuck
2016-06-05 18:35:47.066 INFO 58638 --- [ kafka-binder-] log.sink : chuck

查看日志时,应会看到以下内容:​​words.log-v1-1​

2016-06-05 18:35:47.047  INFO 58639 --- [  kafka-binder-] log.sink                                 : much
2016-06-05 18:35:47.066 INFO 58639 --- [ kafka-binder-] log.sink : wood
2016-06-05 18:35:47.066 INFO 58639 --- [ kafka-binder-] log.sink : would
2016-06-05 18:35:47.066 INFO 58639 --- [ kafka-binder-] log.sink : a
2016-06-05 18:35:47.066 INFO 58639 --- [ kafka-binder-] log.sink : woodchuck
2016-06-05 18:35:47.067 INFO 58639 --- [ kafka-binder-] log.sink : if
2016-06-05 18:35:47.067 INFO 58639 --- [ kafka-binder-] log.sink : a
2016-06-05 18:35:47.067 INFO 58639 --- [ kafka-binder-] log.sink : woodchuck
2016-06-05 18:35:47.067 INFO 58639 --- [ kafka-binder-] log.sink : could
2016-06-05 18:35:47.067 INFO 58639 --- [ kafka-binder-] log.sink : wood

此示例已显示,包含相同单词的有效负载拆分将路由到同一应用程序实例。

24.3. 其他源和接收器应用程序类型

这个例子展示了一些更复杂的东西:将源代码换成其他东西。另一种受支持的源类型是,它接受通过 HTTP POST 请求引入的数据。请注意,源接受与数据流服务器不同的端口上的数据(默认为 8080)。默认情况下,端口是随机分配的。​​time​​​​http​​​​http​

若要创建使用源但仍使用相同接收器的流,我们需要将简单流处理示例中的原始命令更改为以下内容:​​http​​​​log​

dataflow:> stream create --definition "http | log" --name myhttpstream --deploy

请注意,这一次,在我们实际发布一些数据(通过使用 shell 命令)之前,我们不会看到任何其他输出。要查看源正在侦听的随机分配的端口,请运行以下命令:​​http​

dataflow:>runtime apps

╔══════════════════════╤═══════════╤═════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════╗
║ App Id / Instance Id │Unit Status│ No. of Instances / Attributes ║
╠══════════════════════╪═══════════╪═════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════╣
║myhttpstream.log-v1 │ deploying │ 1 ║
╟┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┼┈┈┈┈┈┈┈┈┈┈┈┼┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈╢
║ │ │ guid = 39628 ║
║ │ │ pid = 34403 ║
║ │ │ port = 39628 ║
║myhttpstream.log-v1-0 │ deploying │ stderr = /var/folders/js/7b_pn0t575l790x7j61slyxc0000gn/T/spring-cloud-deployer-6467595568759190742/myhttpstream-1542803867070/myhttpstream.log-v1/stderr_0.log ║
║ │ │ stdout = /var/folders/js/7b_pn0t575l790x7j61slyxc0000gn/T/spring-cloud-deployer-6467595568759190742/myhttpstream-1542803867070/myhttpstream.log-v1/stdout_0.log ║
║ │ │ url = https://192.168.0.102:39628 ║
║ │ │working.dir = /var/folders/js/7b_pn0t575l790x7j61slyxc0000gn/T/spring-cloud-deployer-6467595568759190742/myhttpstream-1542803867070/myhttpstream.log-v1 ║
╟──────────────────────┼───────────┼─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╢
║myhttpstream.http-v1 │ deploying │ 1 ║
╟┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┼┈┈┈┈┈┈┈┈┈┈┈┼┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈╢
║ │ │ guid = 52143 ║
║ │ │ pid = 34401 ║
║ │ │ port = 52143 ║
║myhttpstream.http-v1-0│ deploying │ stderr = /var/folders/js/7b_pn0t575l790x7j61slyxc0000gn/T/spring-cloud-deployer-6467595568759190742/myhttpstream-1542803866800/myhttpstream.http-v1/stderr_0.log║
║ │ │ stdout = /var/folders/js/7b_pn0t575l790x7j61slyxc0000gn/T/spring-cloud-deployer-6467595568759190742/myhttpstream-1542803866800/myhttpstream.http-v1/stdout_0.log║
║ │ │ url = https://192.168.0.102:52143 ║
║ │ │working.dir = /var/folders/js/7b_pn0t575l790x7j61slyxc0000gn/T/spring-cloud-deployer-6467595568759190742/myhttpstream-1542803866800/myhttpstream.http-v1 ║
╚══════════════════════╧═══════════╧═════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════╝

您应该看到相应的源具有包含它正在侦听的主机和端口信息的属性。现在,您已准备好发布到该 URL,如以下示例所示:​​http​​​​url​

dataflow:> http post --target http://localhost:1234 --data "hello"
dataflow:> http post --target http://localhost:1234 --data "goodbye"

然后,流将数据从源汇集到接收器实现的输出日志,生成类似于以下内容的输出:​​http​​​​log​

2016-06-01 09:50:22.121  INFO 79654 --- [  kafka-binder-] log.sink    : hello
2016-06-01 09:50:26.810 INFO 79654 --- [ kafka-binder-] log.sink : goodbye

我们还可以更改接收器实现。可以将输出通过管道传输到文件 ()、Hadoop() 或任何其他可用的接收器应用程序。您还可以定义自己的应用程序。​​file​​​​hdfs​

流开发人员指南

有关如何在本地计算机上创建、测试和运行 Spring Cloud Stream 应用程序的更多信息,请参阅微型网站上的Stream 开发人员指南。

流监控

有关如何监视作为 Stream 的一部分部署的应用程序的详细信息,请参阅微型网站上的流监视指南。

任务

本节详细介绍了如何在 Spring Cloud 数据流上编排Spring Cloud Task应用程序。

如果您刚刚开始使用Spring Cloud Data Flow,那么在进入本节之前,您可能应该阅读“本地”,“Cloud Foundry”或“Kubernetes”的入门指南。

25. 简介

任务应用程序的生存期很短,这意味着它会故意停止运行,可以按需运行或计划稍后运行。 一个用例可能是抓取网页并写入数据库。

SpringCloud Task框架基于 Spring Boot,并增加了 Boot 应用程序记录短期应用程序的生命周期事件的功能,例如何时启动、何时结束以及退出状态。 任务执行文档显示哪些信息存储在数据库中。 Spring Cloud Task 应用程序中代码执行的入口点通常是 Boot 接口的实现,如本例所示。CommandLineRunner

Spring Batch 项目可能是编写短期应用程序的 Spring 开发人员想到的。 Spring Batch 提供了比 Spring Cloud Task 更丰富的功能集,建议在处理大量数据时使用。 一个用例可能是读取许多 CSV 文件,转换每行数据,并将每个转换后的行写入数据库。 Spring Batch 提供了自己的数据库模式,其中包含有关 Spring Batch 作业执行的更丰富的信息集。 Spring Cloud Task 与 Spring Batch 集成,因此,如果 Spring Cloud Task 应用程序定义了 Spring Batch,则会在 Spring Cloud Task 和 Spring Cloud Batch 执行表之间创建链接。Job

在本地计算机上运行数据流时,任务将在单独的 JVM 中启动。 在Cloud Foundry上运行时,使用Cloud Foundry的任务功能启动任务。在 Kubernetes 上运行时,任务是使用 aor aresource 启动的。​​Pod​​​​Job​

26. 任务的生命周期

在深入了解创建任务的细节之前,您应该了解 Spring Cloud 数据流上下文中任务的典型生命周期:

  1. ​创建任务应用程序​
  2. ​注册任务应用程序​
  3. ​创建任务定义​
  4. ​启动任务​
  5. ​查看任务执行​
  6. ​销毁任务定义​
  7. ​持续部署​

26.1. 创建任务应用程序

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

  1. 使用Spring 初始值设定项创建新项目,确保选择以下启动器:
  1. ​Cloud Task​​:此依赖关系是。spring-cloud-starter-task
  2. ​JDBC​​:此依赖项是启动器。spring-jdbc
  3. 选择数据库依赖项:输入数据流当前正在使用的数据库依赖项。例如:。H2
  1. 在新项目中,创建一个新类作为主类,如下所示:
@EnableTask
@SpringBootApplication
public class MyTask {

public static void main(String[] args) {
SpringApplication.run(MyTask.class, args);
}
}
  1. 使用此类时,您需要应用程序中的一个或多个实现。您可以实现自己的方法,也可以使用 Spring Boot 提供的(例如,有一个用于运行批处理作业的)。CommandLineRunnerApplicationRunner
  2. 使用 Spring Boot 将应用程序打包到 über jar 中是通过标准的Spring Boot 约定完成的。 可以按如下所述注册和部署打包的应用程序。

26.1.1. 任务数据库配置


启动任务应用程序时,请确保 Spring Cloud Data Flow 使用的数据库驱动程序也是对任务应用程序的依赖关系。 例如,如果您的 Spring Cloud Data Flow 设置为使用 Postgresql,请确保任务应用程序也将 Postgresql 作为依赖项。


当您在外部(即从命令行)运行任务并希望 Spring Cloud Data Flow 在其 UI 中显示任务执行时,请确保它们之间共享公共数据源设置。 默认情况下,Spring Cloud Task 使用本地 H2 实例,并将执行记录到 Spring Cloud Data Flow 使用的数据库中。

26.2. 注册任务应用程序

您可以使用 Spring Cloud 数据流 Shell命令向应用程序注册表注册任务应用程序。 必须提供可解析为应用程序项目的唯一名称和 URI。对于类型,请指定。 下面的清单显示了三个示例:​​app register​​​​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

在为方案提供 URI 时,格式应符合以下内容:​​maven​

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

如果要一次注册多个应用程序,可以将它们存储在属性文件中,其中键的格式为,值是 URI。 例如,以下清单将是有效的属性文件:​​<type>.<name>​

task.cat=file:///tmp/cat-1.2.1.BUILD-SNAPSHOT.jar
task.hat=file:///tmp/hat-1.2.1.BUILD-SNAPSHOT.jar

然后,您可以使用该命令并通过使用该选项提供属性文件的位置,如下所示:​​app import​​​​--uri​

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

例如,如果要在单个操作中注册数据流附带的所有任务应用程序,可以使用以下命令执行此操作:

dataflow:>app import --uri https://dataflow.spring.io/task-maven-latest

您还可以传递选项(默认情况下)来指示是否应在 shell 进程本身中解析属性文件位置。 如果应从数据流服务器进程解析位置,请指定。​​--local​​​​TRUE​​​​--local false​

使用任选一个时,如果任务应用程序已注册到 提供的名称和版本,默认情况下不会被覆盖。如果您想覆盖 具有不同位置的预先存在的任务应用程序,包括选项。​​app register​​​​app import​​​​uri​​​​uri-metadata​​​​--force​


在某些情况下,资源在服务器端解析。 在其他情况下,URI 将传递到运行时容器实例,并在其中解析。 有关更多详细信息,请参阅每个数据流服务器的特定文档。

26.3. 创建任务定义

您可以通过提供定义名称以及 应用于任务执行的属性。您可以通过以下方式创建任务定义 RESTful API 或 shell。若要使用 shell 创建任务定义,请使用命令创建任务定义,如以下示例所示:​​task create​

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

您可以通过 RESTful API 或 shell 获取当前任务定义的列表。 若要使用 shell 获取任务定义列表,请使用命令。​​task list​

26.3.1. 最大任务定义名称长度

任务定义名称的最大字符长度取决于平台。


有关资源命名的详细信息,请参阅平台文档。 Local 平台将任务定义名称存储在最大大小为 255 的数据库列中。

Table 1. Maximum Task Definition Name Character Length by Platform

Kubernetes Bare Pods

Kubernetes Jobs

云铸造厂

当地

63

52

63

255

26.3.2. 自动创建任务定义

从版本 2.3.0 开始,可以将数据流服务器配置为通过设置自动创建任务定义。 这不是默认行为,但为方便起见而提供。 启用此属性后,任务启动请求可以将注册的任务应用程序名称指定为任务名称。 如果已注册任务应用程序,服务器将根据需要创建仅指定应用程序名称的基本任务定义。这消除了类似于以下内容的手动步骤:​​spring.cloud.dataflow.task.autocreate-task-definitions​​​​true​

dataflow:>task create mytask --definition "mytask"

您仍然可以为每个任务启动请求指定命令行参数和部署属性。

26.4. 启动任务

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

dataflow:>task launch mytask
Launched task 'mytask'

启动任务时,可以设置在启动任务时需要作为命令行参数传递给任务应用程序的任何属性,如下所示:

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


参数需要作为空格分隔的值传递。

您可以使用该选项传入用于自身的其他属性。 此选项的格式是以逗号分隔的属性字符串为前缀。 属性作为应用程序属性传递到。 由实现来选择如何将这些内容传递到实际的任务应用程序中。 如果属性的前缀为 而不是,则将其作为部署属性传递给,其含义可能是特定于实现的。​​TaskLauncher​​​​--properties​​​​app.<task definition name>.<property>​​​​TaskLauncher​​​​deployer​​​​app​​​​TaskLauncher​​​​TaskLauncher​

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

26.4.1. 应用程序属性

每个应用程序都采用属性来自定义其行为。例如,任务设置建立与默认值不同的输出格式。​​timestamp​​​​format​

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

此属性实际上与时间戳应用程序指定的属性相同。 数据流添加了使用速记形式代替的功能。 您还可以指定手写版本,如以下示例所示:​​timestamp​​​​timestamp.format​​​​format​​​​timestamp.format​

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

有关​​流应用程序属性​​的部分详细讨论了此速记行为。 如果已​​注册应用程序属性元数据​​,则可以在键入后在 shell 中使用 Tab 完成来获取候选属性名称的列表。​​--​

外壳为应用程序属性提供选项卡补全。Shell 命令为所有受支持的属性提供其他文档。支持的任务是。​​app info --name <appName> --type <appType>​​​​<appType>​​​​task​


在 Kubernetes 上重新启动 Spring Batch Jobs 时,必须使用入口点 ofor。​​shell​​​​boot​

包含 Kubernetes 敏感信息的应用程序属性

启动某些属性可能包含敏感信息的任务应用程序时,请使用理论。这是因为 (default) 将所有属性转换为命令行参数,因此在某些环境中可能不安全。​​shell​​​​boot​​​​entryPointStyle​​​​exec​

26.4.2. 常用应用程序属性

除了通过DSL进行配置之外,Spring Cloud Data Flow还提供了一种机制,用于设置其启动的所有任务应用程序通用的属性。 可以通过在启动服务器时添加前缀的属性来执行此操作。 然后,服务器将所有属性(不带前缀)传递给它启动的实例。​​spring.cloud.dataflow.applicationProperties.task​

例如,可以通过使用以下选项启动数据流服务器,将所有启动的应用程序配置为使用 and属性:​​prop1​​​​prop2​

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

这会导致 and属性传递给所有启动的应用程序。​​prop1=value1​​​​prop2=value2​


使用此机制配置的属性的优先级低于任务部署属性。 如果在任务启动时指定了具有相同键的属性(例如,重写公共属性),则会重写它们。​​app.trigger.prop2​

26.5. 限制并发任务启动次数

Spring Cloud Data Flow 允许用户限制每个已配置平台并发运行任务的最大数量,以防止 IaaS 或硬件资源饱和。 默认情况下,限制设置为“对于所有受支持的平台”。如果平台实例上并发运行的任务数大于等于限制,则下一个任务启动请求失败,并通过 RESTful API、命令行管理程序或 UI 返回错误消息。 您可以通过设置相应的部署程序属性为平台实例配置此限制,该属性是已配置平台帐户的名称(如果未显式配置帐户)。 指当前支持的部署程序之一:或。因为,该物业是。(不同之处在于已添加到路径中)。​​20​​​​spring.cloud.dataflow.task.platform.<platform-type>.accounts[<account-name>].maximumConcurrentTasks​​​​<account-name>​​​​default​​​​<platform-type>​​​​local​​​​kubernetes​​​​cloudfoundry​​​​spring.cloud.dataflow.task.platform.<platform-type>.accounts[<account-name>].deployment.maximumConcurrentTasks​​​​deployment​

每个受支持平台的实现通过查询基础平台的运行时状态(如果可能)来确定当前正在运行的任务数。按平台识别变量的方法。 例如,在本地主机上启动任务对每个启动请求使用 .run 一个进程,并在内存中跟踪这些进程。在这种情况下,我们不查询底层操作系统,因为以这种方式识别任务是不切实际的。 对于Cloud Foundry来说,任务是其部署模型支持的核心概念。所有任务的状态 ) 可直接通过 API 获得。 这意味着帐户组织和空间中的每个正在运行的任务容器都包含在运行执行计数中,无论它是通过使用 Spring Cloud 数据流还是直接调用启动的。 对于 Kubernetes 来说,如果成功启动任务,就会生成一个正在运行的 pod,我们预计最终会完成或失败。 在此环境中,通常没有简单的方法来识别与任务对应的 Pod。 出于这个原因,我们只计算由 发起的 pod。 由于任务启动器在 Pod 的元数据中提供标签,因此我们根据此标签的存在来过滤所有正在运行的 Pod。​​TaskLauncher​​​​task​​​​LocalTaskLauncher​​​​LocalTaskLauncher​​​​CloudFoundryTaskLauncher​​​​KubernetesTaskLauncher​​​​KubernetesTaskLauncher​​​​task-name​

26.6. 审查任务执行

启动任务后,任务的状态将存储在关系数据库中。状态 包括:

  • 任务名称
  • 开始时间
  • 结束时间
  • 退出代码
  • 退出消息
  • 上次更新时间
  • 参数

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

要获取一个任务定义的任务执行列表,请添加 任务定义名称 — 例如,。检索完整 任务执行的详细信息,使用带有任务执行 ID 的命令, 例如。​​--name​​​​task execution list --name foo​​​​task execution status​​​​task execution status --id 549​

26.7. 销毁任务定义

销毁任务定义会从定义存储库中删除该定义。 这可以通过 RESTful API 或 shell 来完成。 若要通过 shell 销毁任务,请使用命令,如以下示例所示:​​task destroy​

dataflow:>task destroy mytask
Destroyed task 'mytask'

该命令还具有用于执行要销毁的任务的任务的选项,如以下示例所示:​​task destroy​​​​cleanup​

dataflow:>task destroy mytask --cleanup
Destroyed task 'mytask'

默认情况下,该选项设置为(即,默认情况下,在销毁任务时不会清理任务执行)。​​cleanup​​​​false​

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

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

如果需要,您可以使用力开关:

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

以前启动的定义任务的任务执行信息保留在任务存储库中。

这不会停止此定义当前正在运行的任何任务。相反,它会从数据库中删除任务定义。


​task destroy <task-name>​​仅删除定义,而不删除部署在 Cloud Foundry 上的任务。 删除任务的唯一方法是通过 CLI 分两步:



+ .使用命令获取应用程序的列表。 .确定要删除的任务应用程序并运行命令。​​cf apps​​​​cf delete <task-name>​


26.8. 验证任务

有时,任务定义中包含的应用程序在其注册中具有无效的 URI。 这可能是由于在应用程序注册时输入了无效的 URI,或者从要从中提取它的存储库中删除了应用程序。 要验证任务中包含的所有应用程序是否可解析,请使用命令,如下所示:​​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 ║
╚═══════════════╧═════════════════╝

在前面的示例中,用户验证了其时间戳任务。该应用程序是有效的。 现在我们可以看到如果我们有一个流定义,其中包含具有无效 URI 的已注册应用程序会发生什么:​​task:timestamp​

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 数据流会指出任务无效,因为具有无效的 URI。​​task:badtimestamp​

26.9. 停止任务执行

在某些情况下,在平台上运行的任务可能不会因为平台或应用程序业务逻辑本身的问题而停止。 对于这种情况,Spring Cloud Data Flow提供了向平台发送请求以结束任务的功能。 为此,请为一组给定的任务执行提交 a,如下所示:​​task execution stop​

task execution stop --ids 5

Request to stop the task execution with id(s): 5 has been submitted

使用上述命令,停止执行的触发器将提交到底层部署程序实现。因此,该操作将停止该任务。当我们查看任务执行的结果时,我们看到任务执行已完成,退出代码为 0:​​id=5​

dataflow:>task execution list
╔══════════╤══╤════════════════════════════╤════════════════════════════╤═════════╗
║Task Name │ID│ Start Time │ End Time │Exit Code║
╠══════════╪══╪════════════════════════════╪════════════════════════════╪═════════╣
║batch-demo│5 │Mon Jul 15 13:58:41 EDT 2019│Mon Jul 15 13:58:55 EDT 2019│0 ║
║timestamp │1 │Mon Jul 15 09:26:41 EDT 2019│Mon Jul 15 09:26:41 EDT 2019│0 ║
╚══════════╧══╧════════════════════════════╧════════════════════════════╧═════════╝

如果为具有关联子任务执行的任务执行(如组合任务)提交停止,则会为每个子任务执行发送停止请求。

停止具有正在运行的 Spring 批处理作业的任务执行时,该作业的批处理状态为 。 每个受支持的平台都会在请求停止时向任务应用程序发送 SIG-INT。这允许Spring Cloud Task捕获应用程序的状态。但是,Spring Batch 不处理 SIG-INT,因此,作业停止但仍处于 STARTED 状态。​​STARTED​

启动远程分区春季批处理任务应用程序时,Spring Cloud Data Flow 支持直接停止 Cloud Foundry 和 Kubernetes 平台的工作线程分区任务。本地平台不支持停止工作线程分区任务。

26.9.1. 停止在 Spring 云数据流之外启动的任务执行

您可能希望停止已在 Spring Cloud 数据流之外启动的任务。这方面的一个例子是由远程批处理分区应用程序启动的工作器应用程序。 在这种情况下,远程批量分区应用程序存储每个工作器应用程序。但是,不会存储任何平台信息。 因此,当Spring Cloud Data Flow必须停止远程批量分区应用程序及其工作线程应用程序时,您需要指定平台名称,如下所示:​​external-execution-id​

dataflow:>task execution stop --ids 1 --platform myplatform
Request to stop the task execution with id(s): 1 for platform myplatform has been submitted

27. 订阅任务和批处理事件

您还可以在启动任务时利用各种任务和批处理事件。 如果启用任务以生成任务或批处理事件(在 Kafka 作为绑定器的情况下,具有 and 的其他依赖项),则这些事件将在任务生命周期内发布。 缺省情况下,代理上那些已发布事件(Rabbit、Kafka 和其他事件)的目标名称是事件名称本身(例如:,等)。​​spring-cloud-task-stream​​​​spring-cloud-stream-binder-kafka​​​​task-events​​​​job-execution-events​

dataflow:>task create myTask --definition "myBatchJob"
dataflow:>stream create task-event-subscriber1 --definition ":task-events > log" --deploy
dataflow:>task launch myTask

您可以通过在启动任务时指定显式名称来控制这些事件的目标名称,如下所示:

dataflow:>stream create task-event-subscriber2 --definition ":myTaskEvents > log" --deploy
dataflow:>task launch myTask --properties "app.myBatchJob.spring.cloud.stream.bindings.task-events.destination=myTaskEvents"

下表列出了代理上的缺省任务和批处理事件以及目标名称:

Table 2. Task and Batch Event Destinations

事件

目的地

任务事件

​task-events​

作业执行事件

​job-execution-events​

步骤执行事件

​step-execution-events​

项目读取事件

​item-read-events​

项目处理事件

​item-process-events​

项目写入事件

​item-write-events​

跳过事件

​skip-events​

28. 组合任务

Spring Cloud Data Flow 允许您创建有向图,其中图的每个节点都是一个任务应用程序。 这是通过使用 DSL 来完成组合任务的。 您可以通过 RESTful API、Spring Cloud Data Flow Shell 或 Spring Cloud Data Flow UI 创建组合任务。

28.1. 组合任务运行程序

组合任务通过称为组合任务运行程序的任务应用程序运行。Spring 云数据流服务器在启动组合任务时自动部署组合任务运行程序。

28.1.1. 配置组合任务运行程序

组合任务运行程序应用程序具有用于验证和启动子任务的属性。 这默认为。如果您运行分布式 Spring Cloud Data Flow 服务器,就像在 Cloud Foundry 或 Kubernetes 上部署服务器一样,您需要提供可用于访问服务器的 URI。 您可以通过在启动组合任务时设置组合任务运行器应用程序的属性或在启动 Spring Cloud 数据流服务器时设置 Spring Cloud 数据流服务器的属性来提供此信息。 对于后一种情况,启动组合任务时会自动设置组合任务运行程序应用程序属性。​​dataflow-server-uri​​​​localhost:9393​​​​dataflow-server-uri​​​​spring.cloud.dataflow.server.uri​​​​dataflow-server-uri​

配置选项

该任务具有以下选项:​​ComposedTaskRunner​

  • ​composed-task-arguments​​要用于每个任务的命令行参数。(字符串,默认值:<无>)。
  • ​increment-instance-enabled​​允许再次运行单个实例,而无需更改参数,方法是添加基于上次执行的递增数字作业参数。(布尔值,默认值:)。 ComposedTaskRunner是使用Spring Batch构建的。因此,成功执行后,批处理作业被视为已完成。 要多次启动相同的定义,您必须设置任一属性或更改每次启动的定义参数。 使用此选项时,必须将其应用于所需应用程序的所有任务启动,包括首次启动。ComposedTaskRunnerrun.idtrueComposedTaskRunnerincrement-instance-enableduuid-instance-enabledtrue
  • ​uuid-instance-enabled​​允许通过向作业参数添加 UUID 来再次运行单个实例,而无需更改参数。(布尔值,默认值:)。 ComposedTaskRunner是使用Spring Batch构建的。因此,成功执行后,批处理作业被视为已完成。 要多次启动相同的定义,您必须设置任一属性或更改每次启动的定义参数。 使用此选项时,必须将其应用于所需应用程序的所有任务启动,包括首次启动。此选项设置为 true 时将覆盖 的值。 将此选项设置为同时运行同一组合任务定义的多个实例时。ComposedTaskRunnerctr.idfalseComposedTaskRunnerincrement-instance-enableduuid-instance-enabledtrueincrement-instance-idtrue
  • ​interval-time-between-checks​​在检查数据库以查看任务是否已完成之间等待的时间量(以毫秒为单位)。(整数,默认值:)。使用数据存储来确定每个子任务的状态。此间隔指示它应多久检查一次其子任务的状态。ComposedTaskRunner10000ComposedTaskRunnerComposedTaskRunner
  • ​transaction-isolation-level​​为组合任务运行程序建立事务隔离级别。 可在此处找到可用事务隔离级别的列表。 默认值为。ISOLATION_REPEATABLE_READ
  • ​max-wait-time​​单个步骤在执行组合任务失败之前可以运行的最长时间(以毫秒为单位)(整数,默认值:0)。 确定在 CTR 以失败结束之前允许每个子任务运行的最长时间。默认值 of 表示无超时。0
  • ​split-thread-allow-core-thread-timeout​​指定是否允许拆分核心线程超时。(布尔值,默认值:) 设置策略,控制在保持活动时间内没有任务到达时核心线程是否可以超时和终止,并在新任务到达时根据需要替换。false
  • ​split-thread-core-pool-size​​拆分的核心池大小。(整数,默认值:) 拆分中包含的每个子任务都需要一个线程才能执行。因此,例如,这样的定义需要 aof。 这是因为最大的拆分包含三个子任务。计数将意味着该和将并行运行,但CCC将等到任一或完成才能运行。 然后和将并行运行。1<AAA || BBB || CCC> && <DDD || EEE>split-thread-core-pool-size32AAABBBAAABBBDDDEEE
  • ​split-thread-keep-alive-seconds​​斯普利特的线程保持活动数秒。(整数,默认值:) 如果池当前具有多个线程,则如果多余的线程空闲时间超过,则会停止这些线程。60corePoolSizekeepAliveTime
  • ​split-thread-max-pool-size​​拆分的最大池大小。(整数,默认值:)。 确定线程池允许的最大线程数。Integer.MAX_VALUE
  • 拆分线程队列容量斯普利特的容量。(整数,默认值:BlockingQueueInteger.MAX_VALUE)
  • 如果正在运行的线程少于,则始终更喜欢添加新线程而不是排队。corePoolSizeExecutor
  • 对于正在运行的更多线程,总是更喜欢排队请求而不是添加新线程。corePoolSizeExecutor
  • 如果请求无法排队,则会创建一个新线程,除非超过此值。在这种情况下,任务将被拒绝。maximumPoolSize
  • ​split-thread-wait-for-tasks-to-complete-on-shutdown​​是否等待计划任务在关机时完成,不中断正在运行的任务并运行队列中的所有任务。(布尔值,默认值:false)
  • ​dataflow-server-uri​​接收任务启动请求的数据流服务器的 URI。(字符串,默认值:localhost:9393)
  • ​dataflow-server-username​​接收任务启动请求的数据流服务器的可选用户名。 用于使用基本身份验证访问数据流服务器。未使用ifis设置。dataflow-server-access-token
  • ​dataflow-server-password​​接收任务启动请求的数据流服务器的可选密码。 用于使用基本身份验证访问数据流服务器。未使用ifis设置。dataflow-server-access-token
  • ​dataflow-server-access-token​​此属性设置可选的 OAuth2 访问令牌。 通常,该值是使用当前登录用户的令牌(如果可用)自动设置的。 但是,对于特殊用例,也可以显式设置此值。

当您想要使用当前登录用户的访问令牌并将其传播到组合任务运行程序时,存在一个特殊的布尔属性。使用此属性 通过 Spring Cloud 数据流,如果设置为,则自动填充属性。使用时,必须为每个任务执行传递它。 在某些情况下,默认情况下,每个组合任务启动都必须传递用户。 在这种情况下,请将“弹簧云数据流”属性设置为。​​dataflow-server-use-user-access-token​​​​true​​​​dataflow-server-access-token​​​​dataflow-server-use-user-access-token​​​​dataflow-server-access-token​​​​spring.cloud.dataflow.task.useUserAccessToken​​​​true​

若要为组合任务运行程序设置属性,需要为该属性添加前缀。 例如,设置属性的外观。​​app.composed-task-runner.​​​​dataflow-server-uri​​​​app.composed-task-runner.dataflow-server-uri​

28.2. 组合任务的生命周期

组合任务的生命周期由三个部分组成:

  • 创建组合任务
  • 停止组合任务
  • 重新启动组合任务

28.2.1. 创建组合任务

通过任务创建命令创建任务定义时使用组合任务的 DSL,如以下示例所示:

dataflow:> app register --name timestamp --type task --uri maven://org.springframework.cloud.task.app:timestamp-task:
dataflow:> app register --name mytaskapp --type task --uri file:///home/tasks/mytask.jar
dataflow:> task create my-composed-task --definition "mytaskapp && timestamp"
dataflow:> task launch my-composed-task

在前面的示例中,我们假设组合任务要使用的应用程序尚未注册。 因此,在前两个步骤中,我们注册了两个任务应用程序。 然后,我们使用命令创建组合任务定义。 前面示例中的组合任务 DSL 在启动时运行,然后运行时间戳应用程序。​​task create​​​​mytaskapp​

但在我们启动定义之前,我们可以查看 Spring Cloud 数据流为我们生成了什么。 这可以通过使用任务列表命令来完成,如以下示例中所示(包括其输出):​​my-composed-task​

dataflow:>task list
╔══════════════════════════╤══════════════════════╤═══════════╗
║ Task Name │ Task Definition │Task Status║
╠══════════════════════════╪══════════════════════╪═══════════╣
║my-composed-task │mytaskapp && timestamp│unknown ║
║my-composed-task-mytaskapp│mytaskapp │unknown ║
║my-composed-task-timestamp│timestamp │unknown ║
╚══════════════════════════╧══════════════════════╧═══════════╝

在该示例中,Spring Cloud Data Flow 创建了三个任务定义,每个用于组成组合任务 (and) 的每个应用程序以及组合任务 () 定义。 我们还看到,为子任务生成的每个名称都由组合任务的名称和应用程序的名称组成,用连字符分隔(如在 my-composed-taskmytaskapp 中)。​​my-composed-task-mytaskapp​​​​my-composed-task-timestamp​​​​my-composed-task​​​​-​​​​-​

任务应用程序参数

组成组合任务定义的任务应用程序还可以包含参数,如以下示例所示:

dataflow:> task create my-composed-task --definition "mytaskapp --displayMessage=hello && timestamp --format=YYYY"

28.2.2. 启动组合任务

启动组合任务的完成方式与启动独立任务的方式相同,如下所示:

task launch my-composed-task

启动任务后,假设所有任务都成功完成,则在运行 时可以看到三个任务执行,如以下示例所示:​​task execution list​

dataflow:>task execution list
╔══════════════════════════╤═══╤════════════════════════════╤════════════════════════════╤═════════╗
║ Task Name │ID │ Start Time │ End Time │Exit Code║
╠══════════════════════════╪═══╪════════════════════════════╪════════════════════════════╪═════════╣
║my-composed-task-timestamp│713│Wed Apr 12 16:43:07 EDT 2017│Wed Apr 12 16:43:07 EDT 2017│0 ║
║my-composed-task-mytaskapp│712│Wed Apr 12 16:42:57 EDT 2017│Wed Apr 12 16:42:57 EDT 2017│0 ║
║my-composed-task │711│Wed Apr 12 16:42:55 EDT 2017│Wed Apr 12 16:43:15 EDT 2017│0 ║
╚══════════════════════════╧═══╧════════════════════════════╧════════════════════════════╧═════════╝

在前面的示例中,我们看到 已启动,其他任务也按顺序启动。 他们每个人都成功地用anas运行。​​my-compose-task​​​​Exit Code​​​​0​

将属性传递给子任务

要在任务启动时在组合任务图中设置子任务的属性, 使用以下格式:。 以下清单显示了组合任务定义作为示例:​​app.<composed task definition name>.<child task app name>.<property>​

dataflow:> task create my-composed-task --definition "mytaskapp  && mytimestamp"

要显示“HELLO”并为组合任务定义设置时间戳格式,请使用以下任务启动格式:​​mytaskapp​​​​mytimestamp​​​​YYYY​

task launch my-composed-task --properties "app.my-composed-task.mytaskapp.displayMessage=HELLO,app.my-composed-task.mytimestamp.timestamp.format=YYYY"

与应用程序属性类似,也可以使用以下格式设置子任务的属性:​​deployer​​​​deployer.<composed task definition name>.<child task app name>.<deployer-property>​

task launch my-composed-task --properties "deployer.my-composed-task.mytaskapp.memory=2048m,app.my-composed-task.mytimestamp.timestamp.format=HH:mm:ss"
Launched task 'a1'
将参数传递给组合任务运行程序

You can pass command-line arguments for the composed task runner by using the option:​​--arguments​

dataflow:>task create my-composed-task --definition "<aaa: timestamp || bbb: timestamp>"
Created new task 'my-composed-task'

dataflow:>task launch my-composed-task --arguments "--increment-instance-enabled=true --max-wait-time=50000 --split-thread-core-pool-size=4" --properties "app.my-composed-task.bbb.timestamp.format=dd/MM/yyyy HH:mm:ss"
Launched task 'my-composed-task'
退出状态

以下列表显示了如何在执行每个步骤后为组合任务中包含的每个步骤(任务)设置退出状态:

  • 如果有一个,则用作。TaskExecutionExitMessageExitStatus
  • 如果存在 nois 并且 theis 设置为零,则 for 步骤为。ExitMessageExitCodeExitStatusCOMPLETED
  • 如果存在 nois 并且 theis 设置为任何非零数字,则 for 步骤是。ExitMessageExitCodeExitStatusFAILED

28.2.3. 销毁组合任务

用于销毁独立任务的命令与用于销毁组合任务的命令相同。 唯一的区别是销毁组合任务也会销毁与其关联的子任务。 以下示例显示了使用命令之前和之后的任务列表:​​destroy​

dataflow:>task list
╔══════════════════════════╤══════════════════════╤═══════════╗
║ Task Name │ Task Definition │Task Status║
╠══════════════════════════╪══════════════════════╪═══════════╣
║my-composed-task │mytaskapp && timestamp│COMPLETED ║
║my-composed-task-mytaskapp│mytaskapp │COMPLETED ║
║my-composed-task-timestamp│timestamp │COMPLETED ║
╚══════════════════════════╧══════════════════════╧═══════════╝
...
dataflow:>task destroy my-composed-task
dataflow:>task list
╔═════════╤═══════════════╤═══════════╗
║Task Name│Task Definition│Task Status║
╚═════════╧═══════════════╧═══════════╝

28.2.4. 停止组合任务

如果需要停止组合任务执行,您可以通过以下方式执行此操作:

  • RESTful API
  • 春季云数据流仪表板

要通过仪表板停止组合任务,请选择“作业”选项卡,然后单击要停止的作业执行旁边的 *Stop() 按钮。

当前正在运行的子任务完成时,组合任务运行将停止。 与停止组合任务时正在运行的子任务关联的步骤将标记为 as 以及组合任务作业执行。​​STOPPED​

28.2.5. 重新启动组合任务

如果组合任务在执行过程中失败,并且组合任务的状态为 ,则可以重新启动该任务。 您可以通过以下方式执行此操作:​​FAILED​

  • RESTful API
  • 贝壳
  • 春季云数据流仪表板

要通过 shell 重新启动组合任务,请使用相同的参数启动任务。 要通过仪表板重新启动组合任务,请选择“作业”选项卡,然后单击要重新启动的作业执行旁边的“重新启动”按钮。

重新启动已停止的组合任务作业(通过 Spring Cloud 数据流仪表板或 RESTful API)会重新启动子任务,然后按指定顺序启动剩余(未启动)子任务。​​STOPPED​

29. 组合任务DSL

组合任务可以通过三种方式运行:

29.1. 条件执行

条件执行使用双与号 () 表示。 这允许序列中的每个任务仅在前一个任务时启动 成功完成,如以下示例所示:​​&&​

task create my-composed-task --definition "task1 && task2"

当被调用的复合任务启动时,它会启动被调用的任务,如果成功完成,则调用的任务将启动。 如果失败,则不启动。​​my-composed-task​​​​task1​​​​task1​​​​task2​​​​task1​​​​task2​

您还可以使用 Spring Cloud 数据流仪表板来创建条件执行,方法是使用设计器拖放所需的应用程序并将它们连接在一起以创建有向图,如下图所示:

Spring Cloud Data Flow参考指南(四)_spring_02

图2.条件执行

上图是使用 Spring Cloud 数据流仪表板创建的有向图的屏幕截图。 您可以看到图中的四个组件包含条件执行:

  • 开始图标:所有有向图都从此符号开始。只有一个。
  • 任务图标:表示有向图中的每个任务
  • 结束图标:表示有向图的结束
  • 实线箭头:表示以下之间的流条件执行流:
  • 两个应用程序。
  • 启动控制节点和应用程序。
  • 应用程序和结束控制节点。
  • 结束图标:所有有向图都在此符号处结束

您可以通过单击定义选项卡上组合任务定义旁边的详细信息按钮来查看有向图的图表。

29.2. 过渡执行

DSL 支持对执行有向图期间进行的转换进行细粒度控制。 通过提供基于上一个任务的退出状态的相等条件来指定转换。 任务转换由以下符号表示。​​->​

29.2.1. 基本转换

基本转换如下所示:

task create my-transition-composed-task --definition "foo 'FAILED' -> bar 'COMPLETED' -> baz"

在前面的示例中,将启动,如果它的退出状态为 ,则任务将启动。 如果退出状态为 ,将启动。 返回的所有其他状态不起作用,任务将正常结束。​​foo​​​​FAILED​​​​bar​​​​foo​​​​COMPLETED​​​​baz​​​​cat​

使用 Spring Cloud 数据流仪表板创建相同的“基本转换”将类似于下图:

上图是在 Spring Cloud 数据流仪表板中创建的有向图的屏幕截图。 请注意,有两种不同类型的连接器:

  • 虚线:表示从应用程序到可能的目标应用程序之一的转换。
  • 实线:在条件执行或应用程序与控制节点(开始或结束)之间的连接中连接应用程序。

要创建过渡连接器,请执行以下操作:

  1. 创建过渡时,使用连接器将应用程序链接到每个可能的目标。
  2. 完成后,转到每个连接并通过单击将其选中。
  3. 将出现一个螺栓图标。
  4. 单击该图标。
  5. 输入该连接器所需的退出状态。
  6. 该连接线的实线变为虚线。

29.2.2. 使用通配符过渡

DSL 支持通配符进行转换,如以下示例所示:

task create my-transition-composed-task --definition "foo 'FAILED' -> bar '*' -> baz"

在前面的示例中,将启动,如果它的退出状态为 ,则任务将启动。 对于其他的任何退出状态,将启动。​​foo​​​​FAILED​​​​bar​​​​cat​​​​FAILED​​​​baz​

使用 Spring Cloud 数据流仪表板创建相同的“带通配符的转换”将类似于下图:

Spring Cloud Data Flow参考指南(四)_Cloud_03

图4.使用通配符的基本过渡

29.2.3. 使用以下条件执行进行转换

转换后可以有条件执行,只要通配符 未使用,如以下示例所示:

task create my-transition-conditional-execution-task --definition "foo 'FAILED' -> bar 'UNKNOWN' -> baz && qux && quux"

在前面的示例中,将启动,如果它的退出状态为 ,则任务将启动。 如果退出状态为 ,将启动。 对于其他 thanor 的任何退出状态,将启动,并在成功完成后启动。​​foo​​​​FAILED​​​​bar​​​​foo​​​​UNKNOWN​​​​baz​​​​foo​​​​FAILED​​​​UNKNOWN​​​​qux​​​​quux​

使用 Spring Cloud 数据流仪表板创建相同的“条件执行转换”将类似于下图:

在此图中,虚线(转换)将应用程序连接到目标应用程序,但实线连接 、 和 之间的条件执行。​​foo​​​​foo​​​​qux​​​​quux​

29.3. 拆分执行

拆分允许并行运行组合任务中的多个任务。 它通过使用尖括号 () 对要并行运行的任务和流进行分组来表示。 这些任务和流由双管道符号分隔,如以下示例所示:​​<>​​​​||​

task create my-split-task --definition "<foo || bar || baz>"

前面的示例并行启动任务。​​foo​​​​bar​​​​baz​

使用 Spring Cloud 数据流仪表板创建相同的“拆分执行”将类似于下图:

Spring Cloud Data Flow参考指南(四)_spring_04

图6.分裂

使用任务 DSL,您还可以连续运行多个拆分组,如以下示例所示:

task create my-split-task --definition "<foo || bar || baz> && <qux || quux>"

在前面的示例中,、、和任务是并行启动的。 一旦它们全部完成,那么 theandtasks 就会并行启动。 完成后,组合任务结束。 但是,如果,或失败,拆分包含和不启动。​​foo​​​​bar​​​​baz​​​​qux​​​​quux​​​​foo​​​​bar​​​​baz​​​​qux​​​​quux​

使用 Spring Cloud 数据流仪表板创建相同的“与多个组拆分”将类似于下图:

图7.拆分为条件执行的一部分

请注意,设计器在以下情况下插入了一个控制节点 连接两个连续的拆分。​​SYNC​

拆分中使用的任务不应设置其。设置仅供使用 有过渡​。​​ExitMessage​​​​ExitMessage​

29.3.1. 包含条件执行的拆分

拆分还可以在尖括号内执行条件,如以下示例所示:

task create my-split-task --definition "<foo && bar || baz>"

在前面的示例中,我们看到并行启动。 但是,在完成之前不会成功启动。​​foo​​​​baz​​​​bar​​​​foo​

使用 Spring 云数据流仪表板创建相同的“”,类似于下图:​​split containing conditional execution​

Spring Cloud Data Flow参考指南(四)_Cloud_05

图8.使用条件执行进行拆分

29.3.2. 为拆分建立正确的线程计数

拆分中包含的每个子任务都需要一个线程才能运行。若要正确设置此设置,需要查看图形并找到子任务数最多的拆分。该拆分中的子任务数是所需的线程数。 若要设置线程计数,请使用 (默认为 )。因此,例如,需要aof的定义。 这是因为最大的拆分包含三个子任务。计数 2 意味着 and“将并行运行,但 CCC 将等待 bothorto 完成才能运行。 然后和将并行运行。​​split-thread-core-pool-size property​​​​1​​​​<AAA || BBB || CCC> && <DDD || EEE>​​​​split-thread-core-pool-size​​​​3​​​​AAA​​​​BBB​​​​AAA​​​​BBB​​​​DDD​​​​EEE​

  1. 30. 从流启动任务

可以使用任务启动器数据流接收器从流启动任务。 接收器连接到数据流服务器,并使用其 REST API 启动任何定义的任务。 接收器接受表示 的 JSON 有效负载,该有效负载提供要启动的任务的名称,并可能包括命令行参数和部署属性。task launch request

应用启动器任务启动请求公共组件与 Spring Cloud 流功能组合相结合,可以将任何源或处理器的输出转换为任务启动请求。

添加依赖项以自动配置实现,通过Spring Cloud Function注册为 a。​​app-starters-task-launch-request-common​​​​java.util.function.Function​​​​taskLaunchRequest​

例如,可以从时间源开始,添加以下依赖项,生成它,然后将其注册为自定义源。我们在此示例中调用它:​​time-tlr​

<dependency>
<groupId>org.springframework.cloud.stream.app</groupId>
<artifactId>app-starters-task-launch-request-common</artifactId>
</dependency>

Spring Cloud Stream Initializr为创建流应用程序提供了一个很好的起点。

接下来,注册接收器并创建一个任务(我们使用提供的时间戳任务):​​task-launcher-dataflow​

stream create --name task-every-minute --definition "time-tlr --trigger.fixed-delay=60 --spring.cloud.stream.function.definition=taskLaunchRequest --task.launch.request.task-name=timestamp-task | task-launcher-dataflow" --deploy

上述流每分钟生成一个任务启动请求。该请求提供要启动的任务的名称:​​{"name":"timestamp-task"}​

以定义说明了命令行参数的用法。它生成消息,例如为任务提供命令行参数:​​{"args":["foo=bar","time=12/03/18 17:44:12"],"deploymentProps":{},"name":"timestamp-task"}​

stream create --name task-every-second --definition "time-tlr --spring.cloud.stream.function.definition=taskLaunchRequest --task.launch.request.task-name=timestamp-task --task.launch.request.args=foo=bar --task.launch.request.arg-expressions=time=payload | task-launcher-dataflow" --deploy

请注意,使用 SpEL 表达式将每个消息有效负载映射到命令行参数,以及静态参数 ()。​​time​​​​foo=bar​

然后,可以使用 shell 命令查看任务执行列表,如以下示例所示(及其输出):​​task execution list​

dataflow:>task execution list
╔════════════════════╤══╤════════════════════════════╤════════════════════════════╤═════════╗
║ Task Name │ID│ Start Time │ End Time │Exit Code║
╠════════════════════╪══╪════════════════════════════╪════════════════════════════╪═════════╣
║timestamp-task_26176│4 │Tue May 02 12:13:49 EDT 2017│Tue May 02 12:13:49 EDT 2017│0 ║
║timestamp-task_32996│3 │Tue May 02 12:12:49 EDT 2017│Tue May 02 12:12:49 EDT 2017│0 ║
║timestamp-task_58971│2 │Tue May 02 12:11:50 EDT 2017│Tue May 02 12:11:50 EDT 2017│0 ║
║timestamp-task_13467│1 │Tue May 02 12:10:50 EDT 2017│Tue May 02 12:10:50 EDT 2017│0 ║
╚════════════════════╧══╧════════════════════════════╧════════════════════════════╧═════════╝

在此示例中,我们展示了如何使用 thesource 以固定速率启动任务。 此模式可以应用于任何源以启动任务以响应任何事件。​​time​

30.1. 从流启动组合任务

组合任务可以使用接收器启动,如此处所述。 由于我们直接使用,因此我们需要在创建组合任务启动流之前为组合任务运行器本身以及组合任务设置任务定义。 假设我们要创建以下组合任务定义: 第一步是创建任务定义,如以下示例所示:​​task-launcher-dataflow​​​​ComposedTaskRunner​​​​AAA && BBB​

task create composed-task-runner --definition "composed-task-runner"
task create AAA --definition "timestamp"
task create BBB --definition "timestamp"

的发布可以在这里​找到。​​ComposedTaskRunner​

现在,组合任务定义所需的任务定义已准备就绪,我们需要创建一个启动的流。 因此,在这种情况下,我们创建一个流:​​ComposedTaskRunner​

  • 自定义源以发出任务启动请求,如前所示。time
  • 启动task-launcher-dataflowComposedTaskRunner

流应类似于以下内容:

stream create ctr-stream --definition "time --fixed-delay=30 --task.launch.request.task-name=composed-task-launcher --task.launch.request.args=--graph=AAA&&BBB,--increment-instance-enabled=true | task-launcher-dataflow"

现在,我们专注于启动以下各项所需的配置:​​ComposedTaskRunner​

  • ​graph​​:这是要执行的图形。 在这种情况下是。ComposedTaskRunnerAAA&&BBB
  • ​increment-instance-enabled​​:这允许使用Spring 批处理 unique.is 构建每个执行。 因此,我们希望每次启动一个新的作业实例。 为此,我们开始这样做。ComposedTaskRunnerComposedTaskRunnerComposedTaskRunnerincrement-instance-enabledtrue

31. 与任务共享 Spring 云数据流的数据存储

如任务文档中所述,Spring 云数据流允许您查看 Spring Cloud Task 应用程序的执行情况。所以,在 本节,我们将讨论任务应用程序和Spring所需的内容 云数据流,用于共享任务执行信息。

31.1. 常见的数据存储依赖项

Spring Cloud Data Flow 支持许多开箱即用的数据库, 所以你通常需要做的只是声明环境变量 以确定 Spring 云数据流所需的数据存储。 无论您决定将哪个数据库用于 Spring Cloud 数据流,请确保您的任务还 在 itsorfile 中包含该数据库依赖项。如果数据库依赖性 由 Spring Cloud 使用的数据流在任务应用程序中不存在,任务失败 并且不记录任务执行。​​spring_datasource_*​​​​pom.xml​​​​gradle.build​

31.2. 通用数据存储

Spring Cloud 数据流和任务应用程序必须访问相同的数据存储实例。 这样,Spring Cloud Data Flow 就可以读取任务应用程序记录的任务执行,以在命令行管理程序和仪表板视图中列出它们。 此外,任务应用程序必须对 Spring Cloud 数据流使用的任务数据表具有读取和写入权限。

了解任务应用程序和 Spring Cloud 数据流之间的数据源依赖关系后,您现在可以查看如何在各种任务编排方案中应用它们。

31.2.1. 简单的任务启动

从春云数据流启动任务时,数据流会添加其数据源 属性 (,,,) 到正在启动的任务的应用程序属性。因此,任务应用程序 将其任务执行信息记录到 Spring 云数据流存储库中。​​spring.datasource.url​​​​spring.datasource.driverClassName​​​​spring.datasource.username​​​​spring.datasource.password​

31.2.2. 组合任务运行器

Spring Cloud Data Flow 允许您创建一个有向图,其中每个节点 的图形是一个任务应用程序。这是通过组合任务运行程序完成的。 在这种情况下,应用于简单任务启动或任务启动器接收器的规则也适用于组合任务运行程序。 所有子应用程序还必须有权访问组合任务运行程序正在使用的数据存储。 此外,所有子应用程序必须与在其 orfile 中枚举的组合任务运行程序具有相同的数据库依赖项。​​pom.xml​​​​gradle.build​

31.2.3. 从 Spring Cloud 数据流外部启动任务

您可以使用其他方法(例如调度程序)启动 Spring Cloud Task 应用程序,但仍会在 Spring Cloud Data Flow 中跟踪任务执行。 您可以这样做,前提是任务应用程序遵守此处和此处指定的规则。


如果要使用 Spring Cloud 数据流查看Spring 批处理​作业,请确保 批处理应用程序使用注释并遵循此处和此处枚举的规则。 更多信息可在此处​获得。​​@EnableTask​


32. 调度任务

Spring Cloud Data Flow 允许您使用 aexpression 来计划任务的执行。 您可以通过 RESTful API 或 Spring Cloud Data Flow UI 创建计划。​​cron​

32.1. 调度程序

Spring 云数据流通过云平台上可用的调度代理来调度其任务的执行。 使用Cloud Foundry平台时,Spring Cloud Data Flow使用PCF调度程序。 使用 Kubernetes 时,将使用CronJob。

Spring Cloud Data Flow参考指南(四)_spring_06

图9.体系结构概述