Apache Beam Fn API如何接收和发送数据

简介Overviews

Apache Beam Fn API 总体介绍中阐述了总体视角,列出了一系列相关的文档。本文中描述了在处理Bundle时,Beam Runner和Beam SDK Harness之间使用Fn API发送和接收数据的模型。

发送和接受数据

要求

高层视图

逻辑流Logical Stream

编码和解码已知类型

编码和解码未知类型

应对大规模的数据

长度前缀编码

 

发送和接受数据

从高层来看,Runner和SDK Harness之间需要相互传送数据,来支持Bundle的处理。SDK希望允许用户使用任意的数据类型,而不需要Runner必须支持这些类型。Runner和SDK需要接受发送大规模的乱序数据。

要求

SDK Harness已经初始化,并且通过BeamFnControl连接到一个Runner。Runner向SDK Harness发送了处理Bundle的请求。

高层视图

  • A: 特定Runner内部的表达
  • B:Data Plane API序列化
  • C: 序列化之后的数据
  • D: 用户指定的类型T
  • E: State API 序列化

 

Runner和SDK之间使用State 和Data Plane API传输编码之后的数据,称之为逻辑流。SDK Harness负责编码和解码用户指定的数据类型。Runner使用内部的表达形式支持Bundle处理。

逻辑流Logical Stream

BeamFnData和BeamFnState API被建模为一系列的逻辑数据流。各自的Protobuf消息表达了部分的逻辑数据流。

对于BeamFnData API,一组逻辑流在在单个BeamFnData gRPC流上多路复用。逻辑流使用target进行标识,以长度为0的消息结尾。

 

对于BeamFnState API,逻辑流使用State key进行标识,流中的数据片段使用连续的Token进行标识。BeamFnState API中的逻辑流,当返回的响应中token不连续了就算是结束了。

 

对于一个逻辑流,元素在一个嵌套的上下文中进行编码。也有很少的情况下,元素编码之后是0字节,Runner/SDK Harness负责为编码之后的数据添加额外的信息,以便在读写的时候进行识别。

编码和解码已知类型

为了能够支持确定的用例场景,例如GroupByKey,Runner和SDK Harness要对以下几种编码格式达成一致:

  • KV: 键值对包装类.
  • Stream: 持有0个或多个值。用来表达可迭代的数据结构,例如lists, collections, and sets 。
  • LargeStream: 持有1个Steam或者State Key,用来支持迭代大规模的GroupByKey 结果。
  • WindowedValue: 存储窗口、窗格、值和时间戳的类型,用来支持触发器和窗口语义的执行。
  • LengthPrefix: 对被包装的值的长度进行编码的包装器类型。
  • Bytes: 二进制数组。

使用Pcollection关联的Coder对数据元素进行编码(序列化)。更多的细节参考Runner API

建议Runner能够识别如下编码方式,但不做强制要求:

  • GlobalWindow: 表示包含(负无穷,正无穷)时间范围的窗口

    A window representing the time interval (-inf, +inf)

  • IntervalWindow: 表示[开始时间, 结束时间)这一间隔内的窗口。
  • VarInt: 变长的整数。

Runner也可以选择内置其他任意类型的元素的编码方式。

编码和解码未知类型

发送方和接收方需要能够区分不同数据元素的边界,使得连续的字节流可以由发送方正确编码并由接收方解码。 SDK Harness需要充分了解Coder的细节,以便对数据进行编码和解码,而Runner可能只是了解Coder的部分。 让我们使用ParDo的例子,然后写一个GroupByKey。

SDK Harness通过数据层传送表示为WindowedValue<KV<K, V>>的数据。窗口和KV键值对,SDK Harness和Runner都提供了支持,可以进行编码和解码。为了能够执行GroupByKey,Runner需要能够区分Key和Value。所以SDK Harness需要以Runner能够理解的方式,对Key K和值 V进行编码。

类似地,如果我们使用一个SDK Harness的例子来处理GroupByKey的输出上的ParDo。 Runner将需要能够描述价值V边界包裹在一个可迭代的方式,SDK的线束可以区分这些边界。

长度前缀编码器用来包装未知值类型,描述编码之后数据元素的边界,使得双方能够识别编码元素的长度,而不需要知道如何对该值进行编码或解码。 对于写入GroupByKey示例,下图显示了具有未知组件的编码器如何转换为SDK Harness和Runner兼容编码器。

 

 

应对大规模的数据

Protobuf消息有长度限制,取决于所选择语言好的Protobuf类库。由于在类库中中使用无符号/有符号32位整形,所以典型的限制是2GB或者4GB。可以将Protobuf消息视为逻辑上的字节流,跟编码的元素边界无关,来解决限制的问题。

在上例中,注意:

  • 数据元素和Protobuf消息可能是对齐的也可能不对齐。
  • 多个数据元素可以包含在一个Protobuf消息中。
  • 一个数据元素可能跨越多个Protobuf消息。

为了在不同语言版本的Protobuf中可以进行互操作,Runner和SDK harness必须限制Protobuf的消息大小 < 2GB。

长度前缀编码

长度前缀编码器用于包装未知编码器,使得编码可以被SDK线束和Runner两者所理解。 它还允许将任意大的值分解成较小的部分。 长度前缀编码器由包含最大块大小的单个值进行参数化。

长度前缀编码器将任意长字节序列视为一组固定大小的块,其中最后一个块的长度可变长度严格小于参数化的最大值。 下面是一个具有长度前缀编码器参数化为16字节的37字节对象的编码示例。

Length 16

Data[0, 16)

Length 16

Data[16, 32)

Length 5

Data[32, 37)

 

结束!

转载需标明文章来源!

http://blog.csdn.net/ffjl1985/article/details/78242244

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值