Flink源码之StreamTask启动流程

每个ExecutionVertex分配Slot后,JobMaster就会向Slot所在的TaskExecutor提交RPC请求执行Task,接口为TaskExecutorGateway::submitTask

复制代码
CompletableFuture<Acknowledge> submitTask(
        TaskDeploymentDescriptor tdd, JobMasterId jobMasterId, @RpcTimeout Time timeout); 

TaskDeploymentDescriptor 中包含当前Task的执行逻辑、Job信息、输入输出信息

submitTask 方法核心就是构造org.apache.flink.runtime.taskmanager.Task实例,该实例继承自Runnable接口,有个Thread成员变量,构造完成后就启动线程执行Task逻辑。

复制代码
TaskExecutor::submitTask
Task.startTaskThread
Task.run
Task.doRun
Task::setupPartitionsAndGates //初始化Task的输入输出
RuntimeEnvironment::new //封装task执行上下文信息
Task::loadAndInstantiateInvokable //TaskInvokables实例化
StreamTask::new
    StreamTask::createRecordWriterDelegate //创建Writer,为每个StreamEdge创建一个Writer
    StreamTask::createStateBackend //创建StateBackend,一个task一个StateBackend实例
    StreamTask::createCheckpointStorage
    SubtaskCheckpointCoordinatorImpl::new 
Task::restoreAndInvoke
TaskInvokable::restore 
TaskInvokable::invoke //处理输入元素
TaskInvokable::cleanUp

Task的Invokable Class是在StreamGraph中添加Operator形成StreamNode时确定的,对不同的算子有不同的InvokableClass:

  • SourceStreamTask.class //LegacySource算子
  • SourceOperatorStreamTask //Source算子
  • OneInputStreamTask.class //输入是一个算子
  • TwoInputStreamTask:class //输入是两个算子
  • MultipleInputStreamTask.class //输入有多个算子

以上这些类都继承自org.apache.flink.streaming.runtime.tasks.StreamTask

在调用TaskInvokable::restore时会执行:

复制代码
StreamTask::restore
StreamTask::restoreInternal //创建OperatorChain
RegularOperatorChain::new
OperatorChain::new
OperatorChain::createOutputCollector
OperatorChain::createOperatorChain
OperatorChain::createOperator
StreamOperatorFactoryUtil.createOperator  //创建Operator,在每个算子的StreamConfig中定义了每个Operator具体类型,比如StreamMap, StreamFlatMap
SimpleOperatorFactory::createStreamOperator //创建StreamOperator包装了用户函数,, StreamOperator包装了代码中用户函数,会调用用户函数中的open/close等生命周期函数
	AbstractUdfStreamOperator::setup
	AbstractStreamOperator::setup //设置用用自定义函数中的RuntimeContext成员变量
    	StreamingRuntimeContext::new  //
    
StreamTask::init //子类做初始化,创建InputGate、StreamTaskInput、DataOutput及InputProcessor
StreamTask::restoreGates
	StreamTask::createStreamTaskStateInitializer
		StreamTaskStateInitializerImpl::new //
    OperatorChain::initializeStateAndOpenOperators //调用每个Operator的initializeState和Open方法
    	AbstractStreamOperator::initializeState 
			StreamTaskStateInitializerImpl::streamOperatorStateContext //此时会创建keyedStatedBackend和operatorStateBackend
		StreamOperatorStateHandler::new //初始化StreamOperator的stateHandler成员变量,用于状态管理
		StreamOperatorStateHandler::initializeOperatorState
		    StateInitializationContextImpl::new
			AbstractUdfStreamOperator::initializeState//调用用户定义函数中的initializeState方法,可获取Operator State
				StreamingFunctionUtils::restoreFunctionState
		StreamingRuntimeContext::setKeyedStateStore
	StreamOperator::open //调用getRuntimeContext().getState可获取keySate
StreamTask::invoke
StreamTask::runMailboxLoop
MailboxProcessor::runMailboxLoop
StreamTask::processInput

整个过程在StreamTask.java的注释中有说明:

复制代码
 * -- invoke()
 *       |
 *       +----> Create basic utils (config, etc) and load the chain of operators
 *       +----> operators.setup()
 *       +----> task specific init()
 *       +----> initialize-operator-states()
 *       +----> open-operators()
 *       +----> run()
 *       +----> finish-operators()
 *       +----> close-operators()
 *       +----> common cleanup
 *       +----> task specific cleanup()
  1. 首先创建OperatorChain,依次创建出每个StreamOperator
  2. 调用Operator的setup方法,初始化StreamingRuntimeContext
  3. 调用子类init方法初始化
  4. 调用initializeState初始化每个算子的状态,此时会为每个StreamOperator创建keyedStatedBackend和operatorStateBackend,然后会调用用户定义函数中的initializeState方法,用于创建Operator State
  5. 调用算子的open方法,便于用户在自定义函数open中进行初始化,比如初始化keyState
  6. 调用processInput处理流中数据

SourceStreamTask重载了StreamTask::processInput,该方法中直接起一个线程调用SourceFunction::run方法。

OneInputStreamTask则不同,它重载了StreamTask的init方法,在init方法中创建了StreamOneInputProcessor

复制代码
OneInputStreamTask::init
OneInputStreamTask::createCheckpointedInputGate
OneInputStreamTask::createDataOutput //创建StreamTaskNetworkOutput
OneInputStreamTask::createTaskInput //创建StreamTaskNetworkInput
StreamOneInputProcessor::new

在StreamTask::processInput则是调用InputProcessor::processInput不断读取数据进行处理

复制代码
StreamOneInputProcessor::processInput
StreamTaskNetworkInput::emitNext(StreamTaskNetworkOutput)
AbstractStreamTaskNetworkInput::emitNext //循环不断从buffer中读取StreamElement
处理
AbstractStreamTaskNetworkInput::processElement
    StreamTaskNetworkOutput::emitRecord //调用operator的setKeyContextElement和processElement
        OneInputStreamOperator::setKeyContextElement
        AbstractStreamOperator::setKeyContextElement1
        AbstractStreamOperator::setCurrentKey //
            StreamOperatorStateHandler::setCurrentKey //设置状态当前key
        Input::processElement  //调用StreamOperator的processElement方法

以上Task从提交到起线程执行起来的整个过程,在初始化过程中为每个StreamOperator进行状态后端的初始化相当重要,后续处理流的过程中会使用这些状态后端存储管理状态。

相关推荐
com_4sapi27 分钟前
2025 权威认证头部矩阵系统全景对比发布 双榜单交叉验证
大数据·c语言·人工智能·算法·矩阵·机器人
鲸能云2 小时前
政策解读 | “十五五”能源规划下储能发展路径与鲸能云数字化解决方案
大数据·能源
五度易链-区域产业数字化管理平台2 小时前
五度易链大数据治理实战:从数据孤岛到智能决策
大数据
激动的小非2 小时前
电商数据分析报告
大数据·人工智能·数据分析
ITVV3 小时前
湖仓一体部署
大数据·数据湖·湖仓一体
2501_933509074 小时前
无锡制造企税惠防错指南:知了问账帮守政策红利线
大数据·人工智能·微信小程序
F36_9_5 小时前
如何在沟通不畅导致误解后进行修复
大数据
青云交5 小时前
Java 大视界 -- 基于 Java 的大数据实时数据处理在工业互联网设备协同制造中的应用与挑战
flink·spark·工业互联网·预测性维护·实时数据处理·java 大数据·设备协同制造
数字化脑洞实验室5 小时前
智能决策系统落地后如何进行数据集成与安全保障?
大数据