源码解析FlinkKafkaConsumer支持周期性水位线发送

背景

当flink消费kafka的消息时,我们经常会用到FlinkKafkaConsumer进行水位线的发送,本文就从源码看下FlinkKafkaConsumer.assignTimestampsAndWatermarks指定周期性水位线发送的流程

FlinkKafkaConsumer水位线发送

1.首先从Fetcher类开始,创建Fetcher类的时候会构建一个周期性的水位线发送线程并启动

java 复制代码
        // if we have periodic watermarks, kick off the interval scheduler
        if (timestampWatermarkMode == WITH_WATERMARK_GENERATOR && autoWatermarkInterval > 0) {
            PeriodicWatermarkEmitter<T, KPH> periodicEmitter =
                    new PeriodicWatermarkEmitter<>(
                            checkpointLock,
                            subscribedPartitionStates,
                            watermarkOutputMultiplexer,
                            processingTimeProvider,
                            autoWatermarkInterval);

            periodicEmitter.start();
        }

2.随后,PeriodicWatermarkEmitter中注册处理时间定时器,周期性执行

java 复制代码
        public void start() {
            timerService.registerTimer(timerService.getCurrentProcessingTime() + interval, this);
        }

        @Override
        public void onProcessingTime(long timestamp) {

            synchronized (checkpointLock) {
                for (KafkaTopicPartitionState<?, ?> state : allPartitions) {
                    // 这里当前算子任务消费的kafka 分区分别记录每个分区的水位值
                    state.onPeriodicEmit();
                }
				//这里当前算子会把自己消费的kafka分区的所有水位线取最小值后当成当前算子任务自身的水位线发送出去,注意这里是当前算子任务级别的
                watermarkOutputMultiplexer.onPeriodicEmit();
            }

            // schedule the next watermark
            timerService.registerTimer(timerService.getCurrentProcessingTime() + interval, this);
        }
    }

3.对应state.onPeriodicEmit();记录每个kafka分区的水位线方法

java 复制代码
    @Override
    public void onPeriodicEmit(WatermarkOutput output) {
        final org.apache.flink.streaming.api.watermark.Watermark next = wms.getCurrentWatermark();
        if (next != null) {
            output.emitWatermark(new Watermark(next.getTimestamp()));
        }
    }
其中 WatermarkOutput output.emitWatermark(new Watermark(next.getTimestamp()))代码如下:
        public DeferredOutput(OutputState state) {
            this.state = state;
        }

        @Override
        public void emitWatermark(Watermark watermark) {
            state.setWatermark(watermark.getTimestamp());
        }
所以这里最终效果只是对应state(kafka分区[注意,一个算子任务有可能消费好几个kafka分区])上设置了水位线
        /**
         * Returns true if the watermark was advanced, that is if the new watermark is larger than
         * the previous one.
         *
         * <p>Setting a watermark will clear the idleness flag.
         */
        public boolean setWatermark(long watermark) {
            this.idle = false;
            final boolean updated = watermark > this.watermark;
            // 这里也可以看出来,即使代码里面发送了更小值的水位线,水位线也不会回退
            this.watermark = Math.max(watermark, this.watermark);
            return updated;
        }        

4.对应算子任务组合当前任务消费的所有分区水位线的方法

java 复制代码
private void updateCombinedWatermark() {
        long minimumOverAllOutputs = Long.MAX_VALUE;

        boolean hasOutputs = false;
        boolean allIdle = true;
        for (OutputState outputState : watermarkOutputs) {
            if (!outputState.isIdle()) {
                minimumOverAllOutputs = Math.min(minimumOverAllOutputs, outputState.getWatermark());
                allIdle = false;
            }
            hasOutputs = true;
        }

        // if we don't have any outputs minimumOverAllOutputs is not valid, it's still
        // at its initial Long.MAX_VALUE state and we must not emit that
        // 如果算子任务不消费任何分区,它不会发出任何水位线,这里是不是就是kafka消费者要小于kafka主题的原因所在???
        if (!hasOutputs) {
            return;
        }

        if (allIdle) {// 如果当前算子任务处于空闲时间,标识空闲,以便后续算子可以继续推进
            underlyingOutput.markIdle();
        } else if (minimumOverAllOutputs > combinedWatermark) {
            combinedWatermark = minimumOverAllOutputs;
            underlyingOutput.emitWatermark(new Watermark(minimumOverAllOutputs));
        }
    }```

    
相关推荐
TK泰妞14 分钟前
从零搭建高效可复用的提示词工作流
大数据·人工智能
兴通物联科技24 分钟前
对俄出口诚实标识 2026 时间节点与产线赋码采集技术方案
大数据·服务器·单片机·嵌入式硬件·深度学习·计算机视觉
数据小玩子34 分钟前
数据合规共治:工业园区多部门协同亩均效益智能评价方案
大数据·数据分析·精益工程
陕西企来客1 小时前
NAP 信息统一治理:构建生成式 AI 时代企业 GEO 增长的坚实底座-企来客科技NAP方法论-企来客科技NAP信息治理实战解析
大数据·人工智能·科技
CubeSandbox1 小时前
沙箱是选项,不是标配:花椒 Agent 平台的架构思考与 Cube 实践
大数据·人工智能·架构
重生之我是小技1 小时前
Selenium自动化爬虫怎么实现?Python实战与反爬应对指南
大数据
55873 生态系统1 小时前
55873 全域文明生态系统:技术价值矩阵与底层创新内核
大数据·人工智能·55873全域文明生态体系·55873操作系统
2601_962355231 小时前
深度解析279模式:【279模式的最新发展趋势2025】行业白皮书
大数据·人工智能·pygame
龙亘川2 小时前
数智赋能民生保障:亘川智城智慧民政系统构建民政一体化业务闭环
大数据·人工智能·智慧城市·开源软件·数据可视化·政务
智商网输送线配件供应2 小时前
广东自动化流水线配件滚筒输送线选型实战:小批量混批采购模式如何重构供应链效率
大数据·重构·自动化