目录
引入
误区:作业资源不够用,加大并行度,加大slot。
flink作业部署时管理员需给定以下参数:
- 并行度:2
- slot:1
- JobManager内存:2G
- TaskManager内存:2G
上面四个参数有什么关系?
首先要了解JobManager和TaskManager是怎么工作的:
flink作业的提交流程:
作业提交给JobManager后,JobManager将作业图(JobGraph)转化为物理可执行的执行图(ExecutionGraph),同时向ResourceManager申请slots资源,ResourceManager启动足够的TaskManager,JobManager就可以把执行图分发给TaskManager,让TaskManager开始工作。
Flink运行时架构-四大组件
- 作业管理器(JobManager)
管理整个作业 - 任务管理器(TaskManager)
真正干活儿的人 - 资源管理器(ResourceManaget)
负责协调资源, Flink里最重要的资源就是slot - 分发器(Dispatcher)
JobManager
作业提交时的主要工作:
第一步:接收提交的jar包、作业图(JobGraph)、逻辑数据流图
第二步:把作业图(JobGraph)转换为执行图(ExecutionGraph), 执行图是物理层面可以执行的,包含了所有可以并发执行的任务,任务彼此之间的数据传输方式等内容。干活的人(TaskManager)拿到执行图就知道自己该做什么事情了。
第三步:向资源管理器(ResourceManager)申请资源,即TaskManager上的slot,申请到了之后就把执行图分发给TaskManager。
Flink作业执行过程中的主要工作:
负责所有需要中央协调的操作,例如检查点(checkpoints)的协调
TaskManager
作业提交时的主要工作:TaskManager启动之后,会向ResourceManager注册它的slots,并且向JobManager提供slots。
Flink作业执行过程中的主要工作:TaskManager会根据执行图(ExecutionGraph)来执行自己的Task任务,通常Flink作业会在多个TaskManager上运行,一个TaskManager相当于一个JVM进程,每个TaskManager可以包含多个slot,slot是任务执行的最小单元,一个slot相当于一个线程,slot的数量代表了这个TaskManager的最大并发执行能力。TaskManager的不同slot之间,内存是隔离的,cpu不是隔离的,如果该TaskManager为单核的,指定的slot却是3,那么在三个slot的实际执行过程中,会来回切换线程,因此推荐slot的个数为CPU的核数。
ResourceManager
ResourceManager主要负责管理slot,Flink为不同环境和资源管理工具提供了不同的ResourceManager,比如YARN, Mesos, K8s,以及standalone部署。
当 standalone模式时,JobManager过来申请slot的时候,slot不足的话,只能等待slot释放。
当 有外部的资源管理平台的时候,JobManager过来申请slot,slot不足的话,ResourceManager会向资源提供平台发起会话请求资源,当有空闲的节点时,可以启动新的TaskManager用来提供slot。
Dispatcher
Dispatcher服务提供REST接口来接收client的job提交,它负责启动JobManager和提交job,同时运行Web UI。Dispatcher的作用可在下图中体现:
总结
通常来说, JobManager只有一个,TaskManager才是真正执行任务的,所以在给定内存时,TaskManager会多给一些。
并行度和slot的关系
算子的并行度为2代表这个算子可以由两个线程来并行执行。
并行度的设置方式:
a、Operrator Level(算子层次)
b、Execution Environment Level(执行环境层次)
c、Client Level(客户端层次)
d、System Level(系统层次)
并行度的优先级Operrator Level>Execution Environment Level>Client Level>System Level
final StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment();
env.setParallelism(3); //=====================执行环境层次设置并行度==================
DataStream<String> text = [...]
DataStream<Tuple2<String, Integer>> wordCounts = text
.flatMap(new LineSplitter())
.keyBy(value -> value.f0)
.window(TumblingEventTimeWindows.of(Time.seconds(5)))
.sum(1).setParallelism(5); //================算子层次设置并行度=================
wordCounts.print();
env.execute("Word Count Example");
./bin/flink run -p 10 ../examples/*WordCount-java*.jar
#=========================提交作业时设置并行度======================
parallelism.default: 1
#====================flink-conf.yaml文件中设置并行度====================
假设下面的算子链:Source算子,map算子,keyBy算子的并行度都设置的是2,Sink算子的并行度设置的是1。
上面4个Task就分成了7个subTask, 但是由于算子链优化,source算子到map算子是forward分区器,map到keyBy是hash分区器,flink会把source算子和map算子合并,最终变成5个subTask,每个subTask都需要一个线程来执行,前面提到过一个slot相当于一个线程,所以这5个subTask需要5个slot 。
假设有两个TaskManager,每个TaskManager的slot为3:
但是实际上flink还有一个slot共享原则,共享的前提是它们都来自同一个Job的不同task的subtask,所以上面这个作业实际上只需要2个slot了。
slot共享的好处:
1.作业算子最大并行度与slot个数保持一致,知道自己作业中算子的最大并行度就知道需要多少个slot了
2.充分利用资源
再回顾刚才的参数配置:
- 并行度:2
- slot:1
- JobManager内存:2G
- TaskManager内存:2G
并行度为2所以默认需要两个slot,我们设置每个TaskManager的slot为1的话,所以总共需要两个TaskManager。每个TaskManager的内存为2个,相当于总共4G的内存。
以前误以为作业处理慢资源不够用时要同时加大并行度和slot:
- 并行度:2
- slot:2
- JobManager内存:2G
- TaskManager内存:2G
这样配置的结果就是只开启了一台TaskManager,这台TaskManager内存为2G, 两个slot平分这2G内存,每个slot的内存为1G , 反而导致作业资源更加不够用了。
总结:TaskManager个数 = 并行度 ➗ slot个数 (向上取整)
举例:
- 并行度:10
- slot:4
会开启3个TaskManager,一共12个slot,其中有2个slot空闲。
补充知识
TaskManager内存模型
TaskManager的内存模型如下,由参数taskmanager.memory.process.size确定,一共包含五部分:堆内存、堆外内存、直接内存、MetaSpace内存以及JVM Overhead内存。
TaskManager内存调优参考链接
其中Task Heap,Task Off-Heap和Managed Memory是slot均分的,其他是slot共享的。
Task Heap是每个Task运行时所需的堆内存,使用Java代码new出来的对象说占用的内存都是存放在Heap(堆)内存中,它由JVM垃圾收集器维护。
Task Off-Heap通常为0B,如果在Flink应用的代码中调用了Native的方法,需要用到off-heap内存。
Managed Memory是由Flink直接管理的off-heap内存,它主要用于排序、哈希表、中间结果缓存、RocksDB的backend
作业提交时Graph的转换
- 首先是通过API会生成transformations,通过transformations会生成StreamGraph
- 因为有些节点可以打包放在一起被JobManage安排调度,所以可将StreamGraph的某些StreamNode Chain在一起生成JobGraph,前两步转换都是在客户端完成
- 最后会将JobGraph转换为ExecutionGraph,相比JobGraph会增加并行度的概念,这一步是在Jobmanager里完成的。