一、两种watermark类型
1、Periodic(常用)
周期性(一定时间间隔或者到达一定记录数)生成watermark。
对应接口:AssignerWithPeriodicWatermarks
必须结合时间或者累计条数两个维度,否则在极端情况下会有很大的延时。
两个个抽象类:
AscendingTimestampExtractor
BoundedOutOfOrdernessTimestampExtractor(常用)
2、Punctuated(不常用)
在满足自定义条件时生成watermark,每个元素都有一次机会判断是否生成watermark)
对应接口:AssignerWithPunctuatedWatermarks
在TPS很高的生产环境下会产生大量的 Watermark,可能在一定程度上对下游算子造成一定的压力,只有在实时性很高的场景才会选择这种方式来进行生成水印。
在flink高版本已经标记为废弃。
二、代码
public class EventTimeAndWatermarkStream{
public static void main(String[] args) {
StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment();
env.setParallelism(3);
// 采用事件时间
env.setStreamTimeCharacteristic(TimeCharacteristic.EventTime);
FlinkKafkaConsumer010<String> source = new FlinkKafkaConsumer010<>("dwd", new SimpleStringSchema(), KafkaUtils.comsumerProps());
DataStreamSource<String> sourceStream = env.addSource(source);
// 设置watermark
SingleOutputStreamOperator<String> sourceWithWatermarkStream = sourceStream.assignTimestampsAndWatermarks(new AssignerWithPeriodicWatermarks<String>() {
private long currentMaxEventTime = 0L;
/*
生成watermark
*/
@Override
public Watermark getCurrentWatermark() {
long maxOutOfOrderness = 2000;
return new Watermark(currentMaxEventTime - maxOutOfOrderness);
}
/*
生成事件时间
*/
@Override
public long extractTimestamp(String line, long l) {
DateTimeFormatter format = DateTimeFormatter.ofPattern("yyyyMMddHHmmss");
JSONObject item = JSON.parseObject(line);
String timeString = item.getOrDefault("time", "20210101000000").toString();
long time = LocalDateTime.parse(timeString, format).toEpochSecond(ZoneOffset.of("+8")) * 1000;
currentMaxEventTime = Math.max(currentMaxEventTime, time);
return time;
}
});
sourceWithWatermarkStream.print();
env.execute();
}
}
627

被折叠的 条评论
为什么被折叠?



