背景
![](https://img.haomeiwen.com/i16281566/b69c692e653feeb3.jpg)
从2022-08-07晚上开始该任务触发延时告警,此处省略几十条。
定位问题
该线上Flink提交参数如下,其余参数均是1.0版本的默认值
-D state.backend.incremental=true
--taskManagerMemory=10240
--taskManagerMemory=10240 等价于 taskmanager.memory.process.size=10gb
![](https://img.haomeiwen.com/i16281566/fc708e5eb1159dcb.jpg)
从上图能够看出数据流入变的特别小(kafka topic流入数据一直是稳定的10MB/s),Flink任务数据延时一直是上升趋势,那么一定是程序遇到了性能瓶颈。
![](https://img.haomeiwen.com/i16281566/08218773b292b539.jpg)
从上图能够看到源kafka topic 每个分区的消息滞后几十万条
从grafana监控并不能定位Flink程序哪个调用栈出现了性能瓶颈,打个火焰图看看,如下图:
![](https://img.haomeiwen.com/i16281566/c59e20adfd274816.jpg)
从上面的火焰图可以分析该程序大部分时间都是 rocksdb 在进行写数据与压缩数据,由于subtask子任务较多也占用了很多网络资源进行shuffle,由此得出结论rocksdb内存不够导致磁盘的IO增多,网络传输也是一个性能瓶颈点,我们如何在不增加总体内存的背景下增加rocksdb内存以及网络内存?通过以下配置参数调整内存比例:
-D state.backend.rocksdb.memory.fixed-per-slot=1gb
-D taskmanager.memory.network.max=2gb
-D taskmanager.memory.network.fraction=0.2
运行一段时间后发现该任务还是会有数据延迟,继续定位问题发现该任务的主要瓶颈在于window算子的数据倾斜,如下图所示:
![](https://img.haomeiwen.com/i16281566/d25df7f94dda9731.jpg)
数据倾斜问题一直是分布式计算的难点,如果不处理的话一味的 加资源
起不到任何的效果,反而是对资源的浪费。
数据倾斜由于不是本篇文章分享的重点,如何解决数据倾斜放在下一篇文章分享。
疑问
观测线上Flink 1.10任务带来的思考:
- 通过
taskmanager.memory.process.size=10gb
该参数设置Container内存为10GB,通过Web UI监控发现tm内存远远达不到10GB到底其他的内存哪里去了呢? - Flink的内存是如何划分的呢?
- Flink每一块内存到底有什么作用呢?
Flink内存模型
要想深入了解上面几个问题不得不从Flink的内存模型入手,首先得提一下Flink框架源码所使用的开发语言 Java
,说到 Java
首先会联想到JVM
,相比于 JVM
内存控制Flink框架对于内存的管理更加的丰富,并且让开发者更加精细化的控制Flink程序的每个模块内存,首先我们来看下官放给出的Flink内存模型如下图:
![](https://img.haomeiwen.com/i16281566/f0c11b2bb4e27fb2.png)
Flink内存主要分为两部分:container内存、flink内存,其中内存类型和Spark内存类型一样分为堆内(heap)和堆外(off-heap),各模块内存使用场景及配置参数说明如下:
![](https://img.haomeiwen.com/i16281566/37fd5b12f1bf021e.jpg)
内存计算公式如下:
- JVM Metaspace Memory:默认256MB
- JVM Overhead Memory:默认整个container内存的0.1
实际计算:1024M 0.1 < 192 M ? 192 M : (1024M 0.1 > 1Gb ? 1Gb : 1024M * 0.1) = 192 M
因此默认内存为192MB - Flink Memory:Container Memory - JVM Metaspace - JVM Overhead
- Network Memory: Flink Memory * 0.1
- Manager Memory:Flink Memory * 0.4
- 堆内内存:Flink Memory - Network Memory - Manager Memory
示例
线上 LBS 任务配置如下:
-D state.backend.rocksdb.memory.fixed-per-slot=1gb
-D state.backend.incremental=true
--taskManagerMemory=10240
-D taskmanager.memory.network.max=2gb
-D taskmanager.memory.network.fraction=0.2
-D taskmanager.numberOfTaskSlots=2
实际内存计算如下:
- Flink Memory = 10240 - 256 - 1024 = 8960MB
- Network Memory = 8960 * 0.2 = 1792MB
- Manager Memory = 8960 * 0.4 = 3584MB
- Task Heap Memory = 8960 - 1792 - 3584 - 128 - 128 = 3328MB/3.25GB
每个模块内存如下图:
![](https://img.haomeiwen.com/i16281566/deb308dee4edf7b3.jpg)
Flink Web UI如下图:
![](https://img.haomeiwen.com/i16281566/fda21dbb73c20a3a.jpg)
JVM Heap Memory
实际分配比公式计算出来的结果要多10MB左右,大差不差的能够计算出Flink内存的分布方便开发者根据自身任务的情况调整每一个模块的内存比例以及总体内存。至于差距的这部分内存我也会继续找原因,有知道的大佬评论区可以告诉我哪里计算的有问题。
成果
![](https://img.haomeiwen.com/i16281566/7086a274e7a6c44e.jpg)
该任务优化后一直处于较为稳定的状态,再没有收到过延时告警
总结
- 该篇文章能够让我们清楚线上Flink问题的定位流程是什么样的
- 基于Flink内存模型能够清楚Flink每一块内存的分配
- Flink每一块内存的作用。
- 加资源并不能解决所有任务的性能问题
网友评论