在之前的文章中,我们从高级抽象到底层细节各个层面全面介绍了 Flink 网络栈的工作机制。作为这一系列的第二篇文章,本文将在第一篇的基础上更进一步,主要探讨如何监视与网络相关的指标,从而识别背压等因素带来的影响,或找出吞吐量和延迟的瓶颈所在。本文将简要介绍处理背压的手段,而之后的文章将进一步研究网络栈微调的话题。如果你不是很熟悉网络栈的知识,强烈建议先阅读本系列的第一篇文章 《原理解析 | 深入了解 Apache Flink 的网络协议栈》。
监控
网络监控工作中最重要的环节可能就是监控背压了,所谓背压是指系统接收数据的速率高于其处理速度 [1]。这种现象将给发送者带来压力,而导致它的原因可能有两种情况:
- 接收器很慢。
这可能是因为接收器本身就遇到了背压,所以无法以与发送方相同的速率继续处理数据;也有可能是接收器因为垃圾回收工作、缺少系统资源或 I/O 瓶颈而暂时卡住了。
- 网络通道很慢。
这种情况可能和接收器没有(直接)关系,我们说这时是发送器遇到了背压,因为在同一台机器上运行的所有子任务共享的网络带宽可能供不应求了。请注意,除了 Flink 的网络栈之外可能还有其他网络用户,例如源(source)和汇(sink)、分布式文件系统(检查点、网络附加存储)、日志记录和指标监测等。我们之前的一篇关于容量规划的文章介绍了更多相关内容。
[1] 如果你不熟悉背压,不了解它与 Flink 的交互方式,建议阅读我们在 2015 年发表的关于背压的文章。
当背压出现时,它将一路向上游传导并最终到达你的源,还会减慢它们的速度。这本身并不是一件坏事,只是表明你缺乏足够的资源处理当前的负载。但你可能想要做一些改进,在不动用更多资源的前提下处理更高的负载。为此你需要找到(1)瓶颈在哪里(位于哪个任务 / 操作符)和(2)产生瓶颈的原因。Flink 提供了两种识别瓶颈的机制:
- 直接通过 Flink 的 Web UI 及其背压监视器识别
- 间接通过一些网络指标识别。
Flink 的 Web UI 大概是快速排除故障时的首选,但它存在一些缺点,我们将在下面解释。另一方面,Flink 的网络指标更适合持续监控和推断是哪些瓶颈导致了背压,并分析这些瓶颈的本质属性。我们将在下文中具体介绍这两个部分。在这两种情况下,你都需要从所有的源和汇中找出背压的根源。调查工作的起点一般来说是最后一个承受背压的操作符;而且最后这个操作符很可能就是背压产生的源头。
背压监视器
背压监视器只暴露在 Flink 的 WebUI[2] 中。由于它是仅在请求时才会触发的活动组件,因此目前无法通过监控指标来提供给用户。背压监视器通过 Thread.getStackTrace() 对 TaskManager 上运行的所有任务线程采样,并计算缓存请求中阻塞任务的样本数。这些任务之所以会阻塞,要么是因为它们无法按照网络缓冲区生成的速率发送这些缓存,要么就是下游任务处理它们的速度很慢,无法保证发送的速率。背压监视器将显示阻塞请求与总请求的比率。由于某些背压被认为是正常 / 临时的,所以监视器将显示以下状态:
- OK,比率 ≤ 0.10
- LOW,0.10 < 比率 ≤ 0.5
- HIGH,0.5 < 比率 ≤ 1
虽说你也可以调整刷新间隔、样本数或样本之间的延迟等参数,但通常情况下这些参数用不着你来调整,因为默认值提供的结果已经够好了。
[2] 你还可以通过 REST API 访问背压监视器:/jobs/:jobid/vertices/:vertexid/backpressure
背压监视器可以帮助你找到背压源自何处(位于哪个任务