NodeManager本地缓存源码解析

NodeManager本地缓存源码解析

在这里插入图片描述

NodeManager本地缓存中资源有三种可见度:PUBLIC、PRIVATE、APPLICATION,每种可见度都需要不同的处理

  • PUBLIC:全局共享缓存,资源存放在 ${yarn.nodemanager.local-dirs}/filecache/ 目录下

  • PRIVATE:对应用户级别共享资源,资源存放在 y a r n . n o d e m a n a g e r . l o c a l − d i r s / u s e r c a c h e / {yarn.nodemanager.local-dirs}/usercache/ yarn.nodemanager.localdirs/usercache/{user}/filecache/ 目录下

  • APPLICATION:对应容器级别共享资源,资源存放在 y a r n . n o d e m a n a g e r . l o c a l d i r s / u s e r c a c h e / {yarn.nodemanager.localdirs}/usercache/ yarn.nodemanager.localdirs/usercache/{user}/ a p p c a c h e / {appcache}/ appcache/{appid}/filecache/ 目录下

在这里插入图片描述

在提交一个 Application 时,我们必须调用 YarnClient#submitApplication 提交 Application,而 Application 的启动需要Application相关的提交信息,也就是 ApplicationSubmissionContext,在 ApplicationSubmissionContext 中,可以设置相关的 Application 提交描述,例如 队列、优先级、重试次数等,当然我们这里相关的就是容器启动环境描述,也就是 ContainerLaunchContext,ContainerLaunchContext 中就可以设置需要的本地缓存。

可以通过调用 ContainerLaunchContext#setLocalResources设置需要的本地缓存 LocalResource,通过调用 ApplicationSubmissionContext#setAMContainerSpec 设置 ContainerLaunchContext。

我们简单先介绍一下本地缓存 LocalResource,LocalResource 有以下几个属性:

  • Visibility:可见程度,全局可见(PUBLIC)、用户可见(PRIVATE)、 Application 可见(APPLICATION)。
  • Pattern:获取应该用于从存档中提取条目的模式(仅在type为pattern时使用)。
  • ShouldBeUploadedToSharedCache:资源是否上传到共享缓存。
  • Type:资源类型,ARCHIVE、FILE、PATTERN,FILE 和 ARCHIVE 很好理解,但是 PATTERN 要解释一下,PATTERN 是 ARCHIVE 和 FILE 的混合体。只有部分文件未归档,原始文件保留在原处,但与未归档部分位于同一目录中。未归档的部分由pattern属性决定。目前只有jar支持模式,其他所有模式都将被视为ARCHIVE。
  • Timestamp:资源创建时间。
  • Size:资源大小。
  • Resource:资源URI地址。

LocalResource表示运行容器所需的本地资源缓存,NodeManager在启动容器之前通过它对资源进行本地化。

NodeManager 在容器启动的什么时候进行资源本地化呢?

资源本地化在 Container 从 NEW 状态转移到 LOCALIZING、LOCALIZATION_FAILED、LOCALIZED、DONE 状态 (INIT_CONTAINER) 之后,LocalizedResource 从 INIT 状态转移到 DOWNLOADING (REQUEST) 状态时发生的。

ResourceLocalizationService 依次接受事件,然后初始化Application资源、初始化容器资源,具体可以看下面的 ResourceLocalizationService 解析。

资源本地化服务 (ResourceLocalizationService)

资源本地化服务(ResourceLocalizationService) 是本地 NodeManager 本地缓存服务的核心,它负责和 NodeManager 以及其他的本地缓存服务组件通信处理并本地化事件。

本地化事件有6 种类型:

  1. Application资源初始化事件
  2. 容器资源初始化事件
  3. 容器资源本地化完成事件
  4. 清理容器资源事件
  5. 清理Application资源事件
  6. 清理缓存事件

ResourceLocalizationService维护Public、Private、Application的LocalResourcesTracker

处理本地化事件流程

  • ResourceLocalizationService 处理 LocalizationEvent

    ResourceLocalizationService#handle

    • 处理 Application 资源初始化事件(LocalizationEventType#INIT_APPLICATION_RESOURCES)

      ResourceLocalizationService#handleInitApplicationResources

      • 为 PRIVATE 创建一个资源追踪器 (LocalResourcesTrackerImpl),并将资源追踪器放入 PRIVATE 资源追踪器集合(privateRsrc)中
      • 为 application 创建一个资源追踪器 (LocalResourcesTrackerImpl),将资源追踪器放入 APPLICATION 资源追踪器集合(appRsrc)中
      • 创建 ApplicationInitedEvent 事件
      • 向事件分发器发送一个 ApplicationInitedEvent 事件
    • 处理容器资源初始化事件 (ContainerLocalizationRequestEvent)

      ResourceLocalizationService#handleInitContainerResources

      该事件包含相关的 Container 以及请求的资源集合

      • 获取事件相关的 Container
      • 创建加载中的缓存 (LoadingCache)
      • 创建本地化环境 (LocalizerContext)
      • 从事件中获取请求资源,并遍历事件中的请求资源
        • 根据请求资源的能见度获取相应的本地资源追踪器 LocalResourcesTracker,例如 PUBLIC->publicRsrc、PRIVATE->privateRsrc[user]、APPLICATION->appRsrc[appId]
        • 使用 LocalizerContext 和 LoadingCache 创建资源请求事件 ResourceRequestEvent
        • 调用本地化资源追踪器处理资源请求事件
    • 处理容器资源已经本地化事件

      ResourceLocalizationService#handleContainerResourcesLocalized

      • 一旦容器的资源被本地化,杀死相应的 ContainerLocalizer

        • 获取容器id,并通过容器 id 从 privLocalizers 中获取相应的 LocalizerRunner

        • 将 killContainerLocalizer 变量设置为 true ,表示容器本地化已完成,需要杀死相应的 LocalizerRunner,

          ResourceLocalizationService.LocalizerRunner#endContainerLocalization

    • 处理清理容器资源事件

      ResourceLocalizationService#handleCleanupContainerResources

    • 处理清除 Application 资源事件

      ResourceLocalizationService#handleDestroyApplicationResources

      • 将容器对应的 LocalizerRunner 中 killContainerLocalizer 变量设置为 true,
    • 处理清理缓存事件

      ResourceLocalizationService#handleCacheCleanup

      • 创建 ResourceRetentionSet

      • ResourceRetentionSet 处理 PUBLIC 和 PRIVATE 资源

        ResourceRetentionSet#addResources

        • 遍历PUBLIC和PRIVATE资源追踪器 (LocalResourcesTracker) 中的资源,获取所有引用为0的资源
        • 遍历所有引用为0的资源,判断需要删除的资源大小是否大于yarn.nodemanager.localizer.cache.target-size-mb << 20参数的大小,如果大于,那么就删除该资源

本地缓存清理器CacheCleanup

CacheCleanup 将跟随 NodeManager 的资源本地化服务 (ResourceLocalizationService) 启动,用于定期给 ResourceLocalizationService发送缓存清理事件(LocalizationEventType.CACHE_CLEANUP)。

定期的时间由yarn.nodemanager.localizer.cache.cleanup.interval-ms设定。

本地化追踪器LocalizerTracker

LocalizerTracker 也是一个服务,它用于处理本地化资源请求事件 (LocalizerResourceRequestEvent),创建公共和私有的本地化器 LocalizerRunner 和 PublicLocalizer,同时它对接 ResourceLocalizationService,调用 LocalizerRunner 和 PublicLocalizer。

ResourceLocalizationService 通过它来处理清理容器资源事件和容器本地化完成事件,以及调用 LocalizerRunner 处理心跳。

  • 事件分发器接收本地化资源请求事件(LocalizerResourceRequestEvent)

    AsyncDispatcher#dispatch

    每个请求事件中都有相应的LocalizerContext、LocalizedResource、LoadingCache和LocalResourceVisibility

    LocalizerContext记录着容器Id、用户、权限信息和缓存等信息。

    LocalizedResource记录着如下信息:

    1. 本地资源请求信息(LocalResourceRequest),请求信息中包含资源信息,如资源类型、资源地址、资源可见性、时间戳等、
    2. 引用,例如使用该资源等容器Id
    3. 状态机,表示该资源的分配状态

    LoadingCache中包含文件状态的Future,当文件资源处理完成时会完成该Future

    • LocalizerTracker开始处理事件

      ResourceLocalizationService.LocalizerTracker#handle

      • 本地化资源请求的资源有三种可见度:PUBLIC、PRIVATE、APPLICATION,每种可见度都需要不同的处理

        • 对于PUBLIC则使用PublicLocalizer类进行处理

          ResourceLocalizationService.PublicLocalizer#addResource

        • 对于PRIVATE和APPLICATION则使用会获取或创建container专有的LocalizerRunner进行处理

          ResourceLocalizationService.LocalizerRunner#addResource

  • ResourceLocalizationService是一个单独的线程,它会不断检测并处理资源下载队列里面的资源下载请求

    ResourceLocalizationService.PublicLocalizer#run

    • 获取并开始下载资源

      FSDownload#call

    • 等待队列移除相关的Future

    • 创建资源已分配事件(ResourceLocalizedEvent),并交由本地资源追踪器(LocalResourcesTrackerImpl)处理,移除inProgressLocalResources表中相应的资源记录,并将状态从DOWNLOADING状态变为LOCALIZED

公共资源的本地化器(PublicLocalizer)

PublicLocalizer是一个单独的线程,它会不断处理 LocalizerTracker 交给 PublicLocalizer 的本地化资源请求事件。

LocalizerTracker添加资源请求事件到PublicLocalizer过程

  • LocalizerTracker添加资源请求事件到 PublicLocalizer 中

    PublicLocalizer#addResource

    • 先获取和使用信号量锁

    • 判断是否是下载中的资源,否则释放锁并跳过资源处理

    • 获取资源的根地址${nodemanager.tmpdir}/filecache

    • 获取资源的目的地址

      LocalResourcesTrackerImpl#getPathForLocalization

      • 获取或创建缓存根目录管理器

      • 将当前资源存放在 inProgressLocalResources 表中

      • 将内部的资源独特数字加一

      • 拼接资源的根地址、独特数字和资源(jar包名等)

      • 从本地资源Map中获取并设置LocalizedResource的本地路径

      • 开始资源本地化

        NMStateStoreService#startResourceLocalization

      • 返回本地地址

    • 初始化本地缓存目录

      ResourceLocalizationService#getInitializedLocalDirs

    • 初始化本地日志目录

      ResourceLocalizationService#getInitializedLogDirs

    • 创建并启动异步资源下载任务 (FSDownload) 并放入等待队列中

PublicLocalizer运行不断处理资源请求事件

  • PublicLocalizer运行不断处理资源请求事件

    PublicLocalizer#run

    • 循环处理异步资源下载任务
      • 获取完成的异步下载任务
      • 等待队列移除任务对应的本地化资源请求事件
      • 创建资源已经本地化事件
      • LocalResourcesTracker处理资源已经本地化事件
      • 解锁资源

容器专有的资源管理器(LocalizerRunner)

LocalizerRunner是一个单独的线程,将会在容器申请资源的时候创建,它主要有两个作用:

  1. 对接LocalizerTracker,LocalizerTracker会不断接受资源请求,并将资源请求放入LocalizerRunner的等待队列中
  2. 创建并启动 ContainerLocalizer,ContainerLocalizer 对接 ResourceLocalizationService 下载资源。

对接 LocalizerTracker 添加资源并处理等待队列流程

上面说到 LocalizerTracker 会通过调用 LocalizerRunner 的 addResource 方法添加本地化资源请求事件中的资源到LocalizerRunner中的等待队列中,这里来了解 LocalizerRunner是如何处理等待队列的。

ResourceLocalizationService在处理ContainerLocalizer发送的心跳时,会调用 LocalizerTracker 的 processHeartbeat 方法来处理心跳,而 LocalizerTracker 是维护LocalizerRunner的,一个本地化 Id 对应相应的LocalizerRunner,它也是会通过请求中的本地化 Id 来获取LocalizerRunner,最后还是通过 LocalizerRunner 调用 processHeartbeat 处理心跳。

  • LocalizerRunner 处理 ContainerLocalizer 发送的心跳。

    ResourceLocalizationService.LocalizerRunner#processHeartbeat

    • 创建本地化心跳响应 LocalizerHeartbeatResponse 。

    • 遍历心跳中所有资源的状态,根据资源的不同状态创建相应的资源事件,并将事件发送给 LocalResourcesTracker 做处理,如果资源是完成状态,那么将移除正在处理的资源请求Map中的对应资源。

    • 如果 killContainerLocalizer 标志为 true,那么会将响应中的 LocalizerAction 设置为DIE,这将让 ContainerLocalizer 停止运行。

    • 获取需要下载的资源,这时候开始处理 LocalizerTracker 添加到 LocalizerRunner 中的资源本地化请求事件。

      ResourceLocalizationService.LocalizerRunner#findNextResource

      • 遍历等待列表中的资源本地化请求事件。
        • 锁住资源,通过资源请求创建 LocalResource,LocalResource 中包含 Timestamp、Type、Visibility、Pattern、Resource 地址,然后将该资源请求放入正在处理的资源请求 Map,最后返回该 LocalResource。
    • 将获取的需要下载的资源设置到响应中

    • 设置响应中的 LocalizerAction 为LIVE 状态

    • 返回响应

创建并启动 ContainerLocalizer 过程

  • 开始运行LocalizerRunner

    LocalizerRunner#run

    • 将环境证书和安全证书写到容器相对应的目录里面,例如/Dir-nm-0_0/nmPrivate/container_1721233898248_0001_01_000001.tokens

      ResourceLocalizationService.LocalizerRunner#writeCredentials

    • 如果磁盘容量足够那么将使用容器执行器启动容器本地化器

      ContainerExecutor#startLocalizer

      容器执行器有多种ContainerExecutor,例如WindowsSecureContainerExecutor、LinuxContainerExecutor、DefaultContainerExecutor,但其实所有执行器启动容器本地化器的逻辑都是一样的

      • 开始启动容器本地化器

        • 创建用户本地目录,例如:/Dir-nm-0_0/usercache/w

        • 创建用户缓存目录,例如:/Dir-nm-0_0/usercache/w/appcache

        • 创建文件缓存目录,例如:/Dir-nm-0_0/usercache/w/filecache

        • 创建Application目录,例如:Dir-nm-0_0/usercache/w/appcache/application_1721233898248_0001

        • 创建Application日志目录,例如:/nm-log-dirsDir-nm-0_0/application_1721260224148_0001

        • 复制Token到App目录,/Dir-nm-0_0/usercache/w/appcache/application_1721260224148_0001/container_1721260224148_0001_01_000001.tokens

        • 初始化用户FileCache,例如: /Dir-nm-0_0/usercache/w/filecache

        • 初始化Application FileCache,例如:/Dir-nm-0_0/usercache/w/appcache/application_1721260224148_0001/filecache

        • 设置Configuration中的 a p p l i c a t i o n I d . a p p . c a c h e . d i r s 、 {applicationId}.app.cache.dirs、 applicationId.app.cache.dirs{user}.user.cache.dirs配置为用户FileCache和Application FileCache

        • 创建文件环境,设置文件环境的工作目录

        • 创建容器本地化器ContainerLocalizer

        • 使用容器本地化器开始本地化

          ContainerLocalizer#runLocalization

容器本地化器 ContainerLocalizer

容器本地化器用于处理资源本地化器发送过来的资源下载请求,下载相应的资源到指定的缓存目录。

  • 容器本地化器开始本地化

    ContainerLocalizer#runLocalization

    • 初始化目录,创建相应的目录以及设置权限,相关的目录如: x / u s e r c a c h e / x/usercache/ x/usercache/user、 x / u s e r c a c h e / x/usercache/ x/usercache/user/filecache、 x / u s e r c a c h e / x/usercache/ x/usercache/user/appcache/ a p p I d 、 appId、 appIdx/usercache/ u s e r / a p p c a c h e / user/appcache/ user/appcache/appId/filecache

    • 读取的 Token 文件,创建Credentials,创建 UGI 环境。

    • 真正开始本地化Application需要的资源文件,也就是从HDFS上下载文件到本地服务器。

      ContainerLocalizer#localizeFiles

      • 开始循环给资源本地化服务发送心跳,下载响应的资源。

        • 获取所有异步的资源下载请求状态,通过下载状态创建本地化状态(LocalizerStatus),它用于描述所有等待中需要下载的资源(pendingResources)的当前状态。

        • 发送附带资源状态的心跳请求给资源本地化服务 (ResourceLocalizationService),资源本地化服务将通过资源状态并做出相应处理和响应。

          LocalizationProtocol#heartbeat

          响应中附带需要下载的资源以及本地化动作LocalizerAction

        • 读取响应中的本地化动作LocalizerAction。

          • 如果LocalizerAction为LIVE,表示本地化仍在进行中,那么读取响应中的资源规范,创建并提交资源下载请求(FSDownload),并将资源下载请求添加到等待中的资源当中(pendingResources),资源下载请求将异步下载资源到指定缓存目录。
          • 如果LocalizerAction为DIE,表示不需要下载资源了,那么取消所有等待中的资源(pendingResources), 并跳出循环)。
        • 从环境配置项中删除当前Application的环境,并关闭文件系统。

本地资源追踪器(LocalResourcesTracker)

本地化资源追踪器内部维护着对应资源可见度级别的资源请求资源表,以及正在处理中的资源请求对应的资源路径,资源表中保存着资源记录(LocalizedResource), 通过资源事件(ResourceEvent)可以控制内部的资源表。

  • LocalResourcesTrackerImpl开始处理资源事件

    • 根据事件类型做相应的处理:

      • 如果事件类型是LOCALIZED,表示资源已经分配,那么移除inProgressLocalResources表中相应的资源记录

      • 如果事件类型是REQUEST,表示请求资源,那么将创建LocalizedResource,并存入本地资源表中

      • 如果事件类型是RELEASE,表示释放资源,那么打印资源释放日志

      • 如果事件类型是LOCALIZATION_FAILED,表示本地化资源失败,那么将移除资源表中记录信息

        LocalResourcesTrackerImpl#removeResource

      • 如果事件类型是RECOVERED,表示恢复该资源,那么将恢复资源,并将资源存入本地资源表中

    • 交由LocalizedResource处理事件

      LocalizedResource#handle

      LocalizedResource代表相应的资源

      • LocalizedResource将维护的状态机转换一步,也就是从DOWNLOADING状态变为LOCALIZED状态,表示该资源已经本地化完毕

        StateMachine#doTransition

    • 如果事件是RELEASE类型、资源引用为0、状态为DOWNLOADING且资源可视范围为PUBLIC,那么将移除相应的资源,这主要是防止容器被kill等情况

    • 如果资源类型为LOCALIZED类型,那么将调用状态存储服务NMStateStoreService完成资源本地化

      NMStateStoreService#finishResourceLocalization

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值