Flink源码学习(6)StreamTask的初始化和执行
Stream初始化
taskExecutor执行一个Task
当taskExecutor接受提交Task执行的请求,会调用:
CompletableFuture<Acknowledge> submitTask(
TaskDeploymentDescriptor tdd, JobMasterId jobMasterId, @RpcTimeout Time timeout);
提交Task到TM
提交Job过来的JobManager和现在Active JobManager不是同一个的时候,就拒绝提交
初始化task的时候,内部初始化一个执行线程,就是task类启动,把TDD变成Task
Task task = new Task( jobInformation, taskInformation, tdd.getExecutionAttemptId(), tdd.getAllocationId(), tdd.getProducedPartitions(), tdd.getInputGates(), memoryManager, sharedResources, taskExecutorServices.getIOManager(), taskExecutorServices.getShuffleEnvironment(), taskExecutorServices.getKvStateService(), taskExecutorServices.getBroadcastVariableManager(), taskExecutorServices.getTaskEventDispatcher(), externalResourceInfoProvider, taskStateManager, taskManagerActions, inputSplitProvider, checkpointResponder, taskOperatorEventGateway, aggregateManager, classLoaderHandle, fileCache, taskManagerConfiguration, taskMetricGroup, partitionStateChecker, getRpcService().getScheduledExecutor(), channelStateExecutorFactoryManager.getOrCreateExecutorFactory(jobId));
-
task的构造方法
-
封装一个TaskInfo,把task在执行过程中必备的描述信息放入
this.taskInfo = new TaskInfo( taskInformation.getTaskName(), taskInformation.getMaxNumberOfSubtasks(), executionAttemptID.getSubtaskIndex(), taskInformation.getNumberOfSubtasks(), executionAttemptID.getAttemptNumber(), String.valueOf(slotAllocationId));
- 创建shuffle context
final ShuffleIOOwnerContext taskShuffleContext = shuffleEnvironment.createShuffleIOOwnerContext( taskNameWithSubtaskAndId, executionId, metrics.getIOMetricGroup());
- 初始化ResultPartition和ResultSubPartition
- 一个Task的执行有输入和输出,关于输出的抽象ResultPartition和ResultSubPartition
- 具体实现是resultPartition
- 批处理创建一个ReleaseOnConsumptionResultPartition,流处理创建ResultPartition
- subPartition的数量等于下游task的个数
- 输入的抽象是InputGate和InputChannel,也会init
-
singleInputGate创建一个给inputGate
创建inputChannel数组,有两种情况,createUnknownInputChannel也可能是createKnownInputChannel,正常情况是known的。当前是本地获取数据的话localRecoveredInputChannel,正常是remote
-
- 初始化一个thread,task的构造方法
- sourceStreamTask和streamTask初始化
- 创建recordWriter
- 处理输入streamTask.processInput=new mailboxProcess
- 创建状态后端stateBackend
- 通过stateBackend创建checkpointStorage
- 获取分流器
- 用于调整并行度,如果上下游streamNode的并行度一致就用forwardPartition分发策略
- 如果不一致就使用RebalancePartition实现
提交job到standalone集群运行的时候,在client构建streamGraph顶点式streamNode,边是streamEdge的时候,根据生成的transformation为streamGraph生成stramNode,生成Node的hi后判断如果该operator是streamSource的话,就会指定该streamTask的invokableClass为sourceStreamTask
task.Run
流式引擎,上游task执行完一条数据计算,就会发送结果给下游task,规则由streamPartitioner来指定一条数据在一个task执行完毕之后,就要发送给下游另外一个task,这个过程,网络数据传输过程,由netty支持的,具体是由inputChannel实现的
- 状态从created、改为deploying
-
拉起resultPartitionWriter和inputGate
- 构造task的时候,就已经初始化过了
- 注册result Partition Writer
- 如果注册过了就报错
- inputChannel分配buffer
- 包装task的各种组件 environment
-
通过反射实例化streamTask
-
sourceStreamTask
- 是flink job最开始的task,对接source,有一个专门的线程接受数据
- source用于产生data的一个线程
- oneInputStreamTask
-
- 状态从deploying改为running
- 启动streamTask
- streamTask正常结束处理buffer数据
- 状态从running改为finished
state管理源码剖析flink具有有状态计算的特点state是flink job的task运行过程中产生的中间数据,辅助task执行计算,同时存储中间状态帮助flink job的重启恢复。保存状态非常重要state要配合checkpoint机制保证flink失败之后正确的回复错误flink自己周期性的快照叫checkpoint,手动保存叫savepointflink状态分类keyedState具体的key绑定,只能在keyedStream上的函数和算子中使用OperatorState和operator的一个特定的并行实例绑定,例如kafka connectorKeyed state也可以看作是operator state的一种分区partition形式,每一个key都关联一个状态分区state-partition无论是operator state还是keyed state都有两种形式:Managed state和raw state。所有跟state有关的都由stateBackend完成,核心有abstractStateBackend,三种存储类型FileSystem将state存储在taskmanager的内存中,checkpoint存储在文件系统内存中,适合存储量大,文件系统中需要序列化反序列化的开销速度慢点,但是比memory好Memory 保存在内存中,很快,适合小state任务,不能上生产。存储在内存中RocksDB,基于内存的数据库系统,把状态存储在reocksDB,ckeckpoint存在文件系统,比memory快,GC少,支持异步snapshot持久化,用于存储state量大的,window窗口很长的一些job合适
-
StreamTask运行
-
beforeInvoke
- operatorChain的初始化,recoveredChannelState初始化
-
当第一个operator执行完毕的时候就有collector收集计算结果再去调用第二个operator执行processElement,通过output收集处理之后的结果数据
- userFunction.run:function->transformation->streamOperator,headOperator的run方法
- socket连接读数据
- channelSelector确定目标channel决定record被分发到哪一个分区
- runMailboxLoop
不停的处理mail
- afterInvoke
完成task结束之前的操作
- cleanUpInvoke