我是Flink的新手,我正在尝试做一些练习,当我使用带有kafka连接器的窗口时,我遇到了一个问题。
代码是这样的:
val env: StreamExecutionEnvironment = StreamExecutionEnvironment.getExecutionEnvironment
.....
// a KeyedStream with name as the key
val eventsStream: KeyedStream[CustomedObject, String] = env
.addSource[CustomedObject](source.getSource)
.keyBy(c.get("name"))
// defines a Sliding window assigner with event time
val windowedStream: WindowedStream[CustomedObject, String, TimeWindow] = eventsStream.window(SlidingEventTimeWindows.of(Time.seconds(2L), Time.seconds(1L)))
// applys a window function
val result = windowedStream.apply(
(key, window, input: Iterable[CustomedObject], out: Collector[(String, TimeWindow)]) => {
out.collect((key, window))
}
)
问题:当我尝试 eventsStream.print()时,控制台中有输出,但是当我尝试 result.print()时,没有输出
的相关信息: 密钥存在并且在每个事件中都有价值
有人可以告诉我为什么没有每个窗口的内容输出?
答案 0 :(得分:2)
当流的水印到达窗口的末尾时,将触发事件时间窗口。如果没有发生,那么水印可能存在问题。源需要注意生成适当的水印,或者您需要在应用程序中实现它。有关这些主题的详情,请参阅event time和watermarks。
更新了摘要,希望避免任何混淆:
事件时间时间戳和水印的长度通常表示自Epoch以来的毫秒数,但事件时间是逻辑的,单调增加的时钟,而Flink并不关心值实际代表什么。
与处理时间不同,处理时间不断向前推进,事件时间一直保持不变,直到 watermarks 推进。当前水印是事件时间时钟的当前值,它通常落后于到目前为止看到的某个有限延迟的最大时间戳(此延迟是在事件被认为迟到之前将被容纳的最大无序)。 / p>
当您的应用程序在事件时间运行时,Flink需要知道与每个流元素关联的时间戳以及当前水印。 时间戳提取器和水印生成器为此角色提供服务,Flink提供了两种内置方法,可以进行扩展。
除非您的数据源已经为您提取了AssignerWithPunctuatedWatermarks
和AssignerWithPeriodicWatermarks
的时间戳,否则您需要实现Flink将在每个流元素上调用的extractTimestamp(MyEvent element, long previousElementTimestamp)
方法它的时间戳。
这两者之间的区别在于 AssignerWithPunctuatedWatermarks
具有为每个流元素调用的checkAndGetNextWatermark()方法,期望某些元素是特殊的(如标点符号),并且这些特殊元素将用于生成水印。相比之下,使用 AssignerWithPeriodicWatermarks
,每隔ExecutionConfig.getAutoWatermarkInterval()
毫秒调用一次getCurrentWatermark()方法来生成水印,期望某些状态保持为副作用调用extractTimestamp()可用于生成水印(BoundedOutOfOrdernessTimestampExtractor
,这是通过记住到目前为止在流中看到的最大时间戳来实现的。)
答案 1 :(得分:0)
@alpinegizmo非常感谢你的回复,你是对的,我想为其他新人做一个小小的总结。
要注意两点:
1511866730000L
AssignerWithPunctuatedWatermarks
和之间的区别
AssignerWithPeriodicWatermarks
: AssignerWithPunctuatedWatermarks :如果元素已经在创建时带有时间戳,您希望将它们用作时间戳,因此请使用AssignerWithPunctuatedWatermarks
,因为它是" 间断&#34 ;;
AssignerWithPeriodicWatermarks :使用此类以定期间隔生成水印。最多每xx毫秒(通过ExecutionConfig.getAutoWatermarkInterval()
配置),系统将调用getCurrentWatermark()
方法来探测下一个水印值。因此,系统自动为您生成每个事件的时间间隔,它是" periodic "。
我对标点符号和周期性感到困惑,我认为标点符号表示时间戳会保存在某处,它是永久存储。
我希望这可以帮助其他新手!