Flink中自定义窗口算子
虽然Flink提供的窗口算子已经够用了,但是当一些特殊的高级的流式应用出现的时候,会发现可能需要更为复杂的窗口逻辑.
DataStream就为此提供了自定义窗口的接口及算法,可以自定义分配器 触发器 移除器
来共同的进行协同工作,从而实现自定义一个窗口
一个窗口的具体工作过程为:
首先一个元素进入窗口之后会被移交给分配器,其决定了元素该放在哪个窗口中
然后窗口配置的是聚合函数的话,那么会立刻执行聚合,结果为窗口内容存储,如果没有配置聚合函数,那么先将事件放在ListState上
然后加入窗口后触发窗口的触发器,触发器来定义窗口是否准备好计算
触发器判断可以完成窗口后,就进行下一步,即如果是聚合参数就直接发出去,如果是全量窗口函数,就将ListState传递给全量窗口函数
最后是移除器,这是一个可选的组件,允许你在调用前或者之后进行引入,从而删除已经收集的元素,需要注意要在没有指定增量聚合函数的时候使用.
增提的逻辑可以如下
为了保证窗口的API简洁,那么没有定义触发器的WindowAssigner都会提供一个默认的触发器
窗口内部维护了一些状态
窗口会在WindowAssigner首次分配元素的时候创建,窗口内部首先包含了窗口内容,也就是窗口内部的元素
触发器计时器,在触发器中注册个计时器,方便回来回调
触发器的自定义状态, 定义每个窗口内都可以有自己的状态
窗口需要删除的时候,自定义的触发器状态和触发器注册的计时器不会被清除,这些是需要手动在Trigger.clear()来进行清除状态
那么接下来我们来依次看对应的组件
1. 窗口分配器
用于确定元素分配到哪个窗口中,接口结构为
需要注意在其中生成一个触发器
2. 触发器,来决定何时计算,何时发出结果,触发条件可以是时间,可以试试特定数据条件,比如某个特定事件,而且前文说过,内部可以有状态,某种状态上等价于处理函数.
而且每次调用都有一个TriggerResult,决定窗口接下来的行为,可以为 Continue 什么都不做 FIRE 发出结果 PURGE 清除窗口状态,此时会调用ProcessWindowFunction,clear(),FIRE_AND_PURGE 先进行窗口,然后删除
接口定义如下:
触发器中需要注意,需要在窗口删除的时候清理自身的窗口状态,不然会越来越多
还有就是如果希望窗口可以被合并,需要在canMerge中声明支持合并
我们接下来给出一个触发器的示例
上面的触发器在第一次事件到达时注册了一个触发器,此后每次触发时候就再次触发一次.
3. 移除器
最后是自定义窗口机制的可选组件,在执行计算之后或者之前删除元素