SingleOutputStreamOperator<DataBean> watered = maped.assignTimestampsAndWatermarks(WatermarkStrategy.<DataBean>forBoundedOutOfOrderness(Duration.ZERO).withTimestampAssigner(new SerializableTimestampAssigner<DataBean>() {
@Override
public long extractTimestamp(DataBean dataBean, long l) {
return dataBean.getTs();
}
}));
assignTimestampsAndWatermarks,生成水印方法,底层的类,会不断的执行一个定时任务就是 调用 onPeriodicEmit()周期的发送watermark
同时我们看到还有一个onEvent(),在每次收到数据后都会调用一次onEvent方法,不断比较上次的watermark和本次watermark的大小,如果比上次的大就替换成为新的watermark
- 到这:第一次 assignTimestampsAndWatermarks 的逻辑就是
- assignTimestampsAndWatermarks这个方法内部,会每200ms会调用一次onPeriodicEmit()方法,onPeriodicEmit会output.emitWatermark()输出watermark(maxTimestamp),还有个onEvent的方法,onEvent每次收到数据后会根据数据时间和maxTimestamp取最大值,然后不断更新它,就会根据数据的情况一直生成新的watermark。
- 但是当到了数据处理环节后,就不再是这样了
- 到了数据处理环节后,每个数据 和 watermark都被包装成了一个StreamElement,每次处理的时候会根据数据类型进行判断,是watermark则更新当前时间,是数据则是正常流程,因此在下游这两个方法不是异步方法,而是同步阻塞的。
- 因此新的数据只能拿到上次的watermark时间。