资源配置调优

  • 1. 内存设置
  • 1.TaskManager内存模型
  • (1)特定内存
  • (2)框架内存
  • (3)Task内存
  • (4)网络内存
  • (5)托管内存
  • 2. 实战分析各块内存大小
  • 3. 如何配置内存资源
  • 2. CPU资源的合理使用
  • 1 使用DefaultResourceCalculator策略
  • 2 使用DominantResourceCalculator策略
  • 3 使用DominantResourceCalculator策略并指定core个数
  • 4 总结
  • 3. 并行度设置
  • 3.1 全局并行度计算案例
  • 3.2 Source端并行度配置
  • 3.3 Transform端并行度配置
  • 3.4 Sink端并行度配置



  • Flink性能调优的第一步,就是为任务分配合适的资源,在一定范围内,增加资源的分配与性能的提升是成正比的,实现了最优的资源配置后,在此基础上再考虑进行后面论述的性能调优策略。
  • 提交方式主要是yarn-per-job,资源的分配在使用脚本提交Flink任务时进行指定。

标准的Flink任务提交脚本(Generic CLI 模式)

  • 从1.11开始,增加了通用客户端模式,通用客户端模式说白了就是 flink run -t,此模式下参数使用-D <property=value>指定
  • 以前提交job的方式是:flink run -m yarn-cluster,参数用-yD <property=value>
  • 二者区别仅此而已
bin/flink run \
-t yarn-per-job \
-d \
-p 5 \ 指定并行度
-Dyarn.application.queue=test \ 指定yarn队列
-Djobmanager.memory.process.size=1024mb \ 指定JM的总进程大小
-Dtaskmanager.memory.process.size=1024mb \ 指定每个TM的总进程大小
-Dtaskmanager.numberOfTaskSlots=2 \ 指定每个TM的slot数
-c com.atguigu.flink.tuning.UvDemo \
/opt/module/flink-1.13.1/myjar/flink-tuning-1.0-SNAPSHOT.jar

参数列表:
https://nightlies.apache.org/flink/flink-docs-release-1.13/docs/deployment/config/


1. 内存设置

1.TaskManager内存模型

TaskManager是干活的进程,也是Java进程,运行在JVM上;flink 内存资源调优主要就是针对TaskManager;

总进程内存

flinkyarn资源配置 flink资源调度_flinkyarn资源配置


job配置参数

taskmanager.memory.process.size

指的就是总进程内存

(1)特定内存

flinkyarn资源配置 flink资源调度_大数据_02


JVM 特定内存:JVM本身使用的内存,包含JVM的metaspace和over-head


1)JVM metaspace:JVM元空间

taskmanager.memory.jvm-metaspace.size,默认256mb


2)JVM over-head执行开销

:JVM执行时自身所需要的内容,包括线程堆栈、IO、编译缓存等所使用的内存。


taskmanager.memory.jvm-overhead.fraction,默认0.1


taskmanager.memory.jvm-overhead.min,默认192mb


taskmanager.memory.jvm-overhead.max,默认1gb


总进程内存*fraction,如果小于配置的min(或大于配置的max)大小,则使用min/max大小

(2)框架内存

flinkyarn资源配置 flink资源调度_flinkyarn资源配置_03


框架内存:Flink框架,即TaskManager本身所占用的内存,不计入Slot的资源中。


堆内:taskmanager.memory.framework.heap.size,默认128MB


堆外:taskmanager.memory.framework.off-heap.size,默认128MB

(3)Task内存

Task执行用户代码时所使用的内存
堆内:taskmanager.memory.task.heap.size,默认none 不开启,由Flink内存扣除掉其他部分的内存得到。
堆外:taskmanager.memory.task.off-heap.size,默认0,表示不使用堆外内存

(4)网络内存

网络数据交换所使用的堆外内存大小,如网络数据交换缓冲区
位于堆外

  • taskmanager.memory.network.fraction,默认0.1
  • taskmanager.memory.network.min,默认64mb
  • taskmanager.memory.network.max,默认1gb

Flink内存*fraction,如果小于配置的min(或大于配置的max)大小,则使用min/max大小

(5)托管内存

flinkyarn资源配置 flink资源调度_flinkyarn资源配置_04


用于RocksDB State Backend 的本地内存和批的排序、哈希表、缓存中间结果。


位于堆外

  • taskmanager.memory.managed.fraction,默认0.4
  • taskmanager.memory.managed.size,默认none

如果size没指定,则等于Flink内存*fraction,制定了则以指定的为准

2. 实战分析各块内存大小

flinkyarn资源配置 flink资源调度_JVM_05


flinkyarn资源配置 flink资源调度_flink_06


flinkyarn资源配置 flink资源调度_flink_07

3. 如何配置内存资源

提交任务

flinkyarn资源配置 flink资源调度_flinkyarn资源配置_08

从flink1.12版本,WebUI就提供了TaskManager的内存模型图

flinkyarn资源配置 flink资源调度_并行度_09


可以对比上面分析的内存占比,是一模一样的;

查看TaskManager日志

flinkyarn资源配置 flink资源调度_并行度_10

那么给一个flink job多少内存合适? 以及各个部分内存给多少

  • TaskManager默认给2G
  • 如下图,每块内存使用率 TaskManager的WebUI上都有;
  • 整体内存: 如果每块内存占比都很高,可以调高整个JVM进程内存;并且流计算还需要考虑数据洪峰,需要保留一定余地
  • 对于管理内存,它的作用是提供k-v类型的状态来用的,说白了就是给RocksDB使用的,如果我们的状态后端没有使用RocksDB,这块内存给0
  • 对于其他的部分,哪块紧缺,提高哪一块的占比
  • 一般性建议:一个TaskManager在2-8G比较合适,可以先给2G做测试使用,然后看情况进行调整

Flink是实时流处理,关键在于资源情况能不能抗住高峰时期每秒的数据量,通常用QPS/TPS来描述数据情况。

2. CPU资源的合理使用

1 使用DefaultResourceCalculator策略

flinkyarn资源配置 flink资源调度_并行度_11


flinkyarn资源配置 flink资源调度_大数据_12

  • cpu资源主要指的就是core数量;
  • 疑问:为什么提交job的时候调整job并行度为5,但是Vcore个数没有调整?

容器数量的计算方式

  • 在提交参数中,并行度设置的是5,每个TaskManager2个slot;
    至少5个slot,任务才能跑,需要使用3个TaskManager,也就是3个容器;
    JobManager自己也需要一个容器,所以一共占用4个容器;

每个容器的线程数(core数)

现象说明:

  • 默认情况下,一个TaskManager有几个slot就会申请几个Core;
  • 我们在提交任务的时候指定了每个TaskManager2个slot,意味着每个TM申请2个Core,一共6个Core;加上JobManager 一共7个Core;为什么只有4个?

原因: Yarn调度器

对于公平调度器 不会有这种问题,而容量调度器 会有这种问题;

Hadoop除了四个 -site.xlm配置文件,还有一个capacity-scheduler.xml配置文件专门用于配置容量调度器:

flinkyarn资源配置 flink资源调度_JVM_13


其内部有一个资源计算器的配置:

flinkyarn资源配置 flink资源调度_flinkyarn资源配置_14


因此如果我们需要调整容器的cpu core数,需要修改资源计算器;

2 使用DominantResourceCalculator策略

调整如下:

flinkyarn资源配置 flink资源调度_并行度_15


使用Dominant资源计算器;

他的计算规则:内存+cpu

调整完了记得将此文件分发一下,并且重启Yarn!

验证

flinkyarn资源配置 flink资源调度_JVM_16

  • TaskManager3个,占用3个容器,每个容器vcore=2,总vcore=2*3=6,因为默认单个容器的vcore数=单TM的slot数
  • yarn重启完毕后,重新提交job;现象如下,占用了4个container,7个cpu,符合之前的计算!

3 使用DominantResourceCalculator策略并指定core个数

在提交flink job的时候,强行指定yarn 容器的Vcore个数:

flinkyarn资源配置 flink资源调度_JVM_17


现象:

flinkyarn资源配置 flink资源调度_flinkyarn资源配置_18


分析:

JobManager 强行占有一个线程;

指定的并行度5 ,每个TaskManager2个slot,因此需要3个TaskManager,也就是3个容器;

每个容器强行分配3个Vcore,所以TaskManager占9个Vcore

所以一共10个;

4 总结

除了调整slot 并发度以外,还可以指定多给点线程;
slot有共享机制,一个slot可能会有多个task,也就是说一个slot可能有一个到多个线程;

默认情况下,线程数和slot个数 1:1就够了;这里只是提供如何提高cpu资源的方式;

还需要注意一点就是在指定yarn 线程数的时候,不要超过yarn配置的默认值(8),如果还需要往上调,就需要修改yarn配置文件

3. 并行度设置

并行度和内存一样没有固定的原则,和代码逻辑有很大关系;
并行度可以全局设置,也可以针对每一个算子进行设置;

并行度设置回顾
(1)配置文件指定的默认并行度 【1】
(2)job提交参数指定 -p
(3)代码中 env 指定全局并行度
(4)代码中算子后面指定算子级别并行度
优先级别:(4)> (3) > (2) > (1)

那么并行度应该给多少呢?

1.压测 获取单个并行度的处理上限

开发完一个flink job之后,先进行压测,任务并行度给10以下,测试单个并行度的处理上限,观察有没有产生反压,产生反压说明某个地方出现瓶颈处理不过来;

查看产生反压的节点 或者 直接看source(source数据没有经过处理),看source的每个子任务(每个并行度)每秒钟能往下游发送多少数据,能够观察到单个并行度的处理上限

获取单个并行度的处理上限后, 需要根据QPS来获取并行度:

  • 总QPS/单并行度处理能力 = 并行度

如何知道QPS?

  • 要处理的数据源的总QPS应该是心中有数的,也就是每秒的数据量;不要用平均值,建议使用高峰期的
  • 比如:一个不大不小的公司,大概百万日活左右,一天有1亿左右的数据,平均1000多条每秒,高峰就在2000到20000左右,也就是平均在2m左右,高峰在20m/s; source端在产生反压的情况下 平均5000条/s,所以4个并行度刚刚好,一般再乘以1.2,做一点冗余保障!

2.那么如何压测?

压测本质就是不断地灌入数据,考验软件负载能力;

方式1:自己造数据往kafka写,由flink消费;从生产环境拉数据
方式2:如果自己造数据量不够大,就先不让flink消费,让数据积压在kafka中一段时间,再开启flink程序泄洪!这样很容易达到反压

压测的意义?

  • 不能只从QPS去获取并行度,因为每个人写的代码不一样、数据不一样(比如有的字段少,有的字段多,一条数据的处理繁杂程度不同),所以最好先压测,用高峰期的QPS,查看并行度平均处理上限,然后 并行度*1.2 富余一些资源;
  • 对于kafka数据源的,并行度可以和topic分区数保持一致,简单验证一下大概能抗住 就ok了
  • 一般压测给10以下就够了,除非是大厂,数据量能够达到PB级别,QPS及其高,并行度可能大几十甚至上百,默认最大并行度是128

3.1 全局并行度计算案例

全局并行度设置是个粗犷的设置方式;

UV代码案例

flinkyarn资源配置 flink资源调度_flink_19

flinkyarn资源配置 flink资源调度_大数据_20

提交作业

flinkyarn资源配置 flink资源调度_flink_21

在webUI上查看反压情况

flinkyarn资源配置 flink资源调度_JVM_22

  • flink1.13版本后,每个task都能查看反压情况(busy程度)
  • 早期版本,如下图所示:

flinkyarn资源配置 flink资源调度_flinkyarn资源配置_23

有反压情况后,查看source

可以查看每个并行度的数据量:

flinkyarn资源配置 flink资源调度_JVM_24

flinkyarn资源配置 flink资源调度_大数据_25


可以看出来 单并行度瓶颈大概为7000条/s

生产环境高峰期QPS假设30000条/s

那么就给5个并行度往上就够了

3.2 Source端并行度配置

  • 如果全局并行度设置感觉效果不好,或者有浪费,就需要更细粒度的设置;
  • 一些繁忙的算子并行度设置大些。

flinkyarn资源配置 flink资源调度_flinkyarn资源配置_26

3.3 Transform端并行度配置

flinkyarn资源配置 flink资源调度_flinkyarn资源配置_27

为什么设置为2的次幂?和keyBy原理有关

  • keyBy的分区器用的是键组分区器,经过两次hash获取一个id值;
  • 分区号 = id值 * 下游算子并行度 / 最大并行度值(128)

3.4 Sink端并行度配置

flinkyarn资源配置 flink资源调度_JVM_28