本代码分析以TumblingEventTimeWindows 为例,若有疏忽,请包涵。
第一步 在TumblingEventTimeWindows 类中调用assignWindows()方法。
public Collection
if (timestamp > Long.MIN_VALUE) {
// Long.MIN_VALUE is currently assigned when no timestamp is present
//获取窗口的开始时间,其开始时间计算法则是(timestamp - (timestamp - offset + windowSize) % windowSize)
long start = TimeWindow.getWindowStartWithOffset(timestamp, offset, size);
//获取开始是时间再获取整个窗口时间
return Collections.singletonList(new TimeWindow(start, start + size));
} else {
throw new RuntimeException("Record has Long.MIN_VALUE timestamp (= no timestamp marker). " +
"Is the time characteristic set to 'ProcessingTime', or did you forget to call " +
"'DataStream.assignTimestampsAndWatermarks(...)'?");
}
}
第二步 WindowOperator类中调用下面方式处理数据
public void processElement(StreamRecord
//把窗口和数据放在状态里
windowState.setCurrentNamespace(window);
windowState.add(element.getValue());
//调用 onElement 方式
TriggerResult triggerResult = triggerContext.onElement(element);
}
再调用EventTimeTrigger 类的onElement()方法纤细如下
@Override
public TriggerResult onElement(Object element, long timestamp, TimeWindow window, TriggerContext ctx) throws Exception {
判断水印时间是否大于窗口的结束时间,若大于触发,若不大于继续处理下面数据
if (window.maxTimestamp() <= ctx.getCurrentWatermark()) {
// if the watermark is already past the window fire immediately
return TriggerResult.FIRE;
} else {
//若不大于窗口的结束时间,则注册事件时间触发器
ctx.registerEventTimeTimer(window.maxTimestamp());
return TriggerResult.CONTINUE;
}
}
// 注册事件时间触发器方法如下
public void registerEventTimeTimer(long time) {
internalTimerService.registerEventTimeTimer(window, time);
}
把窗口和触发时间放在一个定时队列中
public void registerEventTimeTimer(N namespace, long time) {
eventTimeTimersQueue.add(new TimerHeapInternalTimer<>(time, (K) keyContext.getCurrentKey(), namespace));
}