深入理解 YARN Resource Localization
一個 Applciation 運行在 YARN 上的流程爲,從 YARN Client 向 ResourceManager 提交任務,將 Applciation 所需資源提交到 HDFS 中,然後 ResourceManager 啓動 APPMaster,APPMaster 通知各個 NodeManager 啓動 container 執行具體到計算任務。在啓動 container 之前需要從 HDFS 上下載該 container 執行所依賴的資源,這些資源包括 jar、依賴的 jar 或者其它文件,這個過程就稱爲資源本地化 (Resource Localization)。
本篇主要介紹下資源本地化相關的內容。
相關概念
本地化 (Localization)
本地化是指將 HDFS 上的資源下載到本地的過程。將資源本地化,使 container 不用總是訪問 HDFS 上的數據,而是直接訪問本地數據,提高效率。
本地資源 (LocalResource)
本地資源是指 container 運行時所需要的資源,可以是某個文件或者依賴的 library,這些資源存在 HDFS 中。NodeManager 在 container 啓動之前負責將這些資源進行本地化。對於 Application 來說,本地資源指:
-
URL: 需要從 HDFS 上下載的本地資源地址
-
Size: 本地資源的大小
-
timestamp: 本地資源在 HDFS 上創建時的時間戳
-
LocalResourceType: NodeManager 本地化資源時指定的資源類型,有 FILE、ARCHIVE 和 PATTERN
-
Pattern: 從 archive 中解壓具體內容時使用的規則匹配方式 (只有 LocalResourceType 是 PATTERN 時才生效)。
-
LocalResourceVisibility: NodeManager 將資源本地化之後針對該 Nodemanager 上其它用戶和 Application 的可見性。可見範圍爲 PUBLIC、PRIVATE 和 APPLICATION。
NOTE: 本地資源並不是指在本地磁盤的資源,而是需要從 HDFS 下載到本地的資源。
那麼 container 會請求什麼樣的資源進行本地化呢?可以是任意的文件,但是這些文件對 contianer 必須是隻讀的。
下面舉幾個比較適合做本地資源的典型例子:
-
container 啓動的時候需要的代碼庫,如 jar 文件
-
container 啓動時所需要的 configure 文件
-
靜態的文件目錄
一些動態資源不適合作爲本地資源,例如:container 需要的資源有可能被其它組件進行更新,application 自己會直接更新的文件或者 application 想跟其它服務共享文件的變化情況的。
ResourceLocalizationService
ResourceLocalizationService 是 NodeManager 內部的一個服務,主要負責下載和管理 container 所需的各種資源。下載時會對所有可用的磁盤進行負載均衡,對下載的資源會嚴格控制他們的訪問權限。
DeletionService
DeletionService 也是 NodeManager 內部的一個服務,主要負責在收到指令之後刪除本地目錄
Localizer
Localizer 實際上是一個線程,用於資源本地化。Localizer 有兩種類型,一種是指用與下載 PUBLIC 訪問類型資源的 PublicLocalizer,另一種是下載 PRIVATE 和 APPLICATION 訪問類型的 ContainerLocalizers。
LocalCache
LocalCache 是 NodeManager 維護所有下載到本地的文件的 local-cache。這些資源通過下載時指定的 HDFS 地址來唯一標識。
概念補充
LOCALRESOURCE TIMESTAMPS
timestamp 反應了本地資源的一個版本,NodeManager 在下載本地資源時會檢查 timestamp,這樣 Application 在運行時看到的文件內容都一樣。
利用 timestamp,YARN 能發現資源是否發生過變化,如果發生變化將使 container 失敗避免不一致發生。因爲在 HDFS 上的資源一旦被 NodeManager 本地化到本地磁盤,這個文件就不再與源文件有任何聯繫,只會記錄下原來的 URL 用來在本地進行唯一標識。此時即使源文件發生變化,NodeManager 也不會跟蹤此變化再次下載文件。
這裏需要注意的是當 container 啓動時,ApplicationMaster 會向運行 container 的 NodeManager 指定資源的 timestamp,同樣當運行 ApplicationMaster 的 container 啓動時,也需要資源的 timestamp,此時這個 timestamp 就需要由 client 指定。以 MapReduce on YARN 爲例,MapReduce 的 JobClient 決定 ApplicationMaster 需要的資源的 timestamp,然後由 ApplicationMaster 自己決定 map 和 reduce 所需資源的 timestamp。
LOCALRESOURCE TYPES
上一節中提到 LocalResourceType 爲 FILE、ARCHIVE 和 PATTERN,下面介紹下三種 type 的具體含義。FILE 類型是指普通的文件,文本類型或者二進制文件
-
ARCHIVE 類型是指一些可以被 NodeManager 自動識別解壓的歸檔文件,比如 jars、tars、tar.gz 和 zip
-
PATTERN 是 ARCHIVE 和 FILE 的一種混合體。這種類型下載到本地的源文件會保留,並且在本地化時只有解壓的文件會留存在本地文件系統中。源文件和解壓的文件在同一個目錄中。哪些文件需要從 ARCHIVE 中抽取出來,哪些不需要這些都是由 pattern 決定的。目前只有 jar 支持 PATTERN,其它都被認爲正常的 ARCHIVE。
LOCALRESOURCE VISIBILITES
上一節 LocalResourceVisibility 中提到本地資源有三種可見性,分別爲 PUBLIC、PRIVATE 和 APPLICATION。其中
-
PUBLIC 的訪問權限是指任何用戶的任意 Application 的 container 都可以訪問。典型的 PUBLIC 資源是那些在 HDFS 上可以被任何人訪問的文件,當這些資源被本地化之後會保留相同的訪問權限。如果一個資源是 PUBLIC,當有 container(container 可以是當前 Attempt,也可以是其它用戶的任意 Application 中的 container) 請求相同的本地資源時,只要此資源沒有被 LocalCache 刪除,都可以直接從 LocalCache 裏直接使用,而不需要再次下載。
-
PUBLIC 資源存儲在 NodeManager 本地磁盤的
<local-dir>/filecache
目錄下,此目錄中的所有文件的 owner 是 NodeManager 進程啓動時的用戶,並且所有用戶都有讀權限,因此這些資源可以在此 NodeManager 上運行的所有用戶的 container 共享。 -
PRIVATE 權限本地資源只能在當前節點上相同用戶的 application 之間共享,這些資源存儲在 NodeManager 本地磁盤的
<local-dir>/usercache/$username/[filecache](http://mp.weixin.qq.com/s?__biz=MzIxMTE0ODU5NQ==&mid=2650244653&idx=2&sn=9661125ed95e413c6275d97b9c238ac9&chksm=8f5aec71b82d6567ab31ef860d327344dc617dcc849d5d88805dbc47f9e96aa65418f6d95591&scene=21#wechat_redirect)
目錄下,這些文件的 owner 是啓動 Application 的 user,並且其它用戶沒有訪問權限。類似 PUBLIC,一旦資源本地化,所有的用戶都沒有寫權限,即使是提交任務的 user。這樣是爲了避免惡意的 container 去修改文件。 -
APPLICATION 只在當前節點上同一個 application 的 container 之間共享。這些資源存儲在 NodeManager 本地磁盤的
<local-dir>/usercache/$username/appcache/<app-id>/
目錄下,文件的 owner 是 Application 的提交者,並且只有讀權限。
這裏需要注意的是 LOCALRESOURCE VISIBILITIES 與 LOCALRESOURCE TIMESTAMPS 類似,都是由 ApplicationMaster 指定本地資源的可見性,NodeManager 並不會對資源的可見性做任何決定。同樣當運行 ApplicationMaster 的 container 啓動時,也需要資源的可見性,此時這個可見性就需要由 client 指定。以 MapReduce on YARN 爲例,MapReduce 的 JobClient 決定 ApplicationMaster 需要的資源的可見性,然後由 ApplicationMaster 自己決定 map 和 reduce 所需資源的可見性。
本地化流程
PUBLIC 資源本地化是由 PublicLocalizer 實現的,在 NodeManager 進程中會有一個線程池 PublicLocalizers,其個數是由 yarn.nodemanager.localizer.fetch.thread-count 決定,線程池的大小決定並行下載 PUBLIC 資源的線程最大個數。當 PublicLocalizer 本地化 PUBLIC 資源時,會通過檢查這些資源在 HDFS 上的權限來確定所申請的資源確實爲 PUBLIC。只要有資源不符合就拒絕本地化。PublicLocalizer 能安全的從 HDFS 上下載資源是向 ContainerLaunchContext 傳遞了證書。
PRIVATE/APPLICATON 資源的本地化是由 ContainerLocalizer 實現的,不同與 PUBLIC 的 PublicLocalizer 實現。PublicLocalizer 是直接在 NodeManager 中啓動一個線程池進行本地化,而 ContainerLocalizer 出於安全問題,並沒有在 NodeManager 進程中直接實現,而是在 continer 中實現的。
PRIVATE/APPLICATON 資源的本地化是由 ContainerLocalizer 實現,這是一個單獨的進程,這個進程由 LocalizerRunner 線程管理,LocalizerRunner 是 NodeManager 中的一個線程,只要某個 container 有資源還沒有下載,那麼此 container 就會觸發一個 LocalizerRunner。下面看下具體的細節:
當某個 container 第一次請求 PRIVATE/APPLICATION 類型的本地資源時,如果沒有在 LocalResourcesTracker 中找到,則加入 pending-resources 列表。隨後是否需要創建 LocalizerRunner 線程取決於是否有必要下載資源,如果需要就將本地資源加入 LocalizerRunner 維護的 pending-resources 列表。
NodeManager 在安全模式時,本地資源本地化時需要所用的 user 是 application 的提交用戶而不是 NodeManager 的啓動用戶。因此 LocalizerRunner 會以 application 提交者的身份啓動 LinuxContainerExecutor(LCE) 進程,然後 LCE 會執行 ContainerLocalizer 下載資源。ContainerLocalizer 啓動之後會與 NodeManager 維持一個心跳,通過心跳,LocalizerRunner 給 ContainerLocalizer 分配需要下載的資源或者停止 ContainerLocalizer 進程,而 ContainerLocalizer 會通知 LocalizerRunner 自己的下載進度。如果資源下載失敗,這個資源將會從 LocalResourcesTracker 中移除,並且 container 最終也會失敗。如果下載成功,LocalizerRunner 會通過心跳給 ContainerLocalizer 另一個資源進行下載,直到所有的資源都下載完。
本地資源的生命週期
由於本地資源的訪問權限不一樣,則不同的 LocalResourceType 在本地保留的時間也會不一樣。
-
PUBLIC 由於是在任何用戶的任意 Application 之間共享,所以並不會在某個 container 或者 application 結束之後被刪除,只有在本地目錄達到存儲閾值時纔會被刪除,這個閾值由 yarn.nodemanager.localizer.cache.target-size-mb 控制。
-
PRIVATE 和 PUBLIC 的生命週期一樣。
-
APPLICATION 會在 application 結束之後立即刪除。
本地化相關的配置
在 yarn-site.xml 中有一些資源本地化相關的配置。
-
yarn.nodemanager.local-dirs: 資源本地化時所在的本地目錄,可以是以逗號分隔的多個磁盤目錄。
-
yarn.nodemanager.local-cache.max-files-per-directory: 每個目錄中最多本地化文件的個數,PUBLIC / PRIVATE / APPLICATION 分別統計。
-
yarn.nodemanager.localizer.address: ResourceLocalizationService 服務監聽的 RPC 地址,用來接收不同 localizers
-
yarn.nodemanager.localizer.client.thread-count: ResourceLocalizationService 中用來處理來自 localizers 請求的線程數。默認是 5
-
yarn.nodemanager.localizer.fetch.thread-count: 本地化 PUBLIC 資源時 PublicLocalizer 的線程數。默認是 4
-
yarn.nodemanager.delete.thread-count: DeletionService 中刪除文件的線程數,默認是 4。
-
yarn.nodemanager.localizer.cache.target-size-mb: 本地化資源所佔的最大磁盤空間,單位是 MB,比包括 APPLICATION 資源。
-
yarn.nodemanager.localizer.cache.cleanup.interval-ms: 每隔固定時間,去檢查下磁盤的使用量。在此間隔之後,如果存儲的磁盤空間超過了配置的閾值,會刪除未用的資源。
未使用的資源是指沒有被正在運行的 container 引用的資源。每次 container 請求資源時,container 會被加入到一個資源引用列表中,直到 container 結束之後纔會被移除。所以當引用數爲 0 時,可以被刪除。
參考
-
Management of Application Dependencies in YARN
-
Resource Localization in YARN: Deep Dive
本文轉載自 http://bigdatadecode.club/YARN-Resource-Localization.html
本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源:https://mp.weixin.qq.com/s/hsz3ILDdtj7RhST9X407Xg