Flink程序经过reduce聚合后不输出sink的问题
一、最近提交的一版flink流式计算程序,经过EventTimeSessionWindows后进行了reduce聚合,完成计算完成后迟迟不sink输出结果。
记录下踩过的坑
程序很简单,直接上代码:
StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment();
env.setParallelism(5);
env.setStreamTimeCharacteristic(TimeCharacteristic.EventTime);
//模拟socket数据流
DataStream<String> kafkaDataStreamSource = env.socketTextStream("localhost", 9999, "\n");
kafkaDataStreamSource
.filter((FilterFunction<String>) s -> {
if (s.trim().equals("")) {
return false;
}
return true;
})
.map((MapFunction<String, CarInfo>) s -> JSON.parseObject(s, CarInfo.class))
//设置数据的eventtime作为watermark,代码略
.assignTimestampsAndWatermarks(new ADPunctuatedWatermarks<CarInfo>())
//设置聚合key
.keyBy(CarInfo::getPhoneUID)
//设置Session Window 200s
.window(EventTimeSessionWindows.withGap(Time.seconds(200)))
//聚合
.reduce(new CarInfoReduceFunction<CarInfo>())
//输出打印
.addSink(new SinkFunction<CarInfo>() {
@Override
public void invoke(CarInfo value, Context context) throws Exception {
System.out.println(JSON.toJSONString(value));
}
});
测试发现reduce函数输出正常,可以正常聚合,但就是不走sink;
最终发现是因为并发度大于1的问题,多个并发时不同的数据可能走到了不同的数据通道,导致无法触发session window 的条件,故无法输出。
解决方案
1、可以设置全局并发度为1:
env.setParallelism(1);
2、设置watermark并行度为1:在assignTimestampsAndWatermarks后面添加
...
.assignTimestampsAndWatermarks(new ADPunctuatedWatermarks<CarInfo>())
.setParallelism(1)
...
这一就OK了