触发器
触发器是用来控制窗口什么时候触发计算。所谓的“触发计算”,就是执行窗口函数,认为是计算得到结果并输出的过程。基于WindowedStream 调用.trigger()方法,就可以传入一个自定义的窗口触发器(Trigger)
stream.keyBy(...) .window(...) .trigger(new MyTrigger())
Trigger 是窗口算子的内部属性,每个窗口分配器(WindowAssigner)都会对应一个默认的触发器;对于 Flink 内置的窗口类型,触发器都已经做了实现。例如,所有事件时间窗口,默认的触发器都是EventTimeTrigger
Trigger 是一个抽象类,自定义时必须实现下面四个抽象方法:
onElement():窗口中每到来一个元素,都会调用这个方法;onEventTime():当注册的事件时间定时器触发时,将调用这个方法。
onProcessingTime ():当注册的处理时间定时器触发时,将调用这个方法。clear():当窗口关闭销毁时,调用这个方法。一般用来清除自定义的状态。
返回类型都是 TriggerResult:CONTINUE(继续):什么都不做;FIRE(触发):触发计算,输出结果;PURGE(清除):清空窗口中的所有数据,销毁窗口;FIRE_AND_PURGE(触发并清除):触发计算输出结果,并清除窗口
移除器(Evictor)
移除器主要用来定义移除某些数据的逻辑。基于 WindowedStream 调用.evictor()方法,就可以传入一个自定义的移除器(Evictor)。Evictor 是一个接口,不同的窗口类型都有各自预实现的移除器。
stream.keyBy(...) .window(...) .evictor(new MyEvictor())
Evictor 接口定义了两个方法:
evictBefore():定义执行窗口函数之前的移除数据操作;evictAfter():定义执行窗口函数之后的以处数据操作;默认情况下,预实现的移除器都是在执行窗口函数(window fucntions)之前移除数据的。
允许延迟(Allowed Lateness)
Flink 提供了一个特殊的接口,可以为窗口算子设置一个“允许的最大延迟”(Allowed Lateness)。也就是说,我们可以设定允许延迟一段时间,在这段时间内,窗口不会销毁,继续到来的数据依然可以进入窗口中并触发计算。直到水位线推进到了 窗口结束时间 + 延迟时间,才真正将窗口的内容清空,正式关闭窗口。
基于WindowedStream 调用.allowedLateness()方法,传入一个 Time 类型的延迟时间,就可以表示允许这段时间内的延迟数据。
stream.keyBy(...) .window(TumblingEventTimeWindows.of(Time.hours(1))) .allowedLateness(Time.minutes(1))
将迟到的数据放入侧输出流
设置窗口的延迟时间,终归还是有限的,后续的数据还是会被丢弃。如果不想丢弃任何一个数据,又该怎么做呢?
Flink 还提供了另外一种方式处理迟到数据。我们可以将未收入窗口的迟到数据,放入“侧输出流”(side output)进行另外的处理。所谓的侧输出流,相当于是数据流的一个“分支”,这个流中单独放置那些错过了该上的车、本该被丢弃的数据。
基于 WindowedStream 调用.sideOutputLateData() 方法,就可以实现这个功能。方法需要传入一个“输出标签”(OutputTag),用来标记分支的迟到数据流。因为保存的就是流中的原始数据,所以OutputTag 的类型与流中数据类型相同。
DataStream<Event> stream = env.addSource(...); OutputTag<Event> outputTag = new OutputTag<Event>("late") {}; stream.keyBy(...) .window(TumblingEventTimeWindows.of(Time.hours(1))) .sideOutputLateData(outputTag)
将迟到数据放入侧输出流之后,还应该可以将它提取出来。基于窗口处理完成之后的DataStream,调用.getSideOutput()方法,传入对应的输出标签,就可以获取到迟到数据所在的流。
SingleOutputStreamOperator<AggResult> winAggStream = stream.keyBy(...) .window(TumblingEventTimeWindows.of(Time.hours(1))) .sideOutputLateData(outputTag) .aggregate(new MyAggregateFunction()) DataStream<Event> lateStream = winAggStream.getSideOutput(outputTag);
getSideOutput()是 SingleOutputStreamOperator 的方法,获取到的侧输出流数据类型应该和 OutputTag 指定的类型一致,与窗口聚合之后流中的数据类型可以不同。
浙公网安备 33010602011771号