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

相关推荐
百胜软件@百胜软件23 分钟前
破局存量时代:消费电子品牌的数字化突围与增长密码
大数据·零售数字化·数智中台·珠宝行业
小王毕业啦30 分钟前
2009-2025年 华证ESG年度季度评级评分数据 xlsx
大数据·人工智能·数据挖掘·数据分析·社科数据·实证分析·经管数据
_codemonster41 分钟前
系统分析师案例刷题(五)系统分析、系统设计和需求工程
大数据
2601_9577875843 分钟前
数据驱动的多平台内容矩阵运营效果分析与闭环优化技术
大数据·人工智能·矩阵
189228048611 小时前
NV265固态MT29F32T08GSLBHL8-24QMES:B
大数据·服务器·人工智能·科技·缓存
一切皆是因缘际会2 小时前
AI技术新风口:边缘计算与智能体协同,解锁产业落地新范式
大数据·人工智能·安全·ai·架构·语音识别
znhb993 小时前
从分治到协同:一体化联合脱硫脱硝的技术逻辑与实践路径
大数据
冯RI375II694874 小时前
机械产品CE-MD认证怎么申请
大数据
淡海水5 小时前
ComfyUI全面掌握-知识点详解——基础示例:文生图与图生图实操(参数+案例)
大数据·人工智能·算法·comfyui
aisifang005 小时前
企业级GPT-Image2实战测评:从生成到生产
大数据·数据库·人工智能