Flink 基于时间窗口的自定义CountTrigger

 原理:结合Flink源码中的CountTrigger和EventTimeTrigger逻辑即可。

package net.ben.flink.hbase.function.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.typeutils.base.LongSerializer;
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.TimeWindow;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;


public class CustomCountTriggerWithEventTime<T> extends Trigger<T, TimeWindow> {

    /**
     *
     */
    private static final long serialVersionUID = 6021946857731563476L;
    private static final Logger LOG = LoggerFactory.getLogger(CustomCountTriggerWithEventTime.class);

    private final long maxCount;

    private final ReducingStateDescriptor<Long> countStateDescriptor;

    public CustomCountTriggerWithEventTime(long maxCount) {
        this.maxCount = maxCount;
        countStateDescriptor = new ReducingStateDescriptor<>("countState", new ReduceSum(), LongSerializer.INSTANCE);
    }

    private TriggerResult fireAndPurge(long timestamp, TimeWindow window, TriggerContext ctx) throws Exception {
        clear(window, ctx);

        return TriggerResult.FIRE_AND_PURGE;
    }

    @Override
    public TriggerResult onElement(T element, long timestamp, TimeWindow window, TriggerContext ctx) throws Exception {
        
        if (window.maxTimestamp() > ctx.getCurrentWatermark()) {
            ctx.registerEventTimeTimer(window.maxTimestamp());
		} 

        ReducingState<Long> countState = ctx.getPartitionedState(countStateDescriptor);
        
        // 新的element进来,总数需要加1
        countState.add(1L);
        if (countState.get() >= maxCount) {
            LOG.info("Count Trigger triggered on count exceed. count {}", countState.get());
            return fireAndPurge(timestamp, window, ctx);
        } 
        
        return TriggerResult.CONTINUE;
    }

    @Override
    public TriggerResult onProcessingTime(long time, TimeWindow window, TriggerContext ctx) throws Exception {
        // 窗口结束触发
        return TriggerResult.CONTINUE;
    }

    @Override
    public TriggerResult onEventTime(long time, TimeWindow window, TriggerContext ctx) throws Exception {
        LOG.info("Count Trigger triggered on time reached time {} window end {} window max {}",  time, window.getEnd(), window.maxTimestamp());
        if (time == window.maxTimestamp()) {
            return fireAndPurge(time, window, ctx);
        } else {
            return TriggerResult.CONTINUE;
        }
    }

    @Override
    public void clear(TimeWindow window, TriggerContext ctx) throws Exception {
        ctx.deleteEventTimeTimer(window.maxTimestamp());
        ReducingState<Long> countState = ctx.getPartitionedState(countStateDescriptor);
        countState.clear();
    }

    @Override
	public boolean canMerge() {
		return true;
	}

	@Override
	public void onMerge(TimeWindow window,
			OnMergeContext ctx) {
		// only register a timer if the watermark is not yet past the end of the merged window
		// this is in line with the logic in onElement(). If the watermark is past the end of
		// the window onElement() will fire and setting a timer here would fire the window twice.
		long windowMaxTimestamp = window.maxTimestamp();
		if (windowMaxTimestamp > ctx.getCurrentWatermark()) {
			ctx.registerEventTimeTimer(windowMaxTimestamp);
		}
	}

/**
     * 计数方法
     */
    class ReduceSum implements ReduceFunction<Long> {

        @Override
        public Long reduce(Long value1, Long value2) throws Exception {
            return value1 + value2;
        }
    }

}

参考:

http://lyzane.com/flink-count-trigger-with-timeout

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值