• Flink 背压详解及调优处理


    Flink 背压详解及调优处理
    一、网络流控及反压的介绍
    1)概述

    网络流控是为了在上下游速度不匹配的情况下,防止下游出现过载,网络流控有静态限速和动态反压两种手段:

    Flink 1.5 之前是基于 TCP 流控 + bounded buffer 实现反压

    Flink 1.5 之后实现了自己托管的 credit – based 流控机制,在应用层模拟 TCP 的流控机制

    2)反压的理解

    Flink 拓扑中每个节点(Task)间的数据都以阻塞队列的方式传输,下游来不及消费导致队列被占满后,上游的生产也会被阻塞,最终导致数据源的摄入被阻塞。

    反压(BackPressure)通常产生于这样的场景:短时间的负载高峰导致系统接收数据的速率远高于它处理数据的速率。

    许多日常问题都会导致反压,例如,垃圾回收停顿可能会导致流入的数据快速堆积,或遇到大促、秒杀活动导致流量陡增。

    3)反压的危害

    反压如果不能得到正确的处理,可能会影响到 checkpoint 时长和 state 大小,甚至可能会导致资源耗尽甚至系统崩溃

    1.影响 checkpoint 时长

    barrier 不会越过普通数据,数据处理被阻塞也会导致 checkpoint barrier 流经整个数据管道的时长变长,导致 checkpoint 总体时间(End toEnd Duration)变长。

    2.影响 state 大小

    barrier 对齐时,接受到较快的输入管道的 barrier 后,它后面数据会被缓存起来但不处理,直到较慢的输入管道的 barrier 也到达,这些被缓存的数据会被放到 state 里面,导致 checkpoint 变大。

    这两个影响对于生产环境的作业来说是十分危险的,因为 checkpoint 是保证数据一致性的关键,checkpoint 时间变长有可能导致 checkpoint 超时导致失败,而 state 大小同样可能拖慢 checkpoint 甚至导致 OOM 。

    二、定位反压节点

    解决反压首先要做的是定位到造成反压的节点,排查的时候,先把 operator chain 禁用,方便定位到具体算子

    1)利用 Flink Web UI 定位

    Flink Web UI 提供了 SubTask 级别的反压监控,1.13 版本以前是通过周期性对 Task 线程的栈信息采样,得到线程被阻塞在请求 Buffer(意味着被下游队列阻塞)的频率来判断该节点是否处于反压状态。

    默认配置下,这个频率在 0.1 以下则为 OK,0.1 至 0.5 为 LOW,而超过 0.5 则为 HIGH。

    Flink 1.13 优化了反压检测的逻辑(使用基于任务 Mailbox 计时,而不在基于堆栈采样),并且重新实现了作业图的 UI 展示:Flink 现在在 UI 上通过颜色和数值来展示繁忙和反压的程度。

    在这里插入图片描述

    1.通过 WebUI 看到 Map 算子处于反压

    在这里插入图片描述

    分析瓶颈算子如果处于反压状态,那么有两种可能性:

    A.该节点的发送速率跟不上它的产生数据速率。

    这一般会发生在一条输入多条输出的 Operator(比如 flatmap)。这种情况,该节点是反压的根源节点,它是从 Source Task 到 Sink Task 的第一个出现反压的节点

    B.下游的节点接受速率较慢,通过反压机制限制了该节点的发送速率。

    这种情况,需要继续排查下游节点,一直找到第一个为 OK 的一般就是根源节点

    总体来看,如果我们找到第一个出现反压的节点,反压根源要么是就这个节点,要么是它紧接着的下游节点

    通常来讲,第二种情况更常见。如果无法确定,还需要结合 Metrics 进一步判断。

    2)利用 Metrics 定位

    监控反压时会用到的 Metrics 主要和 Channel 接受端的 Buffer 使用率有关,最为有用的是以下几个 Metrics:

    在这里插入图片描述

    三、反压的原因及处理

    注意:反压可能是暂时的,可能是由于负载高峰、CheckPoint 或作业重启引起的数据积压而导致反压。如果反压是暂时的,应该忽略它。另外,请记住,断断续续的反压会影响我们分析和解决问题。

    定位到反压节点后,分析造成原因的办法主要是观察 Task Thread。按照下面的顺序,一步一步去排查。

    1)查看是否数据倾斜

    在实践中,很多情况下的反压是由于数据倾斜造成的,这点我们可以通过 Web UI 各个 SubTask 的 Records Sent 和 Record Received 来确认,另外 Checkpoint detail 里不同 SubTask 的 State size 也是一个分析数据倾斜的有用指标。

    在这里插入图片描述

    2)使用火焰图分析

    如果不是数据倾斜,最常见的问题可能是用户代码的执行效率问题(频繁被阻塞或者性能问题),需要找到瓶颈算子中的哪部分计算逻辑消耗巨大。

    最有用的办法就是对 TaskManager 进行 CPU profile,从中我们可以分析到 Task Thread 是否跑满一个 CPU 核:如果是的话要分析 CPU 主要花费在哪些函数里面;如果不是的话要看 Task Thread 阻塞在哪里,可能是用户函数本身有些同步的调用,可能是 checkpoint 或者 GC 等系统活动导致的暂时系统暂停。

    1.开启火焰图功能
    rest.flamegraph.enabled: true #默认 false
    
    • 1
    2.WebUI 查看火焰图

    在这里插入图片描述

    2.分析火焰图

    颜色没有特殊含义,具体查看:

    ➢ 纵向是调用链,从下往上,顶部就是正在执行的函数

    ➢ 横向是样本出现次数,可以理解为执行时长。

    看顶层的哪个函数占据的宽度最大。只要有"平顶"(plateaus),就表示该函数可能存在性能问题

    3)分析 GC 情况

    TaskManager 的内存以及 GC 问题也可能会导致反压,包括 TaskManager JVM 各区内存不合理导致的频繁 Full GC 甚至失联。通常建议使用默认的 G1 垃圾回收器。

    可以通过打印 GC 日志(-XX:+PrintGCDetails),使用 GC 分析器(GCViewer 工具)来验证是否处于这种情况。

    ➢ 在 Flink 提交脚本中,设置 JVM 参数,打印 GC 日志:

    -Denv.java.opts="-XX:+UseG1GC -XX:+PrintGCDetails -XX:+PrintGCDateStamps"
    
    • 1

    ➢ 下载 GC 日志:

    因为是 on yarn 模式,运行的节点一个一个找比较麻烦。可以打开 WebUI,选择 JobManager 或者 TaskManager,点击 Stdout,即可看到 GC 日志,点击下载按钮即可将 GC 日志通过 HTTP 的方式下载下来。

    在这里插入图片描述

    ➢ 分析 GC 日志:

    通过 GC 日志分析出单个 Flink Taskmanager 堆总大小、年轻代、老年代分配的内存空间、Full GC 后老年代剩余大小等。

    最重要的指标是 Full GC 后,老年代剩余大小这个指标,按照《Java 性能优化权威指南》这本书 Java 堆大小计算法则,设 Full GC 后老年代剩余大小空间为 M,那么堆的大小建议为 3 ~ 4 倍 M,新生代为 1 ~ 1.5 倍 M,老年代应为 2 ~ 3 倍 M。

    4)外部组件交互

    如果发现 Source 端数据读取性能比较低或者 Sink 端写入性能较差,需要检查第三方组件是否遇到瓶颈,还有就是做维表 join 时的性能问题。

    例如

    Kafka 集群是否需要扩容,Kafka 连接器是否并行度较低,HBase 的 rowkey 是否遇到热点问题,是否请求处理不过来,ClickHouse 并发能力较弱,是否达到瓶颈……

    关于第三方组件的性能问题,需要结合具体的组件来分析,最常用的思路:

    1)异步 io+热缓存来优化读写性能

    2)先攒批再读写

  • 相关阅读:
    Java:join方法详解
    前端面试题之【CSS】
    【我不熟悉的javascript】02. 新手菜鸟们,求你不要再用console.log了,console.table用起来,提升效率的小方法
    C++————类与对象<一>
    C语言经典100例题(56-60)--画圆;画方;画线
    C++面向对象
    docker技术学习
    中国智能马桶行业未来发展及投资可行性建议报告2022-2028年版
    差分方程模型:基金运作与管理
    asm:operand number missing after %-letter
  • 原文地址:https://blog.csdn.net/m0_50186249/article/details/132855715