1. 窗口的其他API简介
对于一个窗口算子而言,窗口分配器和窗口函数是必不可少的。除此之外,Flink 还提供了其他一些可选的 API,可以更加灵活地控制窗口行为。
1.1 触发器(Trigger)
触发器主要是用来控制窗口什么时候触发计算。所谓的"触发计算"本质上就是执行窗口函数,所以可以认为是计算得到结果并输出的过程。
基于WindowsStream调用.trigger()方法,参数传入一个自定义的窗口触发器(Trigger)。
stream.keyBy(...)
.window(...)
.trigger(new MyTrigger())
Trigger
是窗口算子的内部属性,每个窗口分配器(WindowAssigner)
都会对应一个默认的触发器;对于 Flink 内置的窗口类型,它们的触发器都已经做了实现。例如,所有事件时间窗口,默认的触发器都是 EventTimeTrigger
;类似还有 ProcessingTimeTrigger
和 CountTrigger
。所以一般情况下是不需要自定义触发器的。
Trigger
是一个抽象类,自定义时必须实现以下四个抽象方法:
onElement()
:窗口中每到来一个元素,都会调用这个方法。onEventTime()
:当注册的事件时间定时触发时,将调用这个方法。onProcessingTime ()
:当注册的处理时间定时器触发时,将调用这个方法。clear()
:当窗口关闭销毁时,调用这个方法。一般用来清除自定义的状态。
除了 clear()
比较像生命周期方法,其他三个方法其实都是对某种事件的响应。onElement()
是对流中数据元素到来的响应;而另两个则是对时间的响应。这些方法参数中都有一个“触发器上下文”(TriggerContext)
对象,可以用来注册定时器回调(callback)
。对于时间窗口(TimeWindow)
而言,就是在窗口的结束时间设定了一个定时器,这样到时间就可以触发窗口的计算输出了。
另外这三个方法的返回类型都是 TriggerResult
,这是一个枚举类型(enum)
,其中定义了对窗口进行操作的四种类型
。
CONTINUE
(继续):什么都不做FIRE
(触发):触发计算,输出结果PURGE
(清除):清空窗口中的所有数据,销毁窗口FIRE_AND_PURGE
(触发并清除):触发计算输出结果,并清除窗口
Trigger
除了可以控制触发计算,还可以定义窗口什么时候关闭(销毁)。并且TriggerResult
的返回结果可以让计算输出结果和关闭窗口分开执行。
示例:
在日常业务场景中,我们经常会开比较大的窗口来计算每个窗口的pv 或者 uv 等数据。但窗口开的太大,会使我们看到计算结果的时间间隔变长。所以我们可以使用触发器,来隔一段时间触发一次窗口计算。我们在代码中计算了每个 url 在 10 秒滚动窗口的 pv 指标,然后设置了触发器,每隔 1 秒钟触发一次窗口的计算。
public static void main(String[] args) throws Exception {
StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment();
env.setParallelism(1);
// 创建自定义数据源的实时流
DataStream<Event> stringDataStreamSource = env.addSource(new CustomSource())
.assignTimestampsAndWatermarks(WatermarkStrategy.<Event>forBoundedOutOfOrderness(Duration.ZERO)
.withTimestampAssigner(new SerializableTimestampAssigner<Event>() {
@Override
public long extractTimestamp(Event element, long recordTimestamp) {
return element.getTimestamp();
}
}</