ResourceManager 架构
ResourceManager(简称RM),是Linkis的计算资源管理模块,所有的EngineConn(简称EC)、EngineConnManager(简称ECM),甚至包括Yarn在内的外部资源,都由RM负责统筹管理。RM能够基于用户、ECM或其它通过复杂标签定义的粒度对资源进行管控。
RM作为Linkis Manager的一部分,主要作用为:维护ECM上报的可用资源信息,处理ECM提出的资源申请,记录成功申请后,EC在生命周期内实时上报的实际资源使用信息,并提供查询当前资源使用情况的相关接口。
Linkis中,与RM产生交互的其它服务主要有:
引擎管理器,简称ECM:处理启动引擎连接器请求的微服务。ECM作为资源的提供者,负责向RM注册资源(register)和下线资源(unregister)。同时,ECM作为引擎的管理者,负责代替准备启动的新引擎连接器向RM申请资源。每一个ECM实例,均在RM中有一条对应的资源记录,包含它提供的总资源、保护资源等信息,并动态更新已使用资源。
引擎连接器,简称EC,是用户作业的实际执行单元。同时,EC作为资源的实际使用者,负责向RM上报实际使用资源。每一个EC,均在RM中有一条对应的资源记录:在启动过程中,体现为锁定资源;在运行过程中,体现为已使用资源;在被结束之后,该资源记录随之被删除。
如上图所示,所有的资源类均实现一个顶层的Resource接口,该接口定义了所有资源类均需要支持的计算和比较的方法,并进行相应的数学运算符的重载,使得资源之间能够像数字一样直接被计算和比较。
运算符 | 对应方法 | 运算符 | 对应方法 |
---|---|---|---|
+ | add | > | moreThan |
- | minus | \< | lessThan |
* | multiply | = | equals |
/ | divide | >= | notLessThan |
\<= | notMoreThan |
当前支持的资源类型如下表所示,所有的资源都有对应的json序列化与反序列化方法,能够通过json格式进行存储和在网络间传递:
资源类型 | 描述 |
---|---|
MemoryResource | 内存资源 |
CPUResource | CPU资源 |
LoadResource | 同时具备内存与CPU的资源 |
YarnResource | Yarn队列资源(队列,队列内存,队列CPU,队列实例数) |
LoadInstanceResource | 服务器资源(内存,CPU,实例数) |
DriverAndYarnResource | 驱动器与执行器资源(同时具备服务器资源,Yarn队列资源) |
SpecialResource | 其它自定义资源 |
RM中的可用资源,主要有两个来源:ECM上报的可用资源,以及Configuration模块中根据标签配置的资源限制。
ECM资源上报:
- ECM启动时,会广播ECM注册的消息,RM接收到消息后,根据消息中包含的内容进行资源注册,资源相关的内容包括:
- 总资源:该ECM能够提供的资源总数。
- 保护资源:当剩余资源小于该资源时,不再允许继续分配资源。
- 资源类型:如LoadResource,DriverAndYarnResource等类型名称。
- 实例信息:机器名加端口名。
RM在收到资源注册请求后,在资源表中新增一条记录,内容与接口的参数信息一致,并通过实例信息找到代表该ECM的标签,在资源、标签关联表中新增一条关联记录。
ECM在关闭时,会广播ECM关闭的消息,RM接收到消息后,根据消息中的ECM实例信息来进行资源的下线,即删除该ECM实例标签对应的资源和关联记录。
Configuration模块标签资源配置:
用户能够在Configuration模块中,根据不同的标签组合进行资源数量限制的配置,如限制User/Creator/EngineType组合的最大可用资源。
RM通过RPC消息,以组合标签为查询条件,向Configuration模块查询资源信息,并转换成Resource对象参与后续的比较和记录。
接收用户的资源申请
- LinkisManager在收到启动EngineConn的请求时,会调用RM的资源申请接口,进行资源申请。资源申请接口接受一个可选的时间参数,当申请资源的等待时间超出该时间参数的限制时,该资源申请将自动作为失败处理。
判断是否有足够的资源
即为判断剩余可用资源是否大于申请资源,如果大于或等于,则资源充足;否则资源不充足。
RM预处理资源申请中附带的标签信息,根据规则将原始的标签进行过滤、组合和转换等操作(如将User/Creator标签和EngineType标签进行组合),这使得后续的资源判断的粒度更加灵活多变。
在每个转换后的标签上逐一加锁,使得它们所对应的资源记录在资源申请的处理期间保持不变。
根据每个标签:
通过Persistence模块从数据库中查询对应的资源记录,如果该记录包含剩余可用资源,则直接用来比较。
如果没有直接的剩余可用资源记录,则通过[剩余可用资源=最大可用资源-已用资源-已锁定资源-保护资源]公式进行计算得出。
如果没有最大可用资源记录,则请求Configuration模块,看是否有配置的资源信息,如果有则使用到公式中进行计算,如果没有则跳过针对这个标签的资源判断。
如果没有任何资源记录,则跳过针对这个标签的资源判断。
只要有一个标签被判断为资源不充足,则资源申请失败,对每个标签逐一解锁。
只有所有标签都判断为资源充足的情况下,才成功通过资源申请,进入下一步。
锁定申请通过的资源
根据申请通过的资源数量,在资源表中生成一条新的记录,并与每个标签进行关联。
如果对应的标签有剩余可用资源记录,则扣减对应的数量。
生成一个定时任务,在一定时间后检查这批锁定的资源是否被实际使用,如果超时未使用,则强制回收。
对每个标签进行解锁。
上报实际使用资源
EngineConn启动后,广播资源使用消息。RM收到消息后,检查该EngineConn对应的标签是否有锁定资源记录,如果没有,则报错。
如果有锁定资源,则对该EngineConn有关联的所有标签进行加锁。
对每个标签,将对应的锁定资源记录转换为已使用资源记录。
解锁所有标签。
释放实际使用资源
EngineConn结束生命周期后,广播资源回收消息。RM收到消息后,检查该EngineConn对应的标签是否有已使用资源记录。
如果有,则对该EngineConn有关联的所有标签进行加锁。
对每个标签,在已使用资源记录中减去对应的数量。
如果对应的标签有剩余可用资源记录,则增加对应的数量。
对每个标签解锁
在RM中,为了更加灵活并有拓展性对资源进行分类,支持多集群的资源管控的同时,使得接入新的外部资源更加便利,在设计上进行了以下几点的考虑:
通过标签来对资源进行统一管理。资源注册后,与标签进行关联,使得资源的属性能够无限拓展。同时,资源申请也都带上标签,实现灵活的匹配。
将集群抽象成一个或多个标签,并在外部资源管理模块中维护每个集群标签对应的环境信息,实现动态的对接。
抽象出通用的外部资源管理模块,如需接入新的外部资源类型,只要实现固定的接口,即可将不同类型的资源信息转换为RM中的Resource实体,实现统一管理。
RM的其它模块,通过ExternalResourceService提供的接口来进行外部资源信息的获取。
而ExternalResourceService通过资源类型和标签来获取外部资源的信息:
所有外部资源的类型、标签、配置等属性(如集群名称、Yarn的web url、Hadoop版本等信息),都维护在linkis_external_resource_provider表中。
针对每种资源类型,均有一个ExternalResourceProviderParser接口的实现,将外部资源的属性进行解析,将能够匹配到Label的信息转换成对应的Label,将能够作为参数去请求资源接口的都转换成params。最后构建成一个能够作为外部资源信息查询依据的ExternalResourceProvider实例。
根据ExternalResourceService方法的参数中的资源类型和标签信息,找到匹配的ExternalResourceProvider,根据其中的信息生成ExternalResourceRequest,正式调用外部资源提供的API,发起资源信息请求。