我有一个连续的JSONArray数据生成给Kafka主题,并且我想处理具有EventTime特性的记录。为了实现此目标,我必须为JSONArray中包含的每个记录分配水印。
我没有找到实现此目标的便捷方法。我的解决方案是使用DataStreamSource>中的数据,然后使用匿名ProcessFunction迭代List并将对象收集到下游,最后向该下游分配水印。
主要代码如下:
DataStreamSource<List<MockData>> listDataStreamSource = KafkaSource.genStream(env);
SingleOutputStreamOperator<MockData> convertToPojo = listDataStreamSource
.process(new ProcessFunction<List<MockData>, MockData>() {
@Override
public void processElement(List<MockData> value, Context ctx, Collector<MockData> out)
throws Exception {
value.forEach(mockData -> out.collect(mockData));
}
});
convertToPojo.assignTimestampsAndWatermarks(
new BoundedOutOfOrdernessTimestampExtractor<MockData>(Time.seconds(5)) {
@Override
public long extractTimestamp(MockData element) {
return element.getTimestamp();
}
});
SingleOutputStreamOperator<Tuple2<String, Long>> countStream = convertToPojo
.keyBy("country").window(
SlidingEventTimeWindows.of(Time.seconds(10), Time.seconds(10)))
.process(
new FlinkEventTimeCountFunction()).name("count elements");
毫无疑问,代码似乎还可以,也可以正常运行。但是ProcessWindowFunction从未触发。我跟踪了Flink源代码,发现EventTimeTrigger从未返回TriggerResult.FIRE,由TriggerContext.getCurrentWatermark导致始终返回Long.MIN_VALUE。
在事件发生时处理List的正确方法是什么?任何建议将不胜感激。
答案 0 :(得分:0)
问题是您将keyBy和window操作应用到convertToPojo流,而不是带有时间戳和水印(未分配给变量)的流。
如果您大致像这样编写代码,那么它应该可以工作:
listDataStreamSource = KafkaSource ...
convertToPojo = listDataStreamSource.process ...
pojoPlusWatermarks = convertToPojo.assignTimestampsAndWatermarks ...
countStream = pojoPlusWatermarks.keyBy ...
在convertToPojo流上调用assignTimestampsAndWatermarks不会修改该流,而是创建一个包含时间戳和水印的新数据流对象。您需要将窗口应用于该新数据流。