4.3 YARN 应用开发与部署


文档摘要

4.3 YARN 应用开发与部署 4.3 YARN 应用开发与部署详解 4.3.1 YARN 应用开发概述 YARN 的出现打破了 Hadoop 1.0 中 MapReduce 独占资源管理的局面,实现了资源管理与计算框架的解耦。这意味着开发者不再局限于 MapReduce 编程模型,可以根据自身业务需求选择更合适的计算框架,并利用 YARN 提供的资源管理能力高效运行。 YARN 应用的核心思想在于将资源管理和应用管理分离。 ResourceManager (RM) 负责集群资源的统一管理和调度,而 ApplicationMaster (AM) 则作为每个应用的管理者,负责向 RM 申请资源,并将资源分配给应用内部的各个任务。

4.3 YARN 应用开发与部署

4.3 YARN 应用开发与部署详解

4.3.1 YARN 应用开发概述

YARN 的出现打破了 Hadoop 1.0 中 MapReduce 独占资源管理的局面,实现了资源管理与计算框架的解耦。这意味着开发者不再局限于 MapReduce 编程模型,可以根据自身业务需求选择更合适的计算框架,并利用 YARN 提供的资源管理能力高效运行。

YARN 应用的核心思想在于将资源管理和应用管理分离。 ResourceManager (RM) 负责集群资源的统一管理和调度,而 ApplicationMaster (AM) 则作为每个应用的管理者,负责向 RM 申请资源,并将资源分配给应用内部的各个任务。NodeManager (NM) 驻留在集群的每个节点上,负责管理本节点的资源和容器,并执行 AM 分配的任务。

开发一个 YARN 应用,核心目标是构建一个能够与 YARN 框架交互的应用程序,使其能够:

  1. 向 YARN 注册并请求资源: 应用需要通过某种方式告知 YARN 自身的需求,例如所需的 CPU 核数、内存大小、容器数量等。

  2. 管理应用的生命周期: 包括应用的启动、运行、监控和结束等环节。

  3. 在 YARN 分配的容器中执行任务: 应用需要在分配到的容器中执行实际的计算任务。

  4. 与 YARN 框架进行通信: 例如心跳汇报、状态更新、资源释放等。

理解 YARN 应用开发的关键在于理解 ApplicationMaster (AM) 的角色。AM 是 YARN 应用的核心控制组件,它运行在 YARN 容器中,负责与 ResourceManager 交互,协调应用的资源需求和任务执行。开发者需要编写 AM 的逻辑,使其能够有效地管理应用的生命周期,并利用 YARN 提供的资源完成计算任务。

4.3.2 YARN 应用架构详解

为了更好地理解 YARN 应用的开发与部署,我们首先需要深入了解 YARN 应用的架构组成,以及各个组件之间的交互关系。下图使用 Mermaid 的 graph TD 图形化展示了 YARN 应用的基本架构:

图中主要组件及其作用如下:

  • Client (客户端): 用户提交 YARN 应用的入口。客户端负责将应用的相关信息(如 AM 程序、应用配置、所需资源等)提交给 ResourceManager。

  • ResourceManager (RM, 资源管理器): YARN 集群的中央资源管理器,负责整个集群的资源管理和调度。RM 主要包含两个组件:

    • Scheduler (调度器): 根据应用的资源请求和集群的资源状况,分配资源(以 Container 的形式)。YARN 支持多种调度器,如 FIFO Scheduler, Capacity Scheduler, Fair Scheduler 等,以满足不同场景的需求。

    • ApplicationsManager (应用管理器): 负责管理集群中运行的所有应用,包括接受应用的提交请求、启动 AM、监控 AM 的运行状态等。

  • NodeManager (NM, 节点管理器): 运行在集群的每个节点上,负责管理本节点的资源(CPU, 内存, 磁盘, 网络等)和 Container。NM 会定期向 RM 汇报节点资源使用情况和 Container 运行状态,并接受 RM 的指令执行 Container 的启动、停止等操作。

  • ApplicationMaster (AM, 应用管理器): 每个 YARN 应用都有一个对应的 AM 实例,负责管理该应用的生命周期和资源协调。AM 的主要职责包括:

    • 向 RM 注册应用并协商资源: AM 启动后首先向 RM 注册,并根据应用的需求向 RM 申请资源(Container)。

    • 将任务分配到 Container: AM 获取到 Container 资源后,会将应用的各个任务分配到不同的 Container 中执行。

    • 监控任务执行状态: AM 会监控 Container 中任务的执行状态,并处理任务失败、重试等情况。

    • 与 RM 保持心跳: AM 需要定期向 RM 发送心跳,汇报自身状态,以便 RM 监控应用的运行情况。

    • 应用完成或失败后向 RM 注销: 当应用完成或失败后,AM 会向 RM 注销,释放占用的资源。

  • Container (容器): YARN 中的资源分配单位,封装了 CPU、内存、磁盘、网络等资源。NM 负责创建和管理 Container,应用的任务在 Container 中运行。Container 提供了资源隔离和限制的功能,确保不同应用之间不会相互干扰。

  • Application Task (应用任务): 应用中实际的计算任务,例如 MapReduce 中的 Map Task 和 Reduce Task,Spark 中的 Task 等。应用任务运行在 YARN 分配的 Container 中。

YARN 应用的运行流程大致如下:

  1. 客户端提交应用: 用户通过 YARN 客户端提交应用,包括应用的 JAR 包、配置文件、启动命令等。

  2. RM 接收应用请求: ResourceManager 接收到客户端的请求后,将应用信息放入调度队列。

  3. RM 调度资源并启动 AM: Scheduler 根据调度策略和集群资源状况,为应用分配资源,并在某个 NodeManager 上启动 AM Container。

  4. AM 向 RM 注册并申请资源: AM 启动后,向 RM 注册自身,并根据应用的需求向 RM 申请 Container 资源。

  5. RM 分配 Container 资源: Scheduler 根据 AM 的资源请求和集群资源状况,为 AM 分配 Container 资源。

  6. AM 在 Container 中启动任务: AM 获取到 Container 资源后,将应用的各个任务分配到不同的 Container 中执行。

  7. Container 执行任务并向 AM 汇报状态: Container 中的任务执行过程中,会定期向 AM 汇报任务执行状态。

  8. AM 监控任务状态并与 RM 保持心跳: AM 监控所有任务的执行状态,并定期向 RM 发送心跳,汇报应用状态。

  9. 应用完成或失败: 当所有任务执行完成或应用发生错误时,AM 通知 RM 应用完成或失败。

  10. RM 注销应用并回收资源: ResourceManager 注销应用,并回收应用占用的所有资源。

4.3.3 YARN 应用开发实践:一个简单的示例

为了更直观地理解 YARN 应用的开发过程,我们以一个简单的示例应用 "HelloYARN" 为例进行代码实践。该应用的功能非常简单,即在 YARN 集群中运行一个任务,打印 "Hello YARN!" 信息。

1. 项目结构:

首先,我们需要创建一个 Maven 项目,并添加 Hadoop YARN 相关的依赖。项目结构如下:

hello-yarn/ ├── pom.xml └── src/ └── main/ └── java/ └── com/example/ ├── HelloYARNApplicationMaster.java └── HelloYARNTask.java

2. pom.xml 文件:

pom.xml 文件中,添加 Hadoop YARN 客户端的依赖:

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.example</groupId> <artifactId>hello-yarn</artifactId> <version>1.0-SNAPSHOT</version> <properties> <hadoop.version>3.3.0</hadoop.version> <!-- 请替换为你的 Hadoop 版本 --> </properties> <dependencies> <dependency> <groupId>org.apache.hadoop</groupId> <artifactId>hadoop-client</artifactId> <version>${hadoop.version}</version> </dependency> <dependency> <groupId>org.apache.hadoop</groupId> <artifactId>hadoop-yarn-client</artifactId> <version>${hadoop.version}</version> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <version>3.8.1</version> <configuration> <source>1.8</source> <target>1.8</target> </configuration> </plugin> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-assembly-plugin</artifactId> <version>3.3.0</version> <configuration> <descriptorRefs> <descriptorRef>jar-with-dependencies</descriptorRef> </descriptorRefs> <archive> <manifest> <mainClass>com.example.HelloYARNApplicationMaster</mainClass> </manifest> </archive> </configuration> <executions> <execution> <id>assemble-all</id> <phase>package</phase> <goals> <goal>single</goal> </goals> </execution> </executions> </plugin> </plugins> </build> </project>

注意: 请将 <hadoop.version> 属性替换为你实际使用的 Hadoop 版本。

3. HelloYARNTask.java 文件:

HelloYARNTask.java 文件定义了在 Container 中执行的任务逻辑,这里我们简单地打印 "Hello YARN!" 信息。

package com.example; public class HelloYARNTask { public static void main(String[] args) { System.out.println("Hello YARN!"); } }

4. HelloYARNApplicationMaster.java 文件:

HelloYARNApplicationMaster.java 文件是应用的核心,负责与 YARN 框架交互,申请资源,启动任务等。

package com.example; import org.apache.hadoop.conf.Configuration; import org.apache.hadoop.yarn.api.ApplicationConstants; import org.apache.hadoop.yarn.api.protocolrecords.AllocateResponse; import org.apache.hadoop.yarn.api.protocolrecords.RegisterApplicationMasterResponse; import org.apache.hadoop.yarn.api.records.*; import org.apache.hadoop.yarn.client.api.AMRMClient; import org.apache.hadoop.yarn.client.api.NMClient; import org.apache.hadoop.yarn.conf.YarnConfiguration; import org.apache.hadoop.yarn.util.ConverterUtils; import java.util.Collections; import java.util.HashMap; import java.util.Map; public class HelloYARNApplicationMaster { public static void main(String[] args) throws Exception { Configuration conf = new YarnConfiguration(); // 1. 创建 AMRMClient 和 NMClient AMRMClient<AllocateResponse> amRmClient = AMRMClient.createAMRMClient(); amRmClient.init(conf); amRmClient.start(); NMClient nmClient = NMClient.createNMClient(); nmClient.init(conf); nmClient.start(); // 2. 向 RM 注册 AM RegisterApplicationMasterResponse appMasterResponse = amRmClient.registerApplicationMaster( "localhost", // host 0, // rpcPort "" // trackingUrl ); System.out.println("ApplicationMaster registered successfully!"); // 3. 申请 Container 资源 Resource capability = Resource.newInstance(256, 1); // 256MB 内存, 1 vcore Priority priority = Priority.newInstance(0); ResourceBlacklistRequest blacklistRequest = ResourceBlacklistRequest.newInstance(Collections.emptyList(), Collections.emptyList()); amRmClient.addContainerRequest(new ContainerRequest(capability, null, null, priority, false, blacklistRequest)); AllocateResponse allocateResponse = amRmClient.allocate(0); while (allocateResponse.getAllocatedContainers().isEmpty()) { Thread.sleep(100); allocateResponse = amRmClient.allocate(0); } Container container = allocateResponse.getAllocatedContainers().get(0); System.out.println("Container allocated: " + container.getId()); // 4. 在 Container 中启动任务 Map<String, String> env = new HashMap<>(); env.put("CLASSPATH", "./*"); // 设置 classpath,确保能找到 HelloYARNTask 类 LocalResource appJar = LocalResource.newInstanceAsRequired( ConverterUtils.getYarnUrlFromPath(ConverterUtils.getPathToUri( args[0])), // 应用 JAR 包路径,通过命令行参数传入 LocalResourceType.FILE, LocalResourceVisibility.APPLICATION, LocalResourceInitializationType.AT_CLIENT, 1, 1); Map<String, LocalResource> localResources = new HashMap<>(); localResources.put("app.jar", appJar); String command = ApplicationConstants.Environment.JAVA_HOME_DIR.$() + "/bin/java " + HelloYARNTask.class.getName() + " 1>" + ApplicationConstants.LOG_DIR_EXPANSION_VAR + "/stdout" + " 2>" + ApplicationConstants.LOG_DIR_EXPANSION_VAR + "/stderr"; ContainerLaunchContext ctx = ContainerLaunchContext.newInstance( localResources, env, Collections.singletonList(command), null, null, null ); nmClient.startContainer(container, ctx); System.out.println("Container started!"); // 5. 监控 Container 运行状态 ContainerStatus containerStatus = nmClient.getContainerStatus(container.getId(), container.getNodeId()); while (containerStatus.getState() == ContainerState.RUNNING) { Thread.sleep(1000); containerStatus = nmClient.getContainerStatus(container.getId(), container.getNodeId()); } System.out.println("Container finished with state: " + containerStatus.getState()); System.out.println("Container diagnostics: " + containerStatus.getDiagnostics()); // 6. 向 RM 注销 AM amRmClient.unregisterApplicationMaster(FinalApplicationStatus.SUCCEEDED, "HelloYARN finished", ""); System.out.println("ApplicationMaster unregistered!"); // 7. 关闭客户端 amRmClient.stop(); nmClient.stop(); } }

代码详解:

  • 步骤 1: 创建 AMRMClient 和 NMClient: AMRMClient 用于与 ResourceManager 通信,NMClient 用于与 NodeManager 通信。

  • 步骤 2: 向 RM 注册 AM: amRmClient.registerApplicationMaster() 方法向 ResourceManager 注册 ApplicationMaster。

  • 步骤 3: 申请 Container 资源: amRmClient.addContainerRequest() 方法向 ResourceManager 发送 Container 资源请求。amRmClient.allocate() 方法轮询 ResourceManager,直到获取到分配的 Container。

  • 步骤 4: 在 Container 中启动任务:

    • 设置 Container 的环境变量 CLASSPATH,确保 Container 中可以找到 HelloYARNTask 类。

    • 创建 LocalResource 对象,指定应用的 JAR 包路径。LocalResource 用于将应用所需的资源(如 JAR 包、配置文件等)分发到 Container 中。

    • 构建 Container 启动命令 command,使用 Java 命令运行 HelloYARNTask 类。

    • 创建 ContainerLaunchContext 对象,包含 Container 启动所需的资源、环境变量、命令等信息。

    • nmClient.startContainer() 方法在指定的 Container 中启动任务。

  • 步骤 5: 监控 Container 运行状态: nmClient.getContainerStatus() 方法获取 Container 的运行状态,循环检查 Container 状态,直到 Container 运行结束。

  • 步骤 6: 向 RM 注销 AM: amRmClient.unregisterApplicationMaster() 方法向 ResourceManager 注销 ApplicationMaster,释放占用的资源。

  • 步骤 7: 关闭客户端: 关闭 AMRMClientNMClient

5. 打包应用:

使用 Maven 打包应用,生成包含依赖的 JAR 包。在项目根目录下执行命令:

mvn clean package

打包成功后,会在 target 目录下生成 hello-yarn-1.0-SNAPSHOT-jar-with-dependencies.jar 文件。

4.3.4 YARN 应用部署与运行

1. 上传应用 JAR 包:

将打包好的 hello-yarn-1.0-SNAPSHOT-jar-with-dependencies.jar 文件上传到 Hadoop 集群的 HDFS 文件系统中,例如 /user/yourusername/hello-yarn.jar

2. 提交 YARN 应用:

使用 yarn jar 命令提交 YARN 应用。在 Hadoop 集群的客户端节点或配置了 Hadoop 客户端环境的机器上执行以下命令:

yarn jar /user/yourusername/hello-yarn.jar com.example.HelloYARNApplicationMaster /user/yourusername/hello-yarn.jar

命令详解:

  • yarn jar: YARN 客户端命令,用于提交 JAR 应用。

  • /user/yourusername/hello-yarn.jar: 应用的 JAR 包在 HDFS 上的路径。

  • com.example.HelloYARNApplicationMaster: ApplicationMaster 类的完整类名。

  • /user/yourusername/hello-yarn.jar: 作为命令行参数传递给 ApplicationMaster 的应用 JAR 包路径,用于 LocalResource 的创建。

3. 查看应用运行状态:

应用提交后,可以通过 YARN ResourceManager Web UI (通常地址为 http://<ResourceManagerHost>:<ResourceManagerWebAppPort>) 查看应用的运行状态、日志等信息。也可以使用 yarn application -list 命令在命令行查看正在运行的应用列表。

4. 查看应用日志:

应用的日志信息通常存储在 NodeManager 节点的日志目录下。可以通过 YARN ResourceManager Web UI 或命令行工具查看应用的日志。例如,可以使用 yarn logs -applicationId <application_id> 命令查看指定应用的日志。

5. 应用运行结果:

如果应用运行成功,可以在 Container 的标准输出日志中看到 "Hello YARN!" 的信息。日志文件路径通常在 NodeManager 节点的日志目录下,例如 hadoop-yarn-nodemanager/container-logs/container_<timestamp>_<application_id>_<container_id>/userlogs/stdout

4.3.5 YARN 应用部署策略

YARN 应用的部署策略可以根据实际应用场景和需求进行选择和调整。以下是一些常见的 YARN 应用部署策略:

  • 本地模式部署: 适用于开发和测试环境,所有 YARN 组件(RM, NM, AM, Container)都运行在同一个 JVM 进程中。配置简单,但性能有限,不适合生产环境。

  • 伪分布式模式部署: 适用于学习和实验环境,RM 和 NM 运行在同一台机器的不同进程中,模拟分布式环境。

  • 全分布式模式部署: 生产环境常用的部署模式,RM 和 NM 分布式部署在不同的机器上,实现高可用和高性能。

  • 容器化部署: 使用 Docker 等容器技术对 YARN 应用进行打包和部署,可以提高应用的隔离性、可移植性和部署效率。

  • 云平台部署: 将 YARN 集群部署在云平台上,利用云平台的弹性伸缩和按需付费等特性,降低运维成本,提高资源利用率。

选择合适的部署策略需要考虑以下因素:

  • 应用规模和性能需求: 对于大规模、高并发的应用,需要选择全分布式或云平台部署模式,以满足性能和扩展性需求。

  • 环境要求: 开发测试环境可以选择本地模式或伪分布式模式,生产环境必须选择全分布式或云平台部署模式。

  • 运维成本: 云平台部署模式可以降低运维成本,但可能会增加云服务费用。

  • 安全性要求: 生产环境部署需要考虑安全性,例如 Kerberos 认证、授权等。

4.3.6 总结与展望

YARN 作为 Hadoop 生态系统的核心组件,为各种分布式计算框架提供了统一的资源管理平台。掌握 YARN 应用开发与部署技术,对于构建基于 Hadoop 的大数据应用至关重要。随着大数据技术的不断发展,YARN 将继续发挥重要作用,并不断演进和完善,以适应更多样化的应用场景和需求。未来,YARN 将更加注重资源利用率的提升、调度策略的优化、以及与新兴技术的融合,例如容器化、Serverless 等,为大数据应用提供更加高效、灵活、可靠的运行平台。


发布者: 作者: 转发
评论区 (0)
U