背景
Flink已经默认提供了多种窗口,满足大部分的场景使用,但是针对部分场景需要更加灵活的窗口。比如在使用处理时间窗口时,虽然保证了在稳定的时间内的进行数据计算,但是在不同的窗口内的数据量可能差异较大,有可能出现由于数据量过大导致下游算子计算异常的情况,所以期望实现一种窗口,基于处理时间的窗口,但是当窗口内数据量达到一定阈值时结束当前窗口触发计算。
目标
使用触发器Trigger实现基于处理时间与计数的自定义窗口。
描述
Trigger决定了一个窗口何时被下游算子进行逻辑计算处理,以及决定了窗口是否销毁。Flink提供的默认的每个窗口都有不同的触发机制,当这些无法满足需求时,可以通过自定义Trigger实现自定义的窗口。
Trigger抽象类中通过重写方法实现不同的触发逻辑,其中包括以下五个方法:
- onElement() 方法在每条数据进入窗口时调用
- onEventTime() 方法在触发事件时间定时器时调用
- onProcessingTime() 方法在触发处理时间定时器时调用
- onMerge() 方法在窗口合并是调用,在窗口合并时会将对应的Trigger状态进行合并,如会话窗口的实现。
- clear() 方法在窗口被清理是被调用
前三个方法是窗口触发逻辑的核心方法,在这三个方法执行后窗口都会根据方法的返回值进行判断下一步操作。方法返回值都为TriggerResult枚举类型,该枚举类型共包含四个枚举值:
- CONTINUE :不进行任何操作
- FIRE:触发窗口计算(即触发下游算子的逻辑处理),但窗口继续保留,所有元素也都保留。
- PURGE:清除窗口中的所有元素并丢弃窗口,不触发窗口计算或释放任何元素。
- FIRE_AND_PURGE:先触发窗口计算,输出结果,再清除窗口内所有元素,丢弃窗口。
结合上述的状态简单描述下当前设计自定义触发器,便于理解
在窗口接收到每一条数据时,首先判断是否是当前窗口的第一条数据(或者说是否还没有创建过定时器),若是则创建当前窗口关闭时的定时器,继续判断下是否当前窗口的数据量已经满足设定的阈值,若是则创建下个窗口结束时的定时器,并触发计算,关闭当前窗口。若窗口内数据量在定时器时还没有达到设定阈值,触发器触发时则创建下个窗口结束时的定时器,并触发计算,关闭当前窗口。详细逻辑见下面代码
代码
package trigger;
import org.apache.flink.api.common.functions.ReduceFunction;
import org.apache.flink.api.common.state.ReducingState;
import org.apache.flink.api.common.state.ReducingStateDescriptor;
import org.apache.flink.api.common.time.Time;
import org.apache.flink.streaming.api.windowing.triggers.Trigger;
import org.apache.flink.streaming.api.windowing.triggers.TriggerResult;
import org.apache.flink.streaming.api.windowing.windows.Window;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class CountOrTimeTrigger<W extends Window> extends Trigger<Object, W> {
private final long maxCount;
private final Time interval;
private long nextTimerTime;
private boolean hasIntervalTimer = false;
private final static Logger logger = LoggerFactory.getLogger(CountOrTimeTrigger.class);
public CountOrTimeTrigger(long maxCount, Time interval) {
this.maxCount = maxCount;
this.interval = interval;
}
//定义状态描述器
private final ReducingStateDescriptor<Long> countDescriptor = new ReducingStateDescriptor<>("count", new Sum(), Long.class);
/**
* 创建自定义触发器
*
* @param maxCount 最大数量
* @return Count


376

被折叠的 条评论
为什么被折叠?



