Google cloud dataflow 获取来自数千个传感器的平均数据

Google cloud dataflow 获取来自数千个传感器的平均数据,google-cloud-dataflow,apache-beam,Google Cloud Dataflow,Apache Beam,我一直在尝试构建一个数据流管道,从Pubsub接收数据并将其发布到Bigtable或Bigquery。我可以为一个传感器写入原始数据,但当我试图计算一个数据窗口(60秒)的平均值时,我无法为数千个传感器写入原始数据 要说明该场景,请执行以下操作: 我的数据有效载荷 在我的示例中,将有数千个全名为“{location}{name}”的传感器。对于每个传感器,我希望将数据窗口设置为60秒,并计算该数据的平均值 我期待的最后形式 为了插入到Bigtable和Bigquery中,我将采用作为1个元素存在

我一直在尝试构建一个数据流管道,从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中

我的挑战 因此,以最清晰的形式来看,我面临两个主要挑战:

  • 如何将组合值应用于管道
  • 如何将mean应用于管道,但忽略“string”类型的条目
  • 任何帮助都将受到极大欢迎

    到目前为止,在查米卡拉的帮助下,我的部分解决方案
    将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
    实现(通过平均各个字段)
  • 这应该在您的实现中完成,您应该将relavent字段和ignore string字段组合在一起

  • 最后的答案如下。我的突破是认识到不使用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"])