赞
踩
Flink集群的架构,也是典型的主从架构模型,启动Flink,它会启动JobManager
以及TaskManager
进程,这里以standalone模式来讲解其运行时的架构以及一些细节,集群模式后面的文章汇介绍到。
JobManager
是master主节点,它主要负责资源的分配、任务的调度以及集群的管理。TaskManager
是从节点,如果单独运行在一台机器上则可以称作一个slave节点。主从节点之间通过心跳机制保持联系,当我们从client提交一个job的时候,会将job提交到jobmanager
主节点,然后由主节点分配到各个slave节点。各个节点之间消息的通信使用akka
框架来完成,数据的传输基于Netty
框架来完成。整个架构如下图所示:
提交的job会分配给集群中的slave节点去执行,即由每个节点上的TaskManager
来执行,在每一个TaskManager
中,所有的资源会被进行划分(这里指内存等资源,但不包括CPU),被划分为多个slot
,整个job被划分为多个task,被分配到这些slot
中执行,每个slot
对应与一个task,但这并不是说一个slot
只能运行一个task,slot的数量代表task的并行度,因为我们可以通过slot
共享的方式让多个task共享一个slot
,从而充分利用集群的资源。
一个task是提交的job中的一个或者多个operator的组合,如果是多个operator组合而成,则也可以成为一个operatorChain
。在同一个TaskManager
中的task会共享TCP连接(通过多路复用)以及心跳消息以减小开销。
为了提高更加高效的执行提交的job,Flink会尽可能地将多个operator连接成一个operatorChain
。以wordcount为例,下图中将KeyAggregation
和sink
两个operator合并,这是因为这两个操作合并之后并不会改变整个拓扑结构。
要想将多个operator连接成一个operatorChain
,需要满足以下几点条件:
slot group
中,可以手动指定。Always
,即可以与上下游连接(map,flatmap,filter算子的chain策略默认为Always)。Always
或者HEAD
(即只能与下游连接,不能与上游连接,Source默认为HEAD)。Shuffle
操作,即为Forward
。使用operatorChain
之后,会有如下的优点:
我们也可以在程序中手动指定OperatorChain
:
someStream.map(..)
)调用startNewChain()
来指示从该operator开始一个新的chain(与前面截断,不会被chain到前面)。StreamExecutionEnvironment.disableOperatorChaining()
来全局禁用chaining
。someStream.filter(...).slotSharingGroup(“name”)
。上面我们提到多在TaskManager
中会划分为多个slot
,在slot
中执行task,这个task是由多个operator连接在一起的chain组成的。我们可以通过slot
共享的方式来充分利用集群的资源。
在默认的情况下,Flink执行subtask共享slot
,条件是这些subtask必须是来自一个job的task的subtask,在有些情况下,有些一个slot可能持有一个job的整个pipeline流程。共享slot
有以下节点好处:
slot
数量和job中的最大并行度一致,这样就不需要去计算task的数量。slot
则可能非密集型操作会和密集型操作占用相同的资源,共享slot
之后,充分利用了资源,可以使得每个TaskManager
的每个slot
数量较少,节约资源,并且每个slot
具有相同的负载。
在Flink中,使用SlotSharingGroup
类来实现slot
之间的共享,尽可能的让多个subtask
共享一个slot
。保证一个job下并行度相同的subtask共享一个slot
,算子默认的group
为default
(即默认共享slot)。
有些情况下,我们并不需要一些subtask共享slot
,所以会使用下面的方式来为一个算子重新指定一个group。someStream.filter(...).slotSharingGroup("group1")
,即filter
算子重新 指定了group1
,即不与前后操作在同一个chain中。在一些场景下,适当的指定group可以减少单个slot
中的负载。
接着我们说下task slot
的数量和task并行度的关系,其中每个task中的slot
的数量和task中的最高并行度相同。
那么在整个job中,所需的slot
数量是每个task的最大并行度之和。如下图所示,需要的slot
数量为30。
在Flink中的transformation之间,存在多种分区策略,如果每个操作的并行度为1,那么对应的着一对一的分区策略,另外还有几种不同的分区策略。
dataStream.shuffle()
。dataStream.rebalance()
。dataStream.rescale()
。dataStream.broadcast()
。dataStream.partitionCustom(partitioner, "someKey")
。需要注意区分Round-robin
和Rescaling
策略,前者是全局划分的,后者是针对单个TaskManager
来划分的,这样可以避免一些网络连接和开销,提高效率。如下图所示,只针对同一个TaskManager
来划分,而不是全局划分。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。