43、Flink 自定义窗口触发器代码示例

1、方法说明

1)onElement() 方法在每个元素被加入窗口时调用。

返回 TriggerResult 来决定 trigger 如何应对到达窗口的事件
CONTINUE: 什么也不做
FIRE: 触发计算
PURGE: 清空窗口内的元素
FIRE_AND_PURGE: 触发计算,计算结束后清空窗口内的元素

2)onProcessingTime() 方法在注册的 processing-time timer 触发时调用。

返回 TriggerResult 来决定 trigger 如何应对到达窗口的事件
CONTINUE: 什么也不做
FIRE: 触发计算
PURGE: 清空窗口内的元素
FIRE_AND_PURGE: 触发计算,计算结束后清空窗口内的元素

3)onEventTime() 方法在注册的 event-time timer 触发时调用。

返回 TriggerResult 来决定 trigger 如何应对到达窗口的事件
CONTINUE: 什么也不做
FIRE: 触发计算
PURGE: 清空窗口内的元素
FIRE_AND_PURGE: 触发计算,计算结束后清空窗口内的元素

4)clear() 方法处理在对应窗口被移除时所需的逻辑。

5)onMerge() 方法与有状态的 trigger 相关,该方法会在两个窗口合并时,将窗口对应 trigger 的状态合并,比如使用会话窗口时。

2、完整代码示例

import org.apache.flink.api.common.state.ValueState;
import org.apache.flink.api.common.state.ValueStateDescriptor;
import org.apache.flink.streaming.api.datastream.DataStreamSource;
import org.apache.flink.streaming.api.environment.StreamExecutionEnvironment;
import org.apache.flink.streaming.api.functions.windowing.WindowFunction;
import org.apache.flink.streaming.api.windowing.assigners.GlobalWindows;
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.GlobalWindow;
import org.apache.flink.streaming.api.windowing.windows.Window;
import org.apache.flink.util.Collector;

import java.util.ArrayList;
import java.util.List;

/**
 * FIRE 会保留被触发的窗口中的内容,Flink 内置的 trigger 默认使用 `FIRE`。
 * FIRE_AND_PURGE 不会保留被触发的窗口中的内容
 * Purge 只会移除窗口中的内容,不会移除关于窗口的 meta-information 和 trigger 的状态
 */
public class _08_WindowTriggerCustom {
    public static void main(String[] args) throws Exception {
        StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment();

        DataStreamSource<String> input = env.socketTextStream("localhost", 8888);

        ArrayList<String> keyList = new ArrayList<>();
        keyList.add("c");
        keyList.add("d");

        // 测试时限制了分区数,生产中需要设置空闲数据源
        env.setParallelism(2);

        // Processing-Time
        input.keyBy(e -> String.valueOf(e.hashCode() % 2))
                .window(GlobalWindows.create())
                .trigger(new MyCustomWindowTrigger<>(keyList))
                .apply(new WindowFunction<String, String, String, GlobalWindow>() {
                    @Override
                    public void apply(String s, GlobalWindow globalWindow, Iterable<String> iterable, Collector<String> collector) throws Exception {
                        for (String word : iterable) {
                            collector.collect(word);
                        }
                    }
                })
                .print();

        env.execute();
    }
}

class MyCustomWindowTrigger<W extends Window> extends Trigger<String, W> {
    private List<String> keyWords;

    private ValueStateDescriptor<String> valueStateDescriptor;

    public MyCustomWindowTrigger(List<String> keyWords) {
        this.keyWords = keyWords;
        this.valueStateDescriptor = new ValueStateDescriptor<>("cnt", String.class);
    }

    // onElement() 方法在每个元素被加入窗口时调用。
    // 返回 `TriggerResult` 来决定 trigger 如何应对到达窗口的事件
    //- `CONTINUE`: 什么也不做
    //- `FIRE`: 触发计算
    //- `PURGE`: 清空窗口内的元素
    //- `FIRE_AND_PURGE`: 触发计算,计算结束后清空窗口内的元素
    @Override
    public TriggerResult onElement(String input, long l, W w, TriggerContext triggerContext) throws Exception {
        //当窗口内的元素匹配到首个关键字时触发,触发前的元素用 '-' 拼接
        //a0\b0\a1\b1\c2\d2
        //FIRE_AND_PURGE=会清除窗口状态
        //FIRE=不会清除窗口状态
        //2> b0
        //2> a1
        //2> c2
        //
        //1> a0
        //1> b1
        //1> d2
        ValueState<String> partitionedState = triggerContext.getPartitionedState(valueStateDescriptor);
        String value = partitionedState.value();

        for (String keyWord : keyWords) {
            if (input.startsWith(keyWord)) {
                if (value == null || value.isEmpty()) {
                    partitionedState.update(input);
                }
                value += "-" + input;
                partitionedState.update(value);
            }
        }

        if (partitionedState.value() != null && !partitionedState.value().isEmpty()) {
//            return TriggerResult.FIRE_AND_PURGE;
            return TriggerResult.FIRE;
        }

        return TriggerResult.CONTINUE;
    }

    // onProcessingTime() 方法在注册的 processing-time timer 触发时调用。
    // 返回 `TriggerResult` 来决定 trigger 如何应对到达窗口的事件
    //- `CONTINUE`: 什么也不做
    //- `FIRE`: 触发计算
    //- `PURGE`: 清空窗口内的元素
    //- `FIRE_AND_PURGE`: 触发计算,计算结束后清空窗口内的元素
    @Override
    public TriggerResult onProcessingTime(long l, W w, TriggerContext triggerContext) throws Exception {
        return TriggerResult.CONTINUE;
    }

    // onEventTime() 方法在注册的 event-time timer 触发时调用。
    // 返回 `TriggerResult` 来决定 trigger 如何应对到达窗口的事件
    //- `CONTINUE`: 什么也不做
    //- `FIRE`: 触发计算
    //- `PURGE`: 清空窗口内的元素
    //- `FIRE_AND_PURGE`: 触发计算,计算结束后清空窗口内的元素
    @Override
    public TriggerResult onEventTime(long l, W w, TriggerContext triggerContext) throws Exception {
        return TriggerResult.CONTINUE;
    }

    // clear() 方法处理在对应窗口被移除时所需的逻辑。
    @Override
    public void clear(W w, TriggerContext triggerContext) throws Exception {
        ValueState<String> partitionedState = triggerContext.getPartitionedState(valueStateDescriptor);
        partitionedState.clear();
    }

    // onMerge() 方法与有状态的 trigger 相关,该方法会在两个窗口合并时,将窗口对应 trigger 的状态合并,比如使用会话窗口时。
    @Override
    public void onMerge(W window, OnMergeContext ctx) throws Exception {
    }
}

相关推荐

  1. 43Flink 定义窗口触发器代码示例

    2024-06-14 20:50:03       9 阅读
  2. 41Flink 的默认窗口触发器 EventTime 代码示例

    2024-06-14 20:50:03       5 阅读
  3. 定义fink source

    2024-06-14 20:50:03       15 阅读
  4. flink:定义数据分区

    2024-06-14 20:50:03       27 阅读
  5. 定义Flink SourceFunction定时读取数据库

    2024-06-14 20:50:03       33 阅读
  6. 36、Flink 的 WindowAssigner之滑动窗口示例

    2024-06-14 20:50:03       10 阅读
  7. 37、Flink 的 WindowAssigner之会话窗口示例

    2024-06-14 20:50:03       7 阅读

最近更新

  1. TCP协议是安全的吗?

    2024-06-14 20:50:03       16 阅读
  2. 阿里云服务器执行yum,一直下载docker-ce-stable失败

    2024-06-14 20:50:03       16 阅读
  3. 【Python教程】压缩PDF文件大小

    2024-06-14 20:50:03       15 阅读
  4. 通过文章id递归查询所有评论(xml)

    2024-06-14 20:50:03       18 阅读

热门阅读

  1. 针对oracle系列数据库慢数据量大的问题

    2024-06-14 20:50:03       8 阅读
  2. git本地配置及IDEA下Git合并部分文件

    2024-06-14 20:50:03       8 阅读
  3. Spring Boot 3 整合 Redisson 实现分布式锁

    2024-06-14 20:50:03       8 阅读
  4. gitlab克隆本地切换p分支

    2024-06-14 20:50:03       8 阅读
  5. Webrtc支持FFMPEG硬解码之Intel(一)

    2024-06-14 20:50:03       7 阅读
  6. 前端开发中的热更新原理

    2024-06-14 20:50:03       9 阅读
  7. Linux/Ubuntu/Debian常用服务管理命令

    2024-06-14 20:50:03       9 阅读
  8. 【Spring Boot实现网页会话(Session )】

    2024-06-14 20:50:03       8 阅读
  9. 嵌入式Linux:格式化I/O

    2024-06-14 20:50:03       11 阅读
  10. llama factory 大数据量下训练失败

    2024-06-14 20:50:03       14 阅读
  11. 【AI原理解析】— Meta Llama-3模型

    2024-06-14 20:50:03       9 阅读
  12. 个人 PCB 设计规范

    2024-06-14 20:50:03       6 阅读