一篇文章搞懂 Apache YARN 的 NodeManager 热重启

前言

本文隶属于专栏《大数据技术体系》,该专栏为笔者原创,引用请注明来源,不足和错误之处请在评论区帮忙指出,谢谢!

本专栏目录结构和参考文献请见大数据技术体系


正文

NM 重启是一项功能,可以重新启动 NodeManager 而不会丢失在节点上运行的容器。

当 NM 处理请求时,它将任何必要的状态同步地存储到状态存储器中。

当 NM 重新启动时,它通过加载各种子系统的状态来恢复正常工作。


1. 本地化资源状态存储和恢复

当 NM 开始下载资源时,它通过调用 startResourceLocalization(user, appId, proto, localPath)来保存本地资源。

  /**
   * Record the start of localization for a resource
   * @param user the username or null if the resource is public
   * @param appId the application ID if the resource is app-specific or null
   * @param proto the resource request
   * @param localPath local filesystem path where the resource will be stored
   * @throws IOException
   */
  public abstract void startResourceLocalization(String user,
      ApplicationId appId, LocalResourceProto proto, Path localPath)
          throws IOException;

公共资源的 user 和 appId 应该是空的,而私有资源仅 appId 是空的。

proto 是与容器请求关联的原始资源请求。

NM 使用键值存储数据库 leveldb 来存储本地状态,存储本地资源请求时其对应的键为

  • 公共资源:Localization/public/started/
  • 私人资源: Localization/private/filecache/started/
  • 应用资源: Localization/private//appcache//started/

这些键对应的值是根据本地资源请求构造的 LocalResourceProto 对象。

如果一个本地资源下载成功, NM 调用 finishResourceLocalization(user,appId proto) 来保存状态。

  /**
   * Record the completion of a resource localization
   * @param user the username or null if the resource is public
   * @param appId the application ID if the resource is app-specific or null
   * @param proto the serialized localized resource
   * @throws IOException
   */
  public abstract void finishResourceLocalization(String user,
      ApplicationId appId, LocalizedResourceProto proto) throws IOException;

这个操作将在 leveldb 中存储一个 completed 的 <key, proto> 对, compleled 键与 started 键除了 /started 被替换为 /compleled 之外,q其他部分一致。

通过这种键的差异在恢复状态时很容易区分正在进行和已经完成的下载资源。

在恢复状态时, NM 通过加载这些键值对以实现重新下载那些没有完成的本地资源。


2. 应用和容器状态的存储和恢复

在恢复状态期间, loadApplicationsState 方法从 leveldb 加载应用程序状态,对于已经结束的 App,会对其进行日志聚合并清理 App。

  /**
   * Load the state of applications.
   * @return recovered state for applications.
   * @throws IOException IO Exception.
   */
  public abstract RecoveredApplicationsState loadApplicationsState()
      throws IOException;

loadContainerState 方法以 leveldb 加载容器状态,一个容器的状态包括 Requested 、 Launched 、 Killed 和 Completed。

  private RecoveredContainerState loadContainerState(LeveldbIterator iter,
       String keyPrefix) throws IOException

如果容器的状态是 Completed , NM 将把状态切换为 DONE 并对其进行日志聚合。

如果容器的状态是 Launched , NM 将对这个容器执行正常的后动流程。

当恢复一个正在运行的容器时, NM 会给这个容器创建一个 RecoveredContainerLaunch, RecoveredContainerLaunch 通过 pid 文件和 exitcode 文件周期性跟踪容器状态。

/**
 * This is a ContainerLaunch which has been recovered after an NM restart (for
 * rolling upgrades).
 */
public class RecoveredContainerLaunch extends ContainerLaunch

如果 Pid 文件对应的进程已经结束,但是没有 exitcode 文件, NM 将汇报这个容器的状态是 LOST。

为了支持在 NM 重启过程中保存容器的退出状态,在运行容器的 bash 脚本中会启动一个子进程来保存容器的结束状态。


3. NM 和容器令牌(Token)的状态存储和恢复

NM 的令牌存储在 NMTokens/ 前缀的 key 中, master key 存储在 NMTokens/CurrentMasterKey 和 NMTokens/PreviousMasterKey 下,与 App attempt 相关的 masterkey 存储在 NMTokens/ 下。

在恢复状态期间使用 loadNMTokensState 方法加载这些令牌以恢复 NMTokenSecretManagerInNM 的状态。

  /**
   * Load the state of NM tokens
   * @return recovered state of NM tokens
   * @throws IOException
   */
  public abstract RecoveredNMTokensState loadNMTokensState()
      throws IOException;

容器的令牌存储在 ContainerTokens/ 前缀的 key 中, masterkey 存储在 ContainerTokens/CurrentMasterKey 和 ContainerTokens/PreviousMasterKey ,过期时间存储在 ContainerTokens/下。

在恢复状态期间使用 loadContainerTokensState 方法加载这些令牌以恢复 NMContainerTokenSecrelManager 的状态。

  /**
   * Load the state of container tokens
   * @return recovered state of container tokens
   * @throws IOException
   */
  public abstract RecoveredContainerTokensState loadContainerTokensState()
      throws IOException;

4. 日志聚合的恢复

目志聚合服务没有状态存储。

App 恢复后, App 的 init/finished 事件将传播到日志聚合服务。

如容器被恢复,已经结束的容器的完成事件被传播到日志聚合服务。

当日志聚合服务接收到 App 完成的事件,它会从头开始为其上传日志,覆盖任何现有的 .TMP 文件。

猜你喜欢

转载自blog.csdn.net/Shockang/article/details/128607629