Google cloud dataflow 获取来自数千个传感器的平均数据
我一直在尝试构建一个数据流管道,从Pubsub接收数据并将其发布到Bigtable或Bigquery。我可以为一个传感器写入原始数据,但当我试图计算一个数据窗口(60秒)的平均值时,我无法为数千个传感器写入原始数据 要说明该场景,请执行以下操作: 我的数据有效载荷 在我的示例中,将有数千个全名为“{location}{name}”的传感器。对于每个传感器,我希望将数据窗口设置为60秒,并计算该数据的平均值 我期待的最后形式 为了插入到Bigtable和Bigquery中,我将采用作为1个元素存在的最终形式Google cloud dataflow 获取来自数千个传感器的平均数据,google-cloud-dataflow,apache-beam,Google Cloud Dataflow,Apache Beam,我一直在尝试构建一个数据流管道,从Pubsub接收数据并将其发布到Bigtable或Bigquery。我可以为一个传感器写入原始数据,但当我试图计算一个数据窗口(60秒)的平均值时,我无法为数千个传感器写入原始数据 要说明该场景,请执行以下操作: 我的数据有效载荷 在我的示例中,将有数千个全名为“{location}{name}”的传感器。对于每个传感器,我希望将数据窗口设置为60秒,并计算该数据的平均值 我期待的最后形式 为了插入到Bigtable和Bigquery中,我将采用作为1个元素存在
finalform = {
"timestamp": "2021-01-27 13:56:01.634717+08:00",
"location": "location1",
"name" : "name1",
"datapoint1" : "Integer That Has Been Averaged",
"datapoint2" : "Integer That Has Been Averaged",
"datapoint3" : "String that has been left alone",
.....
"datapointN" : "Integer That Has Been Averaged",
}
到目前为止,我的解决方案需要帮助。
现在,在最后一行之后,我被卡住了。我希望能够应用组合值以使用平均值。
然而,在应用GroupBy之后,我得到了一个元组(namedkey,value)。然后我运行一个ParDo来处理这个问题,将json分解成(key,value)元组,为组合值做准备,所有数据再次混合,来自不同位置的传感器数据现在混合在PCollection中
我的挑战
因此,以最清晰的形式来看,我面临两个主要挑战:
将apache_梁导入为梁
将apache_beam.runners.interactive.interactive_beam作为ib导入
从apache_梁导入窗口
等级平均值fn(光束组合fn):
def创建_收集器(自身):
打印(dir(self))
返回(1,2,3,4,5,6)
def添加输入(自身、总和计数、输入):
打印(“添加输入”,总和计数,输入)
返回和计数
def合并_蓄能器(自身、蓄能器):
打印(累加器)
数据=zip(*累加器)
返回数据
def提取输出(自身、总和计数):
打印(“提取输出”,总和计数)
数据=总计数
返回数据
使用beam.Pipeline()作为管道:
总计=(
管道
|“创建工厂计数”>>梁。创建([
{
“时间戳”:“2021-01-27 13:55:41.634717+08:00”,
“位置”:“L1”,
“名称”:“S1”,
“数据1”:1,
“数据2”:“字符串”,
“数据3”:3,
},
{
“时间戳”:“2021-01-27 13:55:41.634717+08:00”,
“位置”:“L1”,
“名称”:“S2”,
“数据1”:1,
“数据2”:“字符串”,
“数据3”:3,
},
{
“时间戳”:“2021-01-27 13:55:41.634717+08:00”,
“位置”:“L2”,
“名称”:“S3”,
“数据1”:1,
“数据2”:“字符串”,
“数据3”:3,
},
{
“时间戳”:“2021-01-27 13:55:51.634717+08:00”,
“位置”:“L1”,
“名称”:“S1”,
“数据1”:1,
“数据2”:“字符串”,
“数据3”:3,
},
{
“时间戳”:“2021-01-27 13:55:51.634717+08:00”,
“位置”:“L1”,
“名称”:“S2”,
“数据1”:1,
“数据2”:“字符串”,
“数据3”:3,
},
{
“时间戳”:“2021-01-27 13:55:51.634717+08:00”,
“位置”:“L2”,
“名称”:“S3”,
“数据1”:1,
“数据2”:“字符串”,
“数据3”:3,
},
{
“时间戳”:“2021-01-27 13:56:01.634717+08:00”,
“位置”:“L1”,
“名称”:“S1”,
“数据1”:1,
“数据2”:“字符串”,
“数据3”:3,
},
{
“时间戳”:“2021-01-27 13:56:01.634717+08:00”,
“位置”:“L1”,
“名称”:“S2”,
“数据1”:1,
“数据2”:“字符串”,
“数据3”:3,
},
{
“时间戳”:“2021-01-27 13:56:01.634717+08:00”,
“位置”:“L2”,
“名称”:“S3”,
“数据1”:1,
“数据2”:“字符串”,
“数据3”:3,
},
])
|beam.GroupBy(位置=lambda s:s[“位置”],名称=lambda s:s[“名称”])
|beam.CombinePerKey(AverageFn())
|电子地图(印刷版))
CombinePerKey
部分(特别是CombinePerKey
)。您应该首先使用适当的键(例如位置和名称的组合)将数据排列到KV
s的PCCollection中。此PCollection
之后可以是一个CombinePerKey
和一个组合给定数据对象的CombineFn
实现(通过平均各个字段)最后的答案如下。我的突破是认识到不使用GroupBy,而是使用beam.Map,因为beam.Map是1:1转换。我正在将我的一行数据转换为一个元组(key,data),其中key基本上是我使用Beam.row()指定的唯一标识符,稍后我将使用combineperkey收集并处理该行
将apache_梁导入为梁
将apache_beam.runners.interactive.interactive_beam作为ib导入
从apache_梁导入窗口
数据=[
{
“时间戳”:“2021-01-27 13:55:41.634717+08:00”,
“位置”:“L1”,
“名称”:“S1”,
“数据1”:1,
“数据2”:“字符串”,
“数据3”:5,
“数据4”:5,
},
{
“时间戳”:“2021-01-27 13:55:41.634717+08:00”,
“位置”:“L1”,
“名称”:“S2”,
“数据1”:9,
“数据2”:“字符串”,
“数据3”:2,
“数据4”:2,
},
{
“时间戳”:“2021-01-27 13:55:41.63
finalform = {
"timestamp": "2021-01-27 13:56:01.634717+08:00",
"location": "location1",
"name" : "name1",
"datapoint1" : "Integer That Has Been Averaged",
"datapoint2" : "Integer That Has Been Averaged",
"datapoint3" : "String that has been left alone",
.....
"datapointN" : "Integer That Has Been Averaged",
}
p = beam.Pipeline()
rawdata = p | "Read" >> beam.io.ReadFromPubSub(topic=topic)
jsonData = rawdata | "Parse Json" >> beam.Map(json.loads)
windoweddata = jsonData|beam.WindowInto(window.FixedWindows(60))
groupedData = windoweddata | beam.GroupBy(location=lambda s: s["location"], name=lambda s: s["name"])