每个工作单元的输出被称作resultpartition,每个resultpartition又根据下游输出结果的不同分区被细分为resultsubpartition,与下游的inputchannel一一对应。
flink网络栈是flink中的核心组件,是flink-runtime模块的一部分。它连接了所有taskmanager中独立的工作单元(subtask)。这是数据交换的核心部分,任务的吞吐量和延迟都与它息息相关,可以说flink的网络栈决定了flink框架本身性能的好坏。
不同于taskmanager、jobmanager之间通信所使用的akka rpc框架,flink网络栈采用了更底层的网络api,使用的是netty框架。
它抽象了以下三个概念的不同设置。
工作单元的输出类型和调度类型是紧密交织在一起的,两者的特定组合才有效。pipelined result partition是流式的输出,流式输出需要将数据发送到一个正在工作的工作单元,因此目标任务就需要在上游结果下发之前或者在任务启动之初完成部署。批作业产出有限的结果,而流式作业产出无限的结果。
为了理解真实的数据流转,我们假想一个有4个并发的任务,部署在两个分别有2个slot的taskmanager上。在flink中,不同的任务可能会共享同一个slot, 通过slot 共享组机制,一个taskmanager可以提供多个slot来运行一个任务的多个工作单元。
taskmanager 1 运行工作单元a.1、a.2、b.1 和 b.2, 而taskmanager 2 运行工作单元a.3、a.4、b.3和b.4。假设a和b之间的shuffle方式是keyby(), 这样在每一个taskmanager上都有2×4个逻辑连接,有些走本地传输,有些是通过网络传输,如图1所示。
▲图1 工作单元部署
不同任务之间的每个(远程)网络连接都将在flink网络栈中获得自己的tcp通道,如果同一个任务的不同工作单元被调度到同一个taskmanager上,那么它们将复用tcp连接用于连接远程tm(多路复用)。在我们的例子中,a.1 → b.3、a.1 → b.4 以及a.2 → b.3、a.2 → b.4将会复用一个tcp连接,如图2所示。
▲图2 数据交换
每个工作单元的输出被称作resultpartition,每个resultpartition又根据下游输出结果的不同分区被细分为resultsubpartition,与下游的inputchannel一一对应。在这个阶段,flink已经不再单独处理每条记录了,而是将一组序列化完的数据打包并复制到networkbuffer中,然后经由netty传输到下游算子。
本文摘编于《flink技术内幕:架构设计与实现原理》,经出版方授权发布。(书号:9787111696292)转载请保留文章来源。