可以关注下公众号,专注数据开发、数据架构之路,热衷于分享技术干货。
一、资源抽象
二、资源管理器
资源管理器在Flink中叫做ResourceManager。Flink同时支持不同的资源集群类型,ResourceManager位于Flink和资源管理集群(Yarn、K8s等)之间,是Flink集群资源管理器的抽象,其主要作用如下:
- 申请容器启动新的TM,或者为作业申请Slot。
- 处理JobManager和TaskManager的异常退出。
- 缓存TaskManager(即容器),等待一段时间之后再释放掉不用的容器,避免资源反复地申请释放。
- JobManager和TaskManager的心跳感知,对于JobManager和TaskManager的退出进行对应处理。
Flink中内置了4种ResourceManager,分别对应于不同的资源管理框架,资源管理体系如下:
- YarnResourceManager
Yarn资源管理器,用来对接Yarn,在Yarn集群上启动和运行Flink集群,能够实现动态的资源申请和释放,是使用最多的资源管理器。
- KubernetesResourceManager(K8s)
K8s资源管理器,用来对接K8s,在K8s环境中启动和运行Flink集群。Flink的未来目标是云原生的大数据计算引擎,K8s资源管理器是未来的重要改进方向。
- StandaloneResourceManager
Flink集群自身的管理器,用于资源确定的部署模式,难以在大规模的数据中心中共享资源,一般会选择使用Yarn模式,所以在实际生产环境中使用得不多。
- MesosResourceManager
Mesos资源管理器,用来对接Mesos,在Mesos上启动和运行Flink集群,用得较少。
三、Slot管理器
3.1、Slot管理器
Slot管理器在Flink中叫作SlotManager,是ResourceManager的组件,从全局角度维护当前有多少TaskManager、每个TaskManager有多少空闲的Slot和Slot等资源的使用情况。当Flink作业调度执行时,根据Slot分配策略为Task分配执行的位置。
SlotManager虽然是ResourceManager的组件,但是其逻辑是通用的,并不关心使用了哪种集群资源。
SlotManager功能:
- 对TaskManager提供注册、取消注册、空闲退出等管理动作,注册则集群可用的Slot变多,取消注册、空闲推出则释放资源,还给资源管理集群。
- 对Flink作业,接收Slot的请求和释放、资源汇报等。当资源不足的时候,SlotManager将资源请求暂存在等待队列中,SlotManager通知ResourceManager去申请更多的资源,启动新的TaskManager,TaskManager注册到SlotManager之后,SlotManager就有可用的新资源了,从等待队列中依次分配资源。
3.2、SlotProvider
SlotProvider接口定义了Slot的请求行为,支持两种请求模式。
- 立即响应模式:Slot请求会立即执行。
- 排队模式:排队等待可用Slot,当资源可用时分配资源。
最终的实现在SchedulerImpl中,其中Scheduler接口增加了SlotSelectionStrategy。
3.3、Slot选择策略
Flink在决定Task运行在哪个TaskManager上是,会根据策略进行选择,选择Slot的时候有不同的选择策略,SlotSelectionStrategy就是策略定义的接口。
选择策略从总体上分为两大类:
- 位置优先的选择策略LocationPreferenceSlotSelectionStrategy。
位置有限的策略分为两类:
- 默认策略。DefaultLocationPreferenceSlotSelectionStrategy,该策略不考虑资源的均衡分配,会从满足条件的可用Slot集合选择第1个,以此类推。
- 均衡策略。EvenlySpreadOutLocationPreferenceSlotSelectionStrategy,该策略考虑资源的均衡分配,会从满足条件的可用Slot集合中选择剩余资源最多的Slot,尽量让各个TaskManager均衡地承担计算压力。
- 已分配Slot优先的选择策略PreviousAllocationSlotSelectionStrategy。
如果当前没有空闲的已分配的Slot,则仍然会使用位置优先的策略来分配和申请Slot。
3.4、Slot资源池
Slot资源池在Flink中叫作SlotPool,是JobMaster中记录当前作业从TaskManager获取的Slot集合。JobMaster的调度器首先从SlotPool中获取Slot来调度任务,SlotPool在没有足够的Slot资源执行作业的时候,首先会尝试从ResourceManager中获取资源,如果ResourceManager当前不可用、ResourceManager拒绝资源请求或者请求超时,资源申请失败,则作业启动失败。
JobMaster申请到资源之后,会在本地持有Slot,避免ResourceManager异常导致作业运行失败。对于批处理而言,持有资源JobMaster首先可以避免多次向ResourceManager申请资源,同时ResourceManager不可用也不会影响作业的继续执行,只有资源不足时才会导致作业执行失败。
当作业已经执行完毕或者作业完全启动且有资源剩余时,JobMaster会将剩余资源交还给ResourceManager。
3.5、Slot共享
Slot共享条件请参考:
3.5.1、Slot共享的优点
默认情况下,Flink作业共享同一个SlotSharingGroup,同一个作业中来自不同JobVertex的Task可以共享作业。使用Slot共享,可以在一个Slot中运行Task组成的流水线。
优点:
- 资源分配简单:Flink集群需要的Slot数量和作业汇总的最高并行度一致,不需要计算一个程序总共包含多少Task。
- 资源利用率高:如果没有Slot共享,资源密集型的Task(如长周期的窗口计算)跟非密集型的作业(如Srouce/Map)占用相同的资源,在整个TaskManager层面上,资源没有充分利用。
3.5.2、Slot共享组与Slot共享管理器
Slot共享管理器在Flink中叫作SlotSharingManager,Slot共享组在Flink中叫作SlotSharingGroup。SlotSharingManager对象管理资源共享与分配,1个Slot共享组对应1个Slot共享管理器。
Flink有两种共享组。
- SlotSharingGroup
非强制性共享约束,Slot共享根据组内的JobVertices ID查找是否已有可以共享的Slot,只要确保相同JobVertex ID不能出现在一个共享的Slot内即可。
在符合资源要求的Slot中,找到没有相同JobVertex ID的Slot,根据Slot选择策略选择一个Slot即可,如果没有符合条件的,则申请新的Slot。
- ColocationGroup
ColocationGroup又叫本地约束共享组,具有强制性的Slot共享限制,CoLocationGroup用在迭代运算中,即在IterativeStream的API中调用。迭代运算中的Task必须共享一个TaskManager的Slot。CoLocationGroup可以看成是SlotSharingGroup的特例。
此处需注意的,JobGraph向ExecutionGraph的转换过程中,为每一个ExecutionVertex赋予了按照并行度编写的编号,相同编号的迭代计算ExecutionVertex会被放入本地共享约束组中,共享相同的CoLocationConstraint对象,在调度时,根据编号就能找到本组其他的Task的Slot信息。
3.5.3、Slot资源申请
- 单独Slot资源申请
该类型的Slot申请首先会从JobMaster的当前SlotPool中尝试获取资源,如果资源不足,则从SlotPool中申请新的Slot,然后SlotPool向ResourceManager 请求新的Slot。
- 共享Slot资源申请
共享Slot在申请的时候,需要向SlotSharingManager请求资源,如果有CoLocation限制,则申请CoLocationMultiTaskSlot,否则申请一般的MultiTaskSlot。
在Flink中使用TaskSlot来定义Slot共享的结构。
SingleTaskSlot表示运行单个Task的Slot,每个SingleTaskSlot对应于一个LogicalSlot。MultiTaskSlot中包含了一组TaskSlot。