我在Kafka的数据看起来像这样:
{
"account": "iOS", //Possible values: iOS, android, web, windows
"events": [
{
"timestamp": "2017-07-03T20:19:35Z"
}
]
}
时间戳从2017-07-03T20:19:35Z
到2017-07-03T20:22:30Z
(约3分钟)。我有这个Flink程序从上面的kafka主题中提取数据:
object TestWindow {
def main(args: Array[String]) = {
val props = new Properties()
props.put(...)
val env = StreamExecutionEnvironment.getExecutionEnvironment
env.setStreamTimeCharacteristic(TimeCharacteristic.EventTime)
env.addSource(new FlinkKafkaConsumer010[String]("topic", new SimpleStringSchema(), props)).
keyBy(jsonStr => {
val jsonParser = new JsonParser()
val jsonObject = jsonParser.parse(jsonStr).getAsJsonObject()
jsonObject.get("account")
}).window(TumblingEventTimeWindows.of(Time.seconds(10)))
.reduce({(v1, v2) =>
println(v1 + " " + v2)
""
})
env.execute()
}
}
我无法理解窗口如何与keyBy
操作一起使用。
我理解上面的keyBy
操作会创建包含相同键元素的不同分区。但我很困惑何时创建窗口以及如何将每个分区添加到哪个窗口?
我的猜测是,当每个JSON对象到达时,它将被keyBy
操作键入,然后基于该JSON对象的事件timeStamp
,它将创建一个窗口10秒钟?
因此,例如,如果时间戳为"2017-07-03T20:19:35Z"
的JSON对象到达且具有account
类型的iOS,则将创建用于iOS的分区键,并且还将为{创建一个窗口{1}}到"2017-07-03T20:19:35Z"
?或者是一个每10秒创建一个窗口,而不管来自Kafka的JSON对象的事件时间戳?
答案 0 :(得分:2)
您对keyBy
的假设是正确的。 keyBy
在已定义的键属性上对流进行分区,并按键计算窗口。
您在示例中使用的TumblingEventTimeWindow
具有固定的窗口边框,即边框不依赖于数据的时间戳。一个10秒的翻滚窗口将创建[00:00:00.000, 00:00:10.000)
,[00:00:10.000, 00:00:20.000)
等窗口。到达窗口运算符的记录将分配给与其时间戳相交的窗口。当窗口关闭时(操作员的本地时间超过窗口的结束时间戳),计算并发出窗口的结果。请注意,窗口仅使用第一个记录进行实例化,即空窗口不会触发计算并且无法发出数据,例如零计数。
其他窗口类型(如会话窗口)具有数据驱动的边界。在会话窗口的情况下,所有不超过彼此相隔一定时间间隔的记录将被分组到一个窗口中。