Apache Flink 源码解析(三)Flink on Yarn (2) Resource Manager

杂谈

首先声明一下,这篇文章很杂,涉及到了挺多的模块,其实应该分为几篇来写更为合理,不过一口气写完了也就先发出来了,后续有空看看能不能改一下。

概述

本文介绍了Flink在Yarn上面的资源申请的流程和机制,屏蔽了具体运行的细节。

YarnResourceManager

  • Flink的YarnResourceManager是ApplicationMaster中负责向Yarn申请资源和分配资源的模块。它有两个重要的成员变量AMRMClientAsync和NMClient,AMRMClientAsync负责向Yarn申请和释放Container,并且会调用三个非常关键的回调方法(YarnResourceManager实现AMRMClientAsync.CallbackHandler接口,实现了这三个方法)。NMClient则负责给申请到的Container提供启动YarnTaskExecutorRunner所需的Context(环境,依赖,命令等等)以及停止Container。
  • 首先看YarnResourceManager的类图。


    YarnResourceManager UML
  • YarnResouceManager继承了ResourceManager抽象类和 AMRMClientAsync的CallbackHandler接口。

    ResourceManager抽象类

    • 首先是ResourceManager这个抽象类,它有三个实现类,Standalone,Mesos和Yarn,分别针对三种不同的资源管理模式,所以它将于TaskExecutor容器申请无关的逻辑都提取了出来。ResourceManager类实现了LeaderContender和ResourceManagerGateway这两个接口。LeaderContender接口用于接收LeaderElectionService的回调,在高可用模式下确定主ResourceManager。如果一个ResouceManager成为Leader,它实现的grantLeadership方法会被调用。


      ResourceManager grantLeadership方法
    • 在该方法中,会启动和这个ResourceManager相关联的SlotManager。Slot是比TaskExecutor更细粒度的资源抽象。一个TaskManager中包含一个或多个Slot。SlotManager会针对每个SlotRequest分配一个Slot, 如果已有的TaskManager没有足够的Slot,SlotManager会向ResourceManager申请新的TaskManager(在启动或者某个TaskExecutor挂掉的情况下会出现这种情况,关于Slot相关内容后续可能会有文章细说,现在可以当成具体执行任务的最小单位的抽象)。

    • 此外,ResourceManager中还有registerJobManager和registerTaskExecutor方法,是由JobManager和TaskManager启动后触发connectToResourceManager,然后调用RPC方法到ResourceManager上注册。在registerJobManager方法中会调用registerJobMasterInternal方法,做了旧的JobManager的清理以及新的JobManager的注册与心跳监控。在registerTaskManager方法中会调用registerTaskManagerInternal方法,这个方法中会将拥有同一个ResourceID的TaskManager从taskExecutors成员变量中移除,并从SlotManager中将这个TaskExecutor中的所有Slot移除。然后将TaskExecutor与YarnWorkerNode的映射关系放入taskExecutors成员变量,最后还要监控TaskExecutor的心跳。当两者心跳超时,jobManagerHeartbeatManager和taskManagerHeartbeatManager分别会回调JobManagerHeartbeatListener和TaskManagerHeartbeatListener的notifyHeartbeatTimeout方法,做清理和断开连接的操作。

容器申请整条链路

  • 之前将ResourceManager介绍了大概,之后会从发起一个SlotRequest来讲资源申请的一整条链路,会涉及到几个重要的方法(文章开头提到的AMRMClientAsync.CallbackHandler接口的三个方法之一的onContainerAllocated)。

  • 在这儿会屏蔽Execution的细节。

    流程

    • 首先SlotPool中的requestNewAllocatedSlot方法被调用入参包含了SlotRequestId和ResourceProfile。


      SlotPool.requestNewAllocatedSlot
    • 这个方法会判断是否有resourcemanager,如果有就会调用requestSlotFromResourceManager并将这个SlotRequest放入SlotPool的一个缓存pendingRequests中并通过rpc调用ResourceManager的requestSlot函数来申请Slot。


      SlotPool.requestSlot
    • 这个rpc调用之后又回到了ResourceManager,ResourceManager将请求通过registerSlotRequest转交给SlotManager,SlotManager会先将请求加入到pendingSlotRequests缓存(注意这儿不是SlotPool的pendingSlotRequests),然后调用internalRequestSlot方法。


      ResourceManager.requestSlot
    • 在internalRequestSlot方法中,根据SlotRequest先找到是否有TaskManager有可用的Slot,如果有,就向那个TaskManager申请Slot。如果没有,就会调用allcoateResource来向ResourceManager申请新的容器(ResourceManager中的内部类ResourceActionImpl实现了这儿的ResourceAction接口)。

    • SlotManager.internalRequestSlot
    • 这个allocateResource方法被调用后,会调用startNewWorker来启动一个新的容器,而startNewWorker是ResourceManager的一个抽象方法,在YarnResourceManager中实现了该方法。

    • ResourceManager.allocateResource
    • 在startNewWorker方法中,封装了向Yarn申请资源的Resource之后,并在requestYarnContainer方法中,通过异步的Yarn的AMRMClientAsync来申请容器。

    • YarnResourceManager.startNewWorker
    • 当Yarn的容器分配好了之后,会调用YarnResourceManager实现的回调方法onContainerAllocated。在这儿,会将超发的container release调,而所需的container则会将于ResourceID的映射放入workerNodeMap缓存,并且通过NMClient(nodeManagerClient)来启动YarnTaskExecutorRunner进程。

    • onContainerAllocated
    • 至此,Yarn申请资源的阶段就已经完成,而停止Worker,或者Container意外退出的逻辑就不多说了,相信看完这整个链路知道怎么去快速的阅读了。

总结

本文简要介绍了Flink在Yarn上的Application Master的设计,并且使用一个例子来过完整个流程,至于什么时候触发的SlotRequest这个并没有提及,和Flink的runtime有密不可分的关系。

你可能感兴趣的:(Apache Flink 源码解析(三)Flink on Yarn (2) Resource Manager)