flink任务运行方式
flink任务提交方式有3种 session、per-job、application三种
flink任务运行底座也有三种,Standalone、yarn、k8s
原则上一个flink任务运行的方式由3*3=9种,但是有些是没法搭配的
yarn:包括yarn-session 、yarn-per-job 、yarn-application
standalone:包括 standalone-session standalone-application,不支持per-job
k8s: 包括 k8s-session、k8s-per-job 、k8s-application
!!!!但是 per-job被官网废弃了,用application替代per-job!!!!

当前主流就是yarn-application
flink历史服务器
flink任务失败或停止之后,flink webui 就看不到了,因此日志就只能到yarn上去看或者taskmanager所在的服务器去看,这样很不方便,因此flink提供了历史服务器,能够看已经退出的flink任务,而且flink不管是standalone还是yarn都支持。
1)创建存储目录
hadoop fs -mkdir -p /logs/flink-job
2)在 flink-config.yaml中添加如下配置
jobmanager.archive.fs.dir: hdfs://hadoop102:8020/logs/flink-job
historyserver.web.address: hadoop102
historyserver.web.port: 8082
historyserver.archive.fs.dir: hdfs://hadoop102:8020/logs/flink-job
historyserver.archive.fs.refresh-interval: 5000
3)启动历史服务器
bin/historyserver.sh start
4)停止历史服务器
bin/historyserver.sh stop
5)在浏览器地址栏输入:http://hadoop102:8082 查看已经停止的 job 的统计信息
flink任务并行度、slot(槽位)、taskmanger数量
假如完成同一件事需要8个人,那么这个任务的并行度就是8,再假如一个人完成这件事需要使用一个工具台,也就是需要8个slot,再假如一个一个车间(taskmanager)只有6个工具台,那这个任务就有问题(有两人闲着)。
并行度:一个任务的并行量
slot(槽位):能够提供完成任务的环境的数量
再接着假如,一个车间(taskmanager)能够提供10个slot(槽位),请问并行度多少为最佳?
答案:当然是10个,每个人都不闲着。
上述任务是发生在一个车间(taskmanager),如果有n个车间(taskmanager),效率又会有n倍(约)提升
那么问题来了,在standalone和k8s底座上起多少个taskmanager是我们手动确定的,在yarn底座上运行的时候,我们没有事先启动好taskmanager,是任务启动之后自己分配的taskmanager,yarn的资源有很多,不可能都用来运行taskmanager,是怎么确定运行taskmanager数量的呢?
答:在1.5版本之后,taskmanager的数量是动态计算,根据slot和并行度进行计算

翻译::::::::::::::
更新返工作业部署的配置
Flink重做的集群和作业部署组件改善了与资源管理器的集成,实现了动态资源分配。这些更改的一个结果是,在向YARN和Mesos提交应用程序时,您不再需要指定容器的数量。Flink会根据应用程序的并行性自动确定容器的数量。
尽管部署逻辑已完全重新设计,但我们的目标是避免不必要地更改以前的行为以实现平稳过渡。尽管如此,您应该在conf/flink-conf.yaml中更新或了解一些选项。
尚未完全支持分配具有多个插槽的taskmanager。因此,我们建议使用单个插槽配置taskmanager,即设置taskmanager.numberOfTaskSlots: 1
如果发现新部署模式存在任何问题,则始终可以通过配置mode: legacy切换回pre-1.5行为。
请通过发布到邮件列表或打开JIRA问题,向Flink社区报告您注意到的任何问题或可能的改进。
注意: 我们计划在下一版本中删除传统模式。
taskmanager数量计算方式:
TaskManager 数 = Job 的最大并行度 / 每个TaskManager 分配的任务槽数slot,结果向上取整
上述公式告诉了我们一个问题,如果slot小,并行度很大,最后导致的taskmanager就会很多,最终导致yarn的资源不足以运行所有的taskmanager,最终导致任务失败



默认一个taskmanager 只有一个slot,那我们把slot槽数设置多一点不就行了么,-Dtaskmanager.numberOfTaskSlots=5 我们设置为5个槽
flink run -t yarn-per-job -c cn.chinaunicom.sdsi.flink.security.test -p 10 \
/home/manager/portal-flink-1.0-jar-with-dependencies.jar
又异常了
Caused by: org.apache.flink.configuration.IllegalConfigurationException: The number of requested virtual cores per node 5 exceeds
the maximum number of virtual cores 4 available in the Yarn Cluster. Please note that the number of virtual cores is set to the number of task slots by
default unless configured in the Flink config with 'yarn.containers.vcores.'
因为我的yarn核数设置为了4(见上方yarn资源图),这里slot设置5,不够用了,因此报错,也就是说slot数,不能高于yarn设置的vcores
调小一点
flink run -t yarn-per-job -c cn.chinaunicom.sdsi.flink.security.test -p 10 \
-Dtaskmanager.numberOfTaskSlots=2 \
/home/manager/portal-flink-1.0-jar-with-dependencies.jar
这样就可以运行了
Flink的内存管理
Taskmanager
我们使用1个并行度,每个容器提供1个slot槽,启动任务
flink run -t yarn-per-job -c cn.chinaunicom.sdsi.flink.security.test -p 1 \
-Dtaskmanager.numberOfTaskSlots=1 \
/home/manager/portal-flink-1.0-jar-with-dependencies.jar

结果发现,启动了2个容器,很明显,一个是taskManager容器,一个是jobManager容器。
一共占用4G内存,两个容器各占2G,内存设置默认都是none,那么这个2G是哪来的?
看一下你的flink/conf/flink-conf.yaml
这两个参数是没有默认值的, 如果你把这两个参数注释掉,你就会发现你的任务无法启动,需要你明确提供这两个参数。
# The total process memory size for the JobManager.
#
# Note this accounts for all memory usage within the JobManager process, including JVM metaspace and other overhead.
jobmanager.memory.process.size: 1600m
# The total process memory size for the TaskManager.
#
# Note this accounts for all memory usage within the TaskManager process, including JVM metaspace and other overhead.
taskmanager.memory.process.size: 1728m
两个参数,虽然不是2G,但是由于yarn容器,内存分配的原因,以1G为单位,向上取整,因此得到了2G
yarn-site.xml
yarn.scheduler.minimum-allocation-mb: 1024mb # 最小内存单元

我们1G内存启动看看效果!
flink run -t yarn-per-job -c cn.chinaunicom.sdsi.flink.security.test -p 1 \
-Dtaskmanager.numberOfTaskSlots=1 \
-Dtaskmanager.memory.process.size=1G \
/home/manager/portal-flink-1.0-jar-with-dependencies.jar
启动之后,打开taskManager,我们能看到这个内存管理图

这个图非常的重要!!
如上图所示,这1G内存使用起来就相当费劲了,不是想象中大家一起用那么简单,这1G内存被分成了好多个内存单元:
| 内存参数 | 解释 | 默认值 |
|---|---|---|
| JVM Metaspace | JVM元空间:JVM 用来存储类元数据的地方,这些元数据包括类的相关信息,比如类的名称、字段、方法等。 | taskmanager.memory.jvm-metaspace.size 默认 256mb |
| JVM Overhead | JVM执行开销:JVM自身运行也是需要内存的,编译、解释、堆内存、堆外内存 | taskmanager.memory.jvm-overhead.fraction,默认 0.1 taskmanager.memory.jvm-overhead.min,默认 192mb taskmanager.memory.jvm-overhead.max,默认 1gb 总进程内存*fraction,如果小于配置的 min(或大于配置的 max)大小,则使用 min/max大小 |
| Network | 网络内存:网络数据交换所使用的堆外内存大小,如网络数据交换缓冲区 | taskmanager.memory.network.fraction,默认 0.1 taskmanager.memory.network.min,默认 64mb taskmanager.memory.network.max,默认 1gb Flink 内存*fraction,如果小于配置的 min(或大于配置的 max)大小,则使用 min/max大小 |
| Task Heap | Task 堆内存:Task任务真正的任务使用的内存,用于存储任务的数据结构、对象实例等 | 堆内:taskmanager.memory.task.heap.size,默认 none,由 Flink 内存扣除掉其他部分的内存得到。 |
| Task Off-Heap | Task 堆外内存:Task任务堆外内存 | taskmanager.memory.task.off-heap.size,默认 0,表示不使用堆外内存 |
| Managed Memory | 托管内存:用于 RocksDB State Backend 的本地内存和批的排序、哈希表、缓存中间结果,如果你不用RocksDB做状态后端,也没有很大的攒批情况,可以把这个内存调小(它默认占40%) | taskmanager.memory.managed.fraction,默认 0.4 taskmanager.memory.managed.size,默认 none 如果 size 没指定,则等于 Flink 内存*fraction |
| Framework Heap/Framework Off-Heap | FLINK框架堆内存/堆外内存:TaskManager自身占用的内存,他和task Heap是可以混用的 | 堆内:taskmanager.memory.framework.heap.size,默认 128MB 堆外:taskmanager.memory.framework.off-heap.size,默认 128MB |
计算方式:
基于Yarn模式,一般参数指定的是总进程内存,taskmanager.memory.process.size,
比如指定为1G
总进程内存 = Flink内存+JVM内存(JVM Metaspace + Overhead)
JVM Metaspace => 256mb
JVM Overhead = 1G * 0.1 < 192mb => 192mb
Flink内存 = 1G - 256mb - 192mb => 576mb
Network = 576mb*0.1 < 64mb=>64mb
Managed Memory = 576mb* 0.4 =>230.4mb
Framework Heap/Framework Off-Heap = 128+128 =>256mb
Task Heap = 576mb-256mb-64mb-230.4mb =>25.6mb
可以和上边那个内存图进行对比,计算逻辑是正确的。
Task Heap 1G内存只被分到了25MB(虽然25MB,但是可以使用框架内存Framework Heap,他两个是一块用的),因此一个taskmanager至少分配2G内存,才比较可靠。
比如指定为2G
总进程内存 = Flink内存+JVM内存(JVM Metaspace + Overhead)
JVM Metaspace => 256mb
JVM Overhead = 2G * 0.1 > 192mb => 204.8mb
Flink内存 = 2G - 256mb - 204.8mb => 1587.2mb
Network = 1587.2mb*0.1 > 64mb=>158.7mb
Managed Memory = 1587.2mb* 0.4 =>634.88mb
Framework Heap/Framework Off-Heap = 128+128 =>256mb
Task Heap = 1587.2mb-256mb-158.7mb-634.88mb =>537.62mb
可以自己启动一个flink任务,验证一下,flink自带的example,nc -lk 2222测试一下,这个任务默认是1个并行
flink run -d -t yarn-per-job SocketWindowWordCount.jar --hostname hdp01 --port 2222
这个地方介绍了常见的内存错误。
https://nightlies.apache.org/flink/flink-docs-release-1.14/zh/docs/deployment/memory/mem_trouble/
资源配置方案
调整yarn的资源分配器
资源分配器,我们改成 DominantResourceCalculator 基于CPU+内存,默认的只基于内存,每个容器只分配1个cpu
vi ${HADOOP_HOME}/etc/hadoop/capacity-scheduler.xml
<property>
<name>yarn.scheduler.capacity.resource-calculator</name>
<!-- <value>org.apache.hadoop.yarn.util.resource.DefaultResourceCalculator</value>-->
<value>org.apache.hadoop.yarn.util.resource.DominantResourceCalculator</value>
<description>
The ResourceCalculator implementation to be used to compare
Resources in the scheduler.
The default i.e. DefaultResourceCalculator only uses Memory while
DominantResourceCalculator uses dominant-resource to compare
multi-dimensional resources such as Memory, CPU etc.
</description>
</property>

调整yarn关于容器的相关配置
打开yarn的dashboard,关注以下红框的属性值
尤其要注意Minimum Allocation和 Maximum Allocation
- Minimum Allocation:为每个容器分配的最小资源([memory-mb (unit=Mi), vcores]),第一个值是内存mb,第二个值是cpu数
- Maximum Allocation:为每个容器分配的最大资源([memory-mb (unit=Mi), vcores]),第一个值是内存mb,第二个值是cpu数
也就是说,不管你的yarn集群有多大,如果这两个值你不调整好,创建出来的容器是受限的。我们修改资源分配器也是为了能使创建出来的容器足够强大

vi ${HADOOP_HOME}/etc/hadoop/yarn-site.xml
<configuration>
<property>
<!-- 单个容器可申请的最小内存量(以 MB 为单位),默认1G-->
<name>yarn.scheduler.minimum-allocation-mb</name>
<value>1024</value>
</property>
<property>
<!-- 单个容器可申请的最大内存量(以 MB 为单位),默认8G-->
<name>yarn.scheduler.maximum-allocation-mb</name>
<value>8192</value>
</property>
<property>
<!-- 单个容器可申请的最小 CPU 核心数 ,默认1个-->
<name>yarn.scheduler.minimum-allocation-vcores</name>
<value>1</value>
</property>
<property>
<!-- 单个容器可申请的最大 CPU 核心数 ,默认4个 -->
<name>yarn.scheduler.maximum-allocation-vcores</name>
<value>4</value>
</property>
</configuration>
任务提交设置
要基于最大并行度进行设置,假设我最大10个并行度
- jobManager内存 2-4G 足够,并行度大就4G
- slot数最好能被并行度整除,保证所有container的slot数均衡,否则就有的container资源浪费。
- 如果我设置2个slot,那就会产生5个taskmanager,一个taskmanager2个核。(设置了DominantResourceCalculator后,slot:vcores 自动就是1:1了,也可以手动指定 -Dyarn.containers.vcores=2,如果不配DominantResourceCalculator,手动指定也不生效 )
- taskManager内存与slot的比例可以设置为 2G:1,一个slot分配2G内存,但是总的ts内存不要特别大,最好不要超过8G(yarn默认的最大容器内存),一定要注意核数多了一定要分配足够的内存(如果太少,每个核心分配到的内存太少,多核发挥不出优势),这两个条件相互制约也是我们设置资源的依据
- 比如上述方案如果我设置slot为5,那么就会产生2个taskmanager,每个taskmanager的核心为5,那匹配的内存就得是10G,这样超过了yarn的限制,最好不要,如果非要这样用需要修改yarn的资源配置参数 yarn.scheduler.maximum-allocation-mb
- 如果我设置为3,那么需要启动4个taskmanager,每个为3核,那么会导致cpu资源不足
TaskManager 数 = Job 的最大并行度 / 每个TaskManager 分配的任务槽数slot,结果向上取整
# 自动设置taskmanager核数,与slot 1:1
flink run -t yarn-per-job -c cn.chinaunicom.sdsi.flink.security.test -p 10 \
-Djobmanager.memory.process.size=2G \
-Dtaskmanager.memory.process.size=4G \
-Dtaskmanager.numberOfTaskSlots=2 \
/home/manager/portal-flink-1.0-jar-with-dependencies.jar
# 手动指定taskmanager核数
flink run -t yarn-per-job -c cn.chinaunicom.sdsi.flink.security.test -p 10 \
-Djobmanager.memory.process.size=2G \
-Dtaskmanager.memory.process.size=4G \
-Dtaskmanager.numberOfTaskSlots=2 \
-Dyarn.containers.vcores=1\
/home/manager/portal-flink-1.0-jar-with-dependencies.jar

1907



被折叠的 条评论
为什么被折叠?



