您的位置:首页 > 运维架构 > Apache

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

2017-10-15 17:47 573 查看
简介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
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: