ApplicationMaster 申请到资源后,是如何与 NodeManager 交互来启动任务的?
在 Hadoop YARN 架构中,当 ApplicationMaster (AM) 向 ResourceManager (RM) 成功申请到资源(以 Container 的形式表示)后,AM 需要直接与对应的 NodeManager (NM) 进行交互来启动实际的计算任务。这个过程是绕过 RM 直接进行的(点对点通信)。
以下是 ApplicationMaster 与 NodeManager 交互并启动任务的详细流程:
1. 准备阶段:构建 ContainerLaunchContext (CLC)
AM 在联系 NM 之前,首先需要构造一个叫做 ContainerLaunchContext (容器启动上下文) 的核心对象。这个对象相当于任务的“执行蓝图”,告诉 NM 具体该如何运行这个任务。
CLC 主要包含以下关键信息:
- Local Resources (本地资源):任务运行所需的依赖文件(如 JAR 包、配置文件、字典文件等)。AM 会指定这些文件在 HDFS 上的路径,要求 NM 下载到本地。
- Environment Variables (环境变量):任务进程运行所需的系统环境变量(如
JAVA_HOME,CLASSPATH等)。 - Commands (启动命令):实际启动任务的命令行(例如
java -Xmx1g my.TaskClass或者一段 bash 脚本)。 - Security Tokens (安全令牌):HDFS 或其他服务的 Delegation Tokens,确保任务在 NM 上运行时有权限访问 HDFS 等组件。
- Service Data (服务数据):特定于应用程序的数据。
2. 发起请求:AM 向 NM 发送启动指令
准备好 CLC 后,AM 会通过 RPC 协议(具体为 ContainerManagementProtocol)直接连接到分配了该 Container 的 NodeManager。
- 调用接口:AM 调用 NM 的
startContainers()RPC 方法。 - 身份验证:AM 在请求中必须携带 RM 之前分配的
ContainerToken。NM 会验证这个 Token,以确认 AM 确实获得了 RM 的授权来使用这些资源,防止恶意程序强占 NM 资源。
3. NM 内部处理阶段 (核心执行过程)
NodeManager 接收到 startContainers() 请求并验证通过后,会在内部经过一系列复杂的步骤来启动任务:
3.1 资源本地化 (Resource Localization)
这是 NM 最重要的一步工作。NM 的 ResourceLocalizationService 会根据 CLC 中提供的 Local Resources 列表,将 HDFS 上的 JAR 包、文件等下载到 NM 所在的物理机的本地磁盘目录中。
- 这些资源可以被设置为
PUBLIC(所有用户可见)、PRIVATE(当前用户可见)或APPLICATION(仅当前应用可见),NM 会根据级别进行缓存和隔离。
3.2 准备运行环境与目录
NM 会为该 Container 创建一个独立的本地工作目录,并将本地化下载的文件软链接(Symlink)到这个工作目录中。同时,NM 会将 CLC 中的环境变量写入到一个启动脚本(通常是 launch_container.sh)中。
3.3 资源隔离 (Cgroups)
如果集群配置了 LinuxContainerExecutor 并启用了 Cgroups,NM 会在操作系统层面为这个 Container 创建 Cgroups 目录,严格限制该任务能够使用的 CPU 和内存上限,防止它影响同节点上的其他任务。
3.4 启动进程
NM 将启动任务交由 ContainerExecutor 组件执行。
- DefaultContainerExecutor:以 NodeManager 进程的操作系统用户身份启动进程(安全性较低)。
- LinuxContainerExecutor:以提交该作业的实际用户身份(如
alice)fork出一个子进程并执行前面生成的启动脚本(安全性高,支持资源隔离)。
至此,实际的 Task 进程(例如 MapReduce 的 MapTask 或 Spark 的 Executor)就被正式拉起并运行了。
4. 运行与监控阶段:状态汇报与心跳
任务启动后,AM 和 NM 还需要保持交互以监控任务状态:
- 状态拉取:AM 会周期性地调用 NM 的
getContainerStatuses()RPC 接口,轮询各个 Container 的运行状态(如 RUNNING, COMPLETE, FAILED 等)。 - (补充说明:NM 也会通过心跳将 Container 的状态汇报给 RM,但 AM 主要通过直接向 NM 查询来获取实时的任务状态以便进行容错处理)。
5. 结束阶段:资源清理
- 当任务进程执行完毕(成功退出或异常崩溃)时,NM 会捕获到进程结束的信号。
- NM 会将该 Container 的状态标记为
EXITED,清理 Cgroups 限制。 - AM 通过轮询得知任务结束后,可以调用
stopContainers()请求 NM 清理资源(或者 NM 在一定时间后自动清理)。 - NM 的
DeletionService会异步删除该 Container 的本地工作目录和私有缓存资源。 - 最后,AM 向 RM 汇报该 Container 已使用完毕,将资源归还给集群。
总结交互时序图 (简述)
- AM --(构建 CLC)--> AM
- AM --(
startContainers(ContainerToken, CLC))--> NM - NM --(验证Token & 下载文件到本地)--> NM本地磁盘
- NM --(配置 Cgroups & 执行启动命令)--> Task OS Process
- AM --(
getContainerStatuses())--> NM (获取任务进度) - Task 结束,NM 清理本地文件。