深入了解 Flink 的网络协议栈( 四 )


深入了解 Flink 的网络协议栈

文章插图
 
注释4:如果队列中有更多已完成的 Buffer,我们可以假设 Netty 已经收到通知 。
▼ 在 Buffer 超时后发送
为了支持低延迟应用,我们不能只等到 buffer 满了才向下游发送数据 。因为可能存在这种情况,某种通信信道没有太多数据,等到 buffer 满了在发送会不必要地增加这些少量 record 的处理延迟 。因此,Flink 提供了一个定期 flush 线程(the output flusher)每隔一段时间会将任何缓存的数据全部写出 。可以通过 StreamExecutionEnvironment#setBufferTimeout 配置 flush 的间隔,并作为延迟5的上限(对于低吞吐量通道) 。下图显示了它与其他组件的交互方式:RecordWriter 如前所述序列化数据并写入网络 buffer,但同时,如果 Netty 还不知道有数据可以发送,output flusher 会(3,4)通知 Netty 服务端线程数据可读(类似与上面的“buffer 已满”的场景) 。当 Netty 处理此通知(5)时,它将消费(获取并发送)buffer 中的可用数据并更新 buffer 的读取索引 。Buffer 会保留在队列中——从 Netty 服务端对此 buffer 的任何进一步操作将在下次从读取索引继续读取 。
深入了解 Flink 的网络协议栈

文章插图
 
注释5:严格来说,Output flusher 不提供任何保证——它只向 Netty 发送通知,而 Netty 线程会按照能力与意愿进行处理 。这也意味着如果存在反压,则 Output flusher 是无效的 。
▼ 特殊消息后发送
一些特殊的消息如果通过 RecordWriter 发送,也会触发立即 Flush 缓存的数据 。其中最重要的消息包括 Checkpoint barrier 以及 end-of-partition 事件,这些事件应该尽快被发送,而不应该等待 Buffer 被填满或者 Output flusher 的下一次 Flush 。
▼ 进一步的讨论
与小于 1.5 版本的 Flink 不同,请注意(a)网络 Buffer 现在会被直接放在 Subpartition 的队列中,(b)网络 Buffer 不会在 Flush 之后被关闭 。这给我们带来了一些好处:
  • 同步开销较少(Output flusher 和 RecordWriter 是相互独立的)
  • 在高负荷情况下,Netty 是瓶颈(直接的网络瓶颈或反压),我们仍然可以在未完成的 Buffer 中填充数据
  • Netty 通知显著减少
但是,在低负载情况下,可能会出现 CPU 使用率和 TCP 数据包速率的增加 。这是因为,Flink 将使用任何可用的 CPU 计算能力来尝试维持所需的延迟 。一旦负载增加,Flink 将通过填充更多的 Buffer 进行自我调整 。由于同步开销减少,高负载场景不会受到影响,甚至可以实现更高的吞吐 。
4.2 BufferBuilder 和 BufferConsumer
如果您想更深入地了解 Flink 中是如何实现生产者- 消费者机制,请仔细查看 Flink 1.5 中引入的 BufferBuilder 和 BufferConsumer 类 。虽然读取是以 buffer 为粒度,但写入它是按 record 进行的,因此是 Flink 中所有网络通信的核心路径 。因此,我们需要在任务线程(task thread)和 Netty 线程之间实现轻量级连接,这意味着尽量小的同步开销 。你可以通过查看源代码获取更加详细的信息 。
5. 延迟与吞吐引入网络 Buffer 的目是获得更高的资源利用率和更高的吞吐,代价是让 Record 在 Buffer 中等待一段时间 。虽然可以通过 Buffer 超时给出此等待时间的上限,但可能很想知道有关这两个维度(延迟和吞吐)之间权衡的更多信息,显然,无法两者同时兼得 。下图显示了不同的 Buffer 超时时间下的吞吐,超时时间从 0 开始(每个 Record 直接 Flush)到 100 毫秒(默认值),测试在具有 100 个节点每个节点 8 个 Slot 的群集上运行,每个节点运行没有业务逻辑的 Task 因此只用于测试网络协议栈的能力 。为了进行比较,我们还测试了低延迟改进(如上所述)之前的 Flink 1.4 版本 。
深入了解 Flink 的网络协议栈

文章插图
 
如图,使用 Flink 1.5+,即使是非常低的 Buffer 超时(例如1ms)(对于低延迟场景)也提供高达超时默认参数(100ms)75% 的最大吞吐,但会缓存更少的数据 。
6. 结论了解 Result partition,批处理和流式计算的不同网络连接以及调度类型,Credit-Based 流量控制以及 Flink 网络协议栈内部的工作机理,有助于更好的理解网络协议栈相关的参数以及作业的行为 。后续我们会推出更多 Flink 网络栈的相关内容,并深入更多细节,包括运维相关的监控指标(Metrics),进一步的网络调优策略以及需要避免的常见错误等 。


推荐阅读