1. flink整体架构以及重要特点
下面这张图是flink的流批统一以及事件驱动的重要概念图
1. flink的特点
1 事件驱动型
事件驱动型运用是一类具有状态的应用,它从一个或者多个事件流中提取数据,并根据到来的事件触发计算,状态更新。类似于kafka这种消息队列都是事件驱动型应用。
事件驱动型概念图
2. 流的世界观
- 有界流:离线数据
- 无界流:实时数据
3. 分层api
2. yarn模式下
1. session-cluster模式
在yarn中初始化一个集群,以后所有的flink job都会向这里提交,这个flink集群常驻在yarn中,除非手动停止(一般是在测试环境中会这样,生成环境一般不会这样搞)
2. 启动
-
启动Hadoop集群
-
启动yarn-session
./yarn-session.sh -n 2 -s 2 -jm 1024 -tm 1024 -nm test -d名词解释:
-n(--container) : taskManager的数量
-s(--slots): 每个taskManager的slot数量,默认一个slot一个core,
-jm: jobManager的内存(MB)
-tm: taskManager的内存(MB)
-nm: yarn的appName(现在yarn的ui上的名字)。
-d: 后台执行
-
执行任务
./flink run -c com.mayishijie.wc.StreamWordCount FlinkTutorial-1.0-SNAPSHOT-jar-with-dependencies.jar --host lcoalhost –port 7777 -
取消yarn-session
yarn application --kill application_1577588252906_0001
2. per-job-cluster模式
每次提交都会创建一个新的flink集群,任务之间互相独立,互不影响,方便管理。任务执行完成之后创建的集群也会消失
启动
和session-cluster的步骤差不多,就是不用启动yarn-session,直接运行任务
2. Flink运行时架构
1. 运行时4大组件
2. 各个组件的职责
1. jobManger(控制一个应用程序执行的主进程)
2. TaskManger
3. ResourceManger
4. dispacher
3. 提交流程
1. 大体流程
2. Yarn下的提交流程详解
其实yarn下无论是flink还是其他,可以参考mr中在yarn下的提交详细流程,其实都差不多
- Flink任务提交后,Client向HDFS上传Flink的Jar包和配置,
- 之后向Yarn ResourceManager提交任务,ResourceManager分配Container资源并通知对应的NodeManager启动ApplicationMaster,
- ApplicationMaster启动后加载Flink的Jar包和配置构建环境,然后启动JobManager,
- 之后ApplicationMaster向ResourceManager申请资源启动TaskManager,ResourceManager分配Container资源后,由ApplicationMaster通知资源所在节点的NodeManager启动TaskManager
- NodeManager加载Flink的Jar包和配置构建环境并启动TaskManager,TaskManager启动后向JobManager发送心跳包,并等待JobManager向其分配任务。
4. 任务调度原理
1. taskManager与slots
1. taskManager与slots的关系图
- 一个worker(TaskManager)是一个JVM进程
- worker能接收多少个task,取决于worker有多少个task slot
- 一个task slot就是taskManager中的资源子集(相当于就是有独立的一块资源集),这也意味着它不用与其它job的subTask竞争管理的内存
- slot目前仅仅是用来隔离task的受管理的内存
- 重点理解6和7:
- task slot是个静态概念,是指taskManager的并发能力(其实就是它拥有多少的资源集,有多少task slot,就有多少的并发能力。可以通过taskmanager.numberOfTaskSlots配置)
- 并行度parallelism是动态概念:就是实际使用taskManager的并发能力(其实就是说:taskManger有很多的task slot,但是我规定只用少数几个,那么就算taskManager有很大的并发能力,但是因为限制只用其中一少部分,那么它的实际并发能力依然比较少),可以通过该参数进行配置parallelism.default。(举例说明:假设一共有3个TaskManager,每一个TaskManager中的分配3个TaskSlot,也就是每个TaskManager可以接收3个task,一共9个TaskSlot,如果我们设置parallelism.default=1,即运行程序默认的并行度为1,9个TaskSlot只用了1个,有8个空闲,因此,设置合适的并行度才能提高效率)
2. 下面这张图就是很好的解释task Slot与parallelism的概念关系
2. 程序与数据流
flink程序都是由3部分组成,source,transformation,sink
- source:读取数据源
- transformation:各种算子处理加工
- sink:负责输出
3. 执行图-ExecutionGraph
- streamGraph:根据用户stream api生成最初的图,表示程序的拓扑结构
- jobGraph:将符合条件的节点chain在一起,减少节点间的流动带来的序列化、反序列化、以及传输带来的消耗
- executionGraph:jobGraph的并行化的版本
- 物理执行图: JobManager 根据 ExecutionGraph 对 Job 进行调度后,在各个TaskManager 上部署 Task 后形成的“图”,并不是一个具体的数据结构。
4. 并行度
一个特定算子的子任务(subtask)个数,就是该算子的并行度。
一个流程序,其中某个算子的拥有最大的并行度,可以任务就是该流程序的并行度。
stream算子之间的传输有2种模式
-
one-to-one(类似spark中的窄依赖)
stream(比如在source和map operator之间)维护着分区以及元素的顺序
-
Redistributing(类似于spark中的宽依赖)
stream(map()跟keyBy/window之间或者keyBy/window跟sink之间)的分区会发生改变。每一个算子的子任务依据所选择的transformation发送数据到不同的目标任务
5. 任务链(Operator Chains)
相同并行度的one to one操作,Flink这样相连的算子链接在一起形成一个task,原来的算子成为里面的一部分。将算子链接成task是非常有效的优化:它能减少线程之间的切换和基于缓存区的数据交换,在减少时延的同时提升吞吐量。链接的行为可以在编程API中进行指定