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了