flink-1.12.1源码阅读之计算流程


  这里以源码工程中提供的一个完整实例,来看flink流计算的完成流程,在此过程中会结合其核心概念进行展开解析.

1 调试

  这里使用flink源码工程中的examples子工程,直接在streaming工程里的WordCount(org.apache.flink.streaming.examples.wordcount)类中打断点,如下
在这里插入图片描述

2 flink流计算的整体概述

2.1 flink流计算相关的任务概念

  Flink的流计算针对计算本身分为job和task,task由不同的算子组成.
  先从最小的算子说起.算子代表一个完整的计算逻辑,比如map等,这些算子本身有并行度的概念,比如map的并行度为4,那么在同一时刻最多就是在4个线程中并行执行该map操作.算子分为shuffle算子和普通算子,这个和spark的操作是一样的.
  Task可以是单个算子,也可以是一串算子组成的链条,这个划分的依据就是当算子的并行度发生变化或者出现shuffle算子(例如分组算子keyBy)时,就分为前后两个task,同时还可以手动通过API明确设置,在这前后也会产生两个task。
  subtask或者是子task,就是指这些task的并行度,每个为一个subtask.
  Job为一个作业,由不同的task组成,比如上述的wordCount计算,读取一个字符串然后计算出其中每个单词的个数,该job就由source任务、flatMap任务、keyBy、keyBy后的sum算子和sink这3个任务组成,整个过程就是一个job.

2.2 flink流计算相关的阶段概念

  每个flink的执行作业(job)都可以在时间线上分为三个阶段:
  1 读如数据源
  2 transform操作,包括所有的算子
  3 持久化数据
  数据源就是source相关的操作,transform就是在source之后,sink之前的所有操作,最后就是sink操作,也就是数据的持久化.

3 第一个断点fromElements方法

  该方法就是读如数据源,这里很简单,就是一个字符串,其调用的方法树为
在这里插入图片描述
  其方法比较简单,最后返回一个DataStreamSource对象.这里需要注意的是其上标有五角星形状的FromElementsFunction的构造方法,其使用了序列化器把输入的字符串序列化了,进入该方法
在这里插入图片描述
  可见,在构造方法内已经完成了序列化.

4 第二个断点execute方法

  这是具体的执行方法,里面会涉及flink的一些核心概念,在遇到时会展开分析.
  其调用的方法树为
在这里插入图片描述
  可见,首先是创建streamGraph.

4.1 getStreamGraph方法

  其调用的方法树为
在这里插入图片描述

  核心方法为generate方法,其调用的方法树为在这里插入图片描述
  重要方法为transform方法,此方法根据程序进行了很多流的转换,同时生成每个转换的之前的输入和转换之后的输出,组成带有定点和边的dag图,flink提供了一个StreamGraph可视化显示工具,可以进行查看生成的dag图.

4.2 execute(StreamGraph)方法

  其调用的方法树为
在这里插入图片描述
  重要方法executeAsync的调用方法树为
在这里插入图片描述
  重要方法为execut,其调用的方法树为
在这里插入图片描述
  重要方法为getJobGraph和submitJob.

4.3 getJobGraph方法

  该方法就是生成job图,进入该方法,其调用的方法树为
在这里插入图片描述
  最后调用的是FlinkPipelineTranslationUtil的getJobGraph方法,其调用的方法树为
在这里插入图片描述
  最终调用的是StreamingJobGraphGenerator的createJobGraph方法,其调用的方法树为
在这里插入图片描述
  从被标注的第一个方法开始,一共有5个重要方法,这些方法的逻辑如下:
  第一个方法,设置改job图的每个计算阶段的hash值,用作唯一标识每个计算阶段
  第二个方法,设置dag图的边
  第三个方法,设置dag图的顶点
  第四个方法,设置每个算子的内存使用比例,这个比例非0即1,不存在0和1之间的小数
  第五个方法,设置保存点
  该方法最终创建了jobGraph,然后提交到执行器去执行.

4.4 submitJob方法

  submitJob方法的调用方法树为
在这里插入图片描述
  可见,最后是调用了Dispatcher的internalSubmitJob方法,其调用的方法树为
在这里插入图片描述
  最后调用的就是persistAndRunJob方法,其调用的方法树为
在这里插入图片描述

4.5 生成executionGraph

  执行图就是在上面的runJob中生成的,其调用方法树为:
在这里插入图片描述
  重要方法为JobManagerRunnerImpl的构造方法,其调用的方法树为
在这里插入图片描述

  重要方法为JobMaster的构造方法,其调用的方法树为
在这里插入图片描述
  其中createScheduler方法的调用方法树为
在这里插入图片描述
  重要方法createInstance的调用方法树为
在这里插入图片描述
  DefaultScheduler的构造方法的调用方法树为
在这里插入图片描述
  至此,由SchedulerBase的createExecutionGraph方法开始创建executionGraph,其具体过程就是依据job图,对应定点和边创建execution的顶点和边.

4.6 根据executionGraph执行task

  上面提到的在创建jobMaster的同时也启动了jobMaster,进入其start方法,调用树为
在这里插入图片描述
  重要方法resetAndStartScheduler的调用树为
在这里插入图片描述
  重要方法startSchedulingInternal的调用树为
在这里插入图片描述
  重要方法allocateSlotsAndDeploy的调用树为
在这里插入图片描述
  重要方法deployOrHandleError的调用树为
在这里插入图片描述
  重要方法deploy的调用树为
在这里插入图片描述
  至此,由TaskManagerGateway的submitTask方法就把task提交了,调用的方法就是TaskExecutor类的submitTask方法,进入该方法,其调用方法树为
在这里插入图片描述
  可见,首先创建了task,其次启动了task的run方法,进入其run方法,调用的方法树为
在这里插入图片描述
  主要就是doRun方法,可以预见,此方法很长,其调用的方法树为
在这里插入图片描述
  主要方法就是loadAndInstantiateInvokable和invoke方法,这很明显,就是要执行task中的逻辑了.
  至此,就剩下executionGraph是怎么划分为task的部分没有说了.这部分并不难,根据源码可以看到,其实主要就是根据定点来确定task的划分,由于边代表了数据的输入和输出,所以再结合定点就可以把每一个task都给确定了,读者可以按照本文中给出的源码阅读流程找到该Task的构造方法进去一窥究竟.

4.7 flink的rpc

  Flink的rpc和spark还有hadoop等都不同,其使用了akka来实现,具体各个业务逻辑交由actor来执行.
  Actor的写法已经很固定了,而且flink并没有使用过多的包装来使用actor,整体上也非常直白和简洁,所以这里不再过多的展开叙述.
  Actor是一个非常好的并发框架,本人在有时间时会作为补充做一个原理的介绍和说明.

4.8 slot的概念和共享的解释

  在flink的领域内,slot更接近于近代可插拔的cpu插槽,所以在jvm进程中,flink有意根据slot数目把可使用内存按照内存页的形式进行了平分.这样以来,原本更接近于cpu概念的slot就转变为了可以代表一定内存资源的资源单位,由jvm进程根据task或subtask启动的线程只能占用其slot的内存,不能共享同一进程下其它slot的内存,实现了同一进程内线程的内存隔离,但没有限制cpu的使用,也就是说cpu对这线程并不隔离.
  Slot共享的概念其实容易使人产生疑惑.上面所说,slot是隔离线程使用的内存的,这里的共享并不是指内存共享,而是指不同的task或subTask可以在同一个slot中起线程来执行.比如本来有一个slot只为map类型的task起线程,在共享后也可以为sum类型的task起线程来执行了,这种不再区分task的slot就是共享.

5 总结

  Flink的流计算整体上要经过三层图和最后一步执行来完成,总结起来就是:
  1 flink由客户端提交后,交由dispatcher来分发任务,交由taskExecutor来执行
  2 flink的执行管理由jobManager和taskManager组成,jobManager负责生成executionGraph,之后部署到taskManager上执行
  3 flink使用了akka作为并行框架,整体上来看还是很符合flink的设计实现
  从flink的流计算过程可以看到,其整体设计是非常好的,同时很多概念也是很清晰的,代码质量也是目前我所看过的源码中最好的.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值