Yarn App 资源本地化

Posted by danner on April 1, 2021

on Yarn 程序都需要将 lib下的jar和代码jar 上传到 HDFS,在启动App前下载资源到本地,这一些列的操作很耗时

该如何节省程序启动时间?

本地化:将远程资源复制/下载到本地文件系统的过程。不再总是远程访问资源,而是将其复制到本地计算机,然后可以在本地访问该计算机。

本地资源:表示运行容器所需的文件/库。NodeManager 负责在启动容器之前对资源进行本地化。对于每个LocalResource,应用程序可以指定:

  • URL:下载本地资源的远程位置
  • Size:资源大小
  • 容器启动前远程文件系统上资源的最后修改时间戳
  • LocalResourceType:指定资源类型 - File、Archive、Pattern
  • Pattern:应用于从存档中提取条目的模式(仅当类型为Pattern时使用)
  • LocalResourceVisibility:指定节点管理器本地化的资源的可见性。可见性可以是
    • PUBLIC:程序结束不会删除资源,本地磁盘满/yarn.nodemanager.localizer.cache.target-size-mb 才删除
    • PRIVATE:同PUBLIC
    • APPLICATION:程序结束立即删除

ResourceLocalizationService:NodeManager 内部的服务,负责安全下载和组织容器所需的各种文件资源。将文件分发到所有可用磁盘上,对下载的文件实施访问控制限制,并对其设置适当的使用限制。

DeletionService:NodeManager 内部运行的一种服务,在接到指示时删除本地路径。

Localizer:执行本地化的实际线程或进程

  • PublicLocalizer:用于公共资源
  • ContainerLocalizer:用于私有资源和应用程序资源

LocalCache: NodeManager 维护和管理所有下载文件的服务器本地缓存。资源是根据复制该文件时最初使用的远程url唯一标识

如何实现本地化

PUBLIC资源本地化

NodeManager 的 PublicLocalizers 线程负责

  • yarn.nodemanager.localizer.fetch.thread-count :PublicLocalizers线程数
  • 远程资源的权限必须是 PUBLIC
PRIVATE/APPLICATION 资源本地化

不在NodeManager 中运行

  • 本地化在 ContainerLocalizer 中运行
  • 每个ContainerLocalizer 进程由NodeManager中的 LocalizerRunner 单个线程管理
  • LocalResourcesTracker 是每个用户/应用程序对象,它跟踪给定用户/应用程序的所有LocalResources
  • 当需要请求资源时,将资源添加到 LocalizerRunner 的 pending-resources队列
  • LocalizerRunner 启动LinuxContainerExecutor(LCE)(作为应用程序提交者运行的进程),然后执行 ContainerLocalizer 下载这些资源
    • ContainerLocalizer 与 NodeManager进程心跳
    • 心跳交互时, LocalizerRunner会给ContainerLocalizer下载资源地址,或者停止ContainerLocalizerContainerLocalizerLocalizerRunner 文件下载状态
    • 如果资源下载失败,该资源将从LocalResourcesTracker 中删除,容器最终将标记为失败。发生这种情况时,LocalizerRunners停止ContainerLocalizers并退出
    • 如果下载成功,LocalizerRunner 继续给ContainerLocalizer其他资源,直到全部下载完成

本地资源的目录

在NodeManager机器上,LocalResources 最终被本地化到以下目录

  • PUBLIC: <local-dir> /filecache
  • PRIVATE: <local-dir>/usercache//filecache
  • APPLICATION: <local-dir>/usercache//appcache/<app-id>/

yarn-site.xml 配置文件可以修改目录

  • yarn.nodemanager.local-dirs: 逗号分隔的本地目录列表,可以将其配置为在本地化过程中用于复制文件。允许多个目录背后的想法是使用多个磁盘进行本地化—这有助于故障转移(一个/几个磁盘坏了不会影响所有容器)和负载平衡(没有一个磁盘受到写操作的限制)。因此,如果可能,应在不同的本地磁盘上配置各个目录
  • yarn.nodemanager.local-cache.max-files-per-directory: 限制将在每个本地化目录中本地化的最大文件数(分别针对PUBLIC/PRIVATE/APPLICATION资源)。其默认值为8192,通常不应分配较大的值(配置一个足够小于基础文件系统(例如ext3)的每个目录最大文件限制的值)。
  • yarn.nodemanager.localizer.address: ResourceLocalizationService
  • yarn.nodemanager.localizer.client.thread-count: 限制 ResourceLocalizationService 中用于处理来自本地化程序的本地化请求的RPC线程数。默认值为5,这意味着默认情况下,在任何时间点,只有5个本地化程序(Container)将被处理,而其他本地化程序将在RPC队列中等待。
  • yarn.nodemanager.localizer.fetch.thread-count: 配置用于本地化PUBLIC 资源的线程数。回想一下,PUBLIC资源的本地化发生在NodeManager地址空间内,因此此属性限制了NodeManager内为PUBLIC 资源本地化生成的线程数量。默认值为4。
  • yarn.nodemanager.delete.thread-count: 控制DeletionService 用于删除文件的线程数。DeletionUser在整个NodeManager中用于删除日志文件和本地缓存文件。默认值为4。
  • yarn.nodemanager.localizer.cache.target-size-mb: 这决定了用于本地化资源的最大磁盘空间。一旦缓存的总磁盘大小超过此值,删除服务将尝试删除任何正在运行的容器未使用的文件。目前,用户缓存/公共缓存/私有缓存没有限制。此限制适用于所有磁盘,但不基于每个磁盘。
  • yarn.nodemanager.localizer.cache.cleanup.interval-ms: 如果总缓存大小超过配置的最大大小,则资源本地化服务将尝试删除未使用的资源。未使用的资源是指未被任何正在运行的容器引用的资源。每次容器请求资源时,容器都会添加到资源的引用列表中。它将一直保留在那里,直到容器完成,以避免意外删除此资源。作为容器资源清理的一部分(当容器完成时),容器将从资源的引用列表中删除。这就是为什么当引用计数降至零时,它是删除的理想候选对象。将基于LRU删除资源,直到当前缓存大小降至目标大小以下。

参考资料

Management of Application Dependencies in YARN

Resource Localization in YARN: Deep Dive