本页从概念上大致介绍了 Dataflow 与 Pub/Sub 的集成。本概览说明了 Dataflow 运行程序的 Pub/Sub I/O 连接器实现所涵盖的一些优化。Pub/Sub 是一个可扩缩、持久的事件提取和传送系统。Dataflow 通过通过去重功能、“正好一次”的处理以及从带有时间戳的事件生成数据水印,为 Pub/Sub 的可扩展、“至少一次”的传送模型起到辅助作用。要使用 Dataflow,请使用 Apache Beam SDK 编写流水线,然后在 Dataflow 服务中执行流水线代码。
在开始之前,请先了解 Apache Beam 和流处理流水线的基本概念。有关详情,请参阅以下资源:
- Apache Beam 概念介绍,例如 PCollection、触发器、窗口和水印
- Lambda 之后:Cloud Dataflow 中的“正好一次”处理第 1 部分和第 3 部分:来源和接收器
- 流处理:批处理之外的世界:101 和 102
- Apache Beam 编程指南
使用 Pub/Sub 构建流式处理流水线
要获享 Dataflow 与 Pub/Sub 集成带来的优势,您可以通过以下任一种方式构建流处理流水线:
使用来自 Apache Beam GitHub 代码库的现有流处理流水线示例代码,例如流式字词提取 (Java)、流式字数计数 (Python) 和 streaming_wordcap (Go)。
在 Java 中使用 Google 提供的 Dataflow 模板和相应的模板源代码。
Google 提供了一组 Dataflow 模板,它们提供了基于界面的方式来启动 Pub/Sub 流处理流水线。如果您使用 Java,还可以使用这些模板的源代码作为创建自定义管道的切入点。
以下流处理模板会将 Pub/Sub 数据导出到不同的目标位置:
- Pub/Sub 订阅到 BigQuery
- Pub/Sub 到 Pub/Sub 中继
- Pub/Sub 到 Cloud Storage Avro
- Pub/Sub 到 Cloud Storage 文本
- Cloud Storage Text to Pub/Sub (Stream)
以下批处理模板会将数据流导入 Pub/Sub 主题:
按照 Pub/Sub 快速入门:使用 Dataflow 进行流处理,运行简单的流水线。
Pub/Sub 和 Dataflow 集成功能
Apache Beam 针对 Pub/Sub 提供了一个参考 I/O 源代码实现方案 (PubsubIO
)(Java、Python 和 Go)。此 I/O 源实现供非 Dataflow 运行程序(例如 Apache Spark 运行程序、Apache Flink 运行程序和 Direct Runner)使用。
Dataflow 运行程序会使用与前述方案不同的专有 PubsubIO
实现方案(适用于 Java、Python 和 Go)。此实现方案利用 Google Cloud 内部 API 和服务提供三个主要优势:低延迟水印、高水印精度(因此能确保数据完整性)和高效的去重(正好一次消息处理)。
Apache Beam I/O 连接器可让您通过使用受控制的来源和接收器与 Dataflow 进行交互。在消息被第一个融合阶段成功处理并且该处理过程的副作用被写入永久性存储空间之后,Dataflow 运行程序的 PubsubIO
实现会自动确认消息。如需了解详情,请参阅融合文档。因此,仅当 Dataflow 可以确认在某些组件崩溃或连接丢失时不会丢失数据时,消息才会被确认。
低延迟水印
Dataflow 可以访问 Pub/Sub 的专有 API,该 API 可提供订阅中最早的未确认消息的存留时间,延迟时间要低于在 Cloud Monitoring 中的时间。可以对比一下的是,Cloud Monitoring 中可用的 Pub/Sub 积压指标通常会延迟 2-3 分钟,但在 Dataflow 中,这些指标只会延迟大约 10 秒。这使得 Dataflow 可以将流水线水印提前并更早地发出窗口计算结果。
高水印精确度
Dataflow 与 Pub/Sub 集成后,自然而然地解决的另一个重要问题是为事件时间中指定的窗口提供可靠的水印。事件时间是发布商应用指定的作为 Pub/Sub 消息属性的时间戳,而不是 Pub/Sub 服务针对消息设置的 publish_time
字段。由于 Pub/Sub 仅针对服务分配的(或处理时间)时间戳计算积压统计信息,因此估算事件时间水印需要单独的机制。
为了解决此问题,如果用户选择使用自定义事件时间戳,Dataflow 服务会再创建一个跟踪订阅。此跟踪订阅用于检查基础订阅积压中的消息的事件时间,并估算事件时间积压。如需了解详情,请参阅介绍 Dataflow 如何计算 Pub/Sub 水印的 StackOverflow 页面。
高效的去重技术
重复信息删除对于正好一次消息处理而言是必需的,您可以使用 Apache Beam 编程模型实现只处理一次 Pub/Sub 消息流。Dataflow 会根据 Pub/Sub 消息 ID 删除重复的消息。因此,所有处理逻辑都可以假定消息已经具有独一无二的 Pub/Sub 消息 ID。用于完成此任务的高效增量式汇总机制是在 PubsubIO
API 中提取的。
如果将 PubsubIO
配置为使用 Pub/Sub 消息特性(而非消息 ID)来删除重复消息,则 Dataflow 会在 10 分钟内删除发布到 Pub/Sub 的重复消息。
不支持的 Pub/Sub 功能
Dataflow 运行程序的 Pub/Sub I/O 连接器实现不支持以下 Pub/Sub 功能。
死信主题和指数退避延迟重试政策
Dataflow 不完全支持 Pub/Sub 死信主题和指数退避延迟重试政策。请改为流水线中显式实现这些模式。 零售应用和 Pub/Sub to BigQuery 模板中提供了两个死信模式的示例。
死信主题和指数退避延迟重试政策不适用于 Dataflow 的原因有两个。
首先,Dataflow 不会 NACK 消息(即在流水线代码失败时向 Pub/Sub 发送否定确认)。 相反,Dataflow 会无限地重试消息处理,同时不断延长消息的确认时限。但是,Dataflow 后端可能会因各种内部原因而 NACK 消息,因此即使流水线代码中没有故障,消息也有可能传送至死信主题。
其次,Dataflow 可能会在流水线完全处理数据之前确认消息。具体来说,Dataflow 会在第一个融合阶段成功处理消息后对其进行确认,并且该处理过程的副作用已写入永久性存储空间。 如果流水线有多个融合阶段,并且在第一个阶段之后的任何时间点发生故障,则消息已确认。
Pub/Sub 正好一次传送
由于 Dataflow 有自己的一次性处理,因此不建议将 Pub/Sub 一次性传送与 Dataflow 搭配使用。启用 Pub/Sub“正好一次”传送会降低流水线性能,因为它限制了可用于并行处理的消息。
Pub/Sub 消息排序
启用 Pub/Sub 消息排序后,Dataflow 可能会对消息进行重新排序。流水线会运行,但无法保证消息会按照 Dataflow 接收消息的顺序到达。但是,将 Pub/Sub 与 Dataflow 搭配使用时,启用消息排序可能会增加延迟时间并降低性能。