我将Kafka事件(对应于来自设备的读数)的DataStream馈入以下代码,该代码在滑动窗口中生成每个设备的读数平均值。这很好。接下来,我要计算同一窗口中每个设备平均值的总和,这是我无法正确用句法表达的部分。
此部分有效:
val stream = env
// words is our Kafka topic
.addSource(kafkaConsumer)
// configure timestamp and watermark assigner
.assignTimestampsAndWatermarks(new DeviceTSAssigner)
.keyBy(_.deviceIdFull)
.timeWindow(Time.minutes(5), Time.minutes(1))
/* count events in window */
.apply{ (key: String, window: TimeWindow, events: Iterable[DeviceData], out: Collector[(String, Long, Double)]) =>
out.collect( (key, window.getEnd, events.map(_.currentReading).sum/events.size))
}
stream.print()
输出类似于
(device1,1530681420000,0.0)
(device2,1530681420000,0.0)
(device3,1530681480000,0.0)
(device4,1530681480000,0.0)
(device5,1530681480000,52066.0)
(device6,1530681480000,69039.0)
(device7,1530681480000,79939.0)
...
...
以下代码是我遇到的问题,我不确定该如何编码,但是我认为应该是这样的:
val avgStream = stream
.keyBy(2) // 2 represents the window.End from stream, see code above
.timeWindow(Time.minutes(1)) // tumbling window
.apply { (
key: Long,
window: TimeWindow,
events: Iterable[(String, Long, Double)],
out: Collector[(Long, Double)]) =>
out.collect( (key, events.map( _._3 ).sum ))
}
我在编译此代码时遇到以下错误。
Error:(70, 52) type mismatch;
found : (Long, org.apache.flink.streaming.api.windowing.windows.TimeWindow, Iterable[(String, Long, Double)], org.apache.flink.util.Collector[(Long, Double)]) => Unit
required: (org.apache.flink.api.java.tuple.Tuple, org.apache.flink.streaming.api.windowing.windows.TimeWindow, Iterable[(String, Long, Double)], org.apache.flink.util.Collector[?]) => Unit
out: Collector[(Long, Double)]) =>
我也尝试了其他变体,例如使用AggregtionFunctions,但是无法获得过去的编译。从错误看来,我需要将输入流元素转换为元组,我已经看过一些代码,但不确定如何做到这一点。我是Scala的新手,所以我认为这是主要问题,因为我想做的事情并不复杂。
更新了07/04/2018
我认为我对我的问题有一个解决方案,似乎可以正常工作,但我仍然想保持开放态度,希望其他人可以对此进行评论(该问题以及我的解决方案)。
基本上,我删除了第一个字段(通过绘制地图),该字段是设备的名称,因为我们不需要它,然后删除了时间戳记(从上一阶段开始),将事件添加到了滚动窗口中,然后只需在第二个字段(基于索引1,从0开始)上求和即可,这是上一阶段的平均读数。
val avgStream = stream
.map(r => (r._2, r._3))
.keyBy(0)
.timeWindowAll(Time.minutes(1))
.sum(1)
.print()
答案 0 :(得分:0)
我能够回答自己的问题,因此上述方法(请参阅更新2018年7月4日)是可行的,但这是一种更好的方法(尤其是如果您不仅想在流(但多个)是使用AggregateFunction。我也早些尝试过,但是由于缺少“地图”步骤而遇到了问题。
一旦我在第二阶段映射了流以提取出感兴趣的相关字段,就可以使用AggregateFunction了。
Flink文档here和此github link都为此提供了一个示例。我从Flink文档示例开始,因为它很容易理解,然后将我的代码转换为更像github示例。