精通Flink项目优化(二.反压处理)

反压处理

反压(BackPressure)通常产生于这样的场景:短时间的负载高峰导致系统接收数据的速率远高于它处理数据的速率。许多日常问题都会导致反压,例如,垃圾回收停顿可能会导致流入的数据快速堆积,或遇到大促、秒杀活动导致流量陡增。反压如果不能得到正确的处理,可能会导致资源耗尽甚至系统崩溃。
反压机制是指系统能够自己检测到被阻塞的 Operator,然后自适应地降低源头或上游数据的发送速率,从而维持整个系统的稳定。Flink 任务一般运行在多个节点上,数据从上游算子发送到下游算子需要网络传输,若系统在反压时想要降低数据源头或上游算子数据的发送速率,那么肯定也需要网络传输。所以下面先来了解一下 Flink 的网络流控(Flink 对网络数据流量的控制)机制。

反压现象及定位

Flink 通过对运行中的任务进行采样来确定其反压,如果一个 Task 因为反压导致处理速度降低了,那么它肯定会卡在向 LocalBufferPool 申请内存块上。那么该 Task 的stack trace 应该是这样:

java.lang.Object.wait(Native Method)
o.a.f.[...].LocalBufferPool.requestBuffer(LocalBufferPool.java:163) 
o.a.f.[...].LocalBufferPool.requestBufferBlocking(LocalBufferPool.java:133) [...]

监控对正常的任务运行有一定影响,因此只有当 Web 页面切换到 Job 的BackPressure 页面时,JobManager 才会对该 Job 触发反压监控。默认情况下,JobManager 会触发 100 次 stack trace 采样,每次间隔 50ms 来确定反压。Web 界面 看 到 的 比 率 表 示 在 内 部 方 法 调 用 中 有 多 少 stack trace 被 卡 在LocalBufferPool.requestBufferBlocking(),例如: 0.01 表示在 100 个采样中只有 1 个被卡在LocalBufferPool.requestBufferBlocking()。采样得到的比例与反压状态的对应关系如下:

OK: 0 <= 比例 <= 0.10
LOW: 0.10 < 比例 <= 0.5
HIGH: 0.5 < 比例 <= 1

Task 的状态为 OK 表示没有反压,HIGH 表示这个 Task 被反压。

Flink Web UI 定位产生反压的位置

在 Flink Web UI 中有 BackPressure 的页面,通过该页面可以查看任务中 subtask的反压状态,如下两图所示,分别展示了状态是 OK 和 HIGH 的场景。排查的时候,先把 operator chain 禁用,方便定位。
精通Flink项目优化(二.反压处理)_第1张图片

Metrics 定位反压位置

当某个 Task 吞吐量下降时,基于 Credit 的反压机制,上游不会给该 Task 发送数据,所以该 Task 不会频繁卡在向 Buffer Pool 去申请 Buffer。反压监控实现原理就是监控Task 是否卡在申请 buffer 这一步,所以遇到瓶颈的 Task 对应的反压⻚⾯必然会显示OK,即表示没有受到反压。如果该 Task 吞吐量下降,造成该 Task 上游的 Task 出现反压时,必然会存在:该Task 对应的 InputChannel 变满,已经申请不到可用的 Buffer 空间。如果该 Task 的InputChannel 还能申请到可用 Buffer,那么上游就可以给该 Task 发送数据,上游 Task 也就不会被反压了,所以说遇到瓶颈且导致上游 Task 受到反压的 Task 对应的InputChannel 必然是满的(不考虑⽹络遇到瓶颈的情况)。从这个思路出发,可以对该 Task 的 InputChannel 的使用情况进行监控,如果 InputChannel 使用率 100%,那么 该 Task就是要找的反压源 。
精通Flink项目优化(二.反压处理)_第2张图片

反压的原因及处理

可能是暂时的,可能是由于负载高峰、CheckPoint 或作业重启引起的数据积压而导致反压。暂时的反压,可以忽略

  • 系统资源
    检查涉及服务器基本资源的使用情况,如 CPU、网络或磁盘 I/O。

针对特定的资源调优 Flink
通过增加并行度或增加集群中的服务器数量来横向扩展
减少瓶颈算子上游的并行度,从而减少瓶颈算子接收的数据量(不建议,可能造成整个Job 数据延迟增大)

  • 垃圾回收(GC)
    长时间GC暂停会导致性能问题。
  • CPU/线程瓶颈
    一个或几个线程导致 CPU 瓶颈,而整个机器的 CPU 使用率仍然相对较低,则可能无法看到 CPU 瓶颈
  • 线程竞争
    subtask 可能会因为共享资源上高负载线程的竞争而成为瓶颈。考虑在用户代码中查找同步开销、锁竞争,尽管避免在用户代码中添加同步。
  • 负载不平衡
    如果瓶颈是由数据倾斜引起的,可以尝试通过将数据分区的 key 进行加盐或通过实现本地预聚合来减轻数据倾斜的影响。
  • 外部依赖
    Source端数据读取性能比较低或者 Sink 端写入性能较差,需要检查第三方组件是否遇到瓶颈。
    举栗:Kafka 集群是否需要扩容,Kafka 连接器是否并行度较低,HBase 的 rowkey 是否遇到热点问题。

你可能感兴趣的:(#,Flink,flink)