Flink Source源码解析

Source

Source执行时由SourceOperatorCoordinator和SourceReader两部分组成,SourceOperatorCoordinator执行SourceSplitEnumerator逻辑,管理SourceSplit, 将SourceSplit分配给SourceReader;SourceReader则读取SourceSplit的具体内容, 传递给SourceOutput发送给下游。

Source接口抽象了工厂方法,可生产SplitEnumerator和SourceReader, 因此,自定义Source时主要关注实现自定义SourceReader和SourceEnumerator。

SourceReader与SourceEnumerator通信图:

OperatorCoordinator&SplitEnumerator

OperatorCoordinator是在JobMaster启动时创建的,包括SourceOperatorCoordinator, SourceOperatorCoordinator会调用Source接口的createEnumerator方法生产SourceSplitEnumerator。

在创建ExecutionJobVertex时,在initialize方法中会为每个ExecutionJobVertex创建OperatorCoordinatorHolder, OperatorCoordinatorHolder持有对应OperatorID的OperatorCoordinator, 其中SourceOperator对应的SourceCoordinator是通过SourceCoordinatorProvider::getCoordinator创建出来。

SourceCoordinator启动时会调用Source::createEnumerator创建SplitEnumerator并启动,流程如下:

复制代码
JobMaster::onStart
JobMaster::startJobExecution
JobMaster::startScheduling
SchedulerBase::startScheduling
DefaultOperatorCoordinatorHandler::startAllOperatorCoordinators
DefaultOperatorCoordinatorHandler::startOperatorCoordinators
OperatorCoordinatorHolder::start
SourceCoordinator::start
Source::createEnumerator
SplitEnumerator::start

SourceCoordinator启动后就可以处理SourceReader的请求,比如请求Split分配事件RequestSplitEvent,SourceReader注册事件ReaderRegistrationEvent, Watermark报告ReportedWatermarkEvent

SourceReader

SourceReader是SourceOperator在启动时创建,SourceOperator和SourceCoordinatorProvider由SourceOperatorFactory创建。

SourceTask启动时加载SourceOperator,创建SourceReader, 向SourceOperatorCoordinator注册Reader后启动Reader, 向SourceCoordinator发送RequestSplitEvent事件。

SourceReader启动流程如下:

复制代码
TaskManager.Task::run
TaskManager.Task::doRun
TaskManager.Task::restoreAndInvoke //调用TaskInvokable.invoke方法
StreamTask::invoke
    StreamTask::restoreInternal
    SourceOperatorStreamTask::init //创建StreamTaskSourceInput
    SourceOperator::initReader
    Source::createReader  //创建SourceReader
    StreamTask::restoreGates
    OperatorChain::initializeStateAndOpenOperators
    SourceOperator::open 
    SourceOperator::registerReader  //注册Reader
    SourceReader::start //启动Reader, 可向Coordinator发送RequestSplitEvent请求Split
StreamTask::runMailboxLoop
MailboxProcessor::runMailboxLoop
StreamTask::processInput
StreamOneInputProcessor::processInput
StreamTaskSourceInput::emitNext 
SourceOperator::emitNext
	SourceOperator::emitNextNotReading
	SourceOperator::initializeMainOutput //创建Source ReaderOutput
SourceReader::pollNext  //循环调用从Queue获取RecordsWithSplitIds数据传递给RecordEmitter发送出去
SourceReader::moveToNextSplit 
SplitContext::getOrCreateSplitOutput //为每个split创建SourceOutput
RecordEmitter::emitRecord
SourceOutput::collect //发送数据到下游
RequestSplitEvent

SourceReader启动后在start方法中向SourceCoordinator发送RequestSplitEvent事件请求Split, SourceCoordinator通过SplitEnumerator获取Split封装成AddSplitEvent返回给SourceReader

SourceCoordinator处理RequestSplitEvent流程:

复制代码
DefaultOperatorCoordinatorHandler::deliverOperatorEventToCoordinator
OperatorCoordinatorHolder::handleEventFromOperator
SourceCoordinator::handleEventFromOperator
SourceCoordinator::handleRequestSplitEvent   //判断是否有可用split
SplitEnumerator::handleSplitRequest  
SplitEnumeratorContext::assignSplit  //返回split给SourceReader
SourceCoordinatorContext::assignSplits
SourceCoordinatorContext::assignSplitsToAttempts //封装AddSplitEvent消息发送给SourceReader

SingleThreadMultiplexSourceReaderBase

为方便自定义SourceReader, Flink提供了SingleThreadMultiplexSourceReaderBase/SingleThreadFetcherManager实现单线程单分片串行或多分片多路同时读取模型。 SourceReader处理AddSplitEvent事件时会创建一个线程执行SplitFetcher逻辑,将获取的split信息传递给SplitReader, 只要存在未完成的split, SplitFetcher线程就会不断调用SplitReader::fetch获取RecordsWithSplitIds,将RecordsWithSplitIds存入Queue中 给SourceReader主线程消费

AddSplitEvent事件处理流程:

复制代码
SourceOperator::handleOperatorEvent
SourceOperator::handleAddSplitsEvent
SourceReaderBase::addSplits
SplitContext::new 创建SplitContext, 记录split状态信息
SingleThreadFetcherManager::addSplits  //添加split
SingleThreadFetcherManager::createSplitFetcher  //创建SplitFetcher线程并启动执行
SplitFetcher::new //Feacher控制中心,保存分配的split信息,以及从split读取的数据
FetchTask::new  //创建FetchTask, 从split读取数据,放入Queue
SplitFetcher::addSplits //封装成AddSplitsTask
AddSplitsTask::new

SplitFetcher::run //优先执行AddSplitsTask,将split信息传递给SplitReader,其次调用FetchTask,只要当前的SplitFetcher还有分配的split未读取完成,会不断调用FetchTask::run方法读取数据
AddSplitsTask::run
SplitReader::handleSplitsChanges 
FetchTask::run 
SplitReader::fetch //获取RecordsWithSplitIds

自定义SourceReader时如果继承自SingleThreadMultiplexSourceReaderBase,则主要实现SplitReader逻辑,关注如何根据split信息从数据源获取记录。

Flink CDC中各种数据源SourceReader的实现就是继承自SingleThreadMultiplexSourceReaderBase。

Ref:

https://cwiki.apache.org/confluence/display/FLINK/FLIP-27%3A+Refactor+Source+Interface

https://zhuanlan.zhihu.com/p/454440159

相关推荐
武子康19 小时前
大数据-236 离线数仓 - 会员指标验证、DataX 导出与广告业务 ODS/DWD/ADS 全流程
大数据·后端·apache hive
武子康2 天前
大数据-235 离线数仓 - 实战:Flume+HDFS+Hive 搭建 ODS/DWD/DWS/ADS 会员分析链路
大数据·后端·apache hive
DianSan_ERP2 天前
电商API接口全链路监控:构建坚不可摧的线上运维防线
大数据·运维·网络·人工智能·git·servlet
够快云库2 天前
能源行业非结构化数据治理实战:从数据沼泽到智能资产
大数据·人工智能·机器学习·企业文件安全
AI周红伟2 天前
周红伟:智能体全栈构建实操:OpenClaw部署+Agent Skills+Seedance+RAG从入门到实战
大数据·人工智能·大模型·智能体
B站计算机毕业设计超人2 天前
计算机毕业设计Django+Vue.js高考推荐系统 高考可视化 大数据毕业设计(源码+LW文档+PPT+详细讲解)
大数据·vue.js·hadoop·django·毕业设计·课程设计·推荐算法
计算机程序猿学长2 天前
大数据毕业设计-基于django的音乐网站数据分析管理系统的设计与实现(源码+LW+部署文档+全bao+远程调试+代码讲解等)
大数据·django·课程设计
B站计算机毕业设计超人2 天前
计算机毕业设计Django+Vue.js音乐推荐系统 音乐可视化 大数据毕业设计 (源码+文档+PPT+讲解)
大数据·vue.js·hadoop·python·spark·django·课程设计
十月南城2 天前
数据湖技术对比——Iceberg、Hudi、Delta的表格格式与维护策略
大数据·数据库·数据仓库·hive·hadoop·spark
中烟创新2 天前
灯塔AI智能体获评“2025-2026中国数智科技年度十大创新力产品”
大数据·人工智能·科技