Yarn 架构深度解析:核心组件与工作机制详解

文章目录

    • [1. Yarn 概述与背景](#1. Yarn 概述与背景)
      • [1.1 Yarn 的设计目标](#1.1 Yarn 的设计目标)
    • [2. Yarn 核心架构](#2. Yarn 核心架构)
      • [2.1 架构组件关系图](#2.1 架构组件关系图)
    • [3. Yarn 核心组件详解](#3. Yarn 核心组件详解)
      • [3.1 ResourceManager(RM)](#3.1 ResourceManager(RM))
        • [3.1.1 Scheduler(调度器)](#3.1.1 Scheduler(调度器))
        • [3.1.2 ApplicationsManager(应用管理器)](#3.1.2 ApplicationsManager(应用管理器))
      • [3.2 NodeManager(NM)](#3.2 NodeManager(NM))
      • [3.3 ApplicationMaster(AM)](#3.3 ApplicationMaster(AM))
      • [3.4 Container](#3.4 Container)
    • [4. Yarn 应用执行流程](#4. Yarn 应用执行流程)
    • [5. Yarn 资源调度模型](#5. Yarn 资源调度模型)
      • [5.1 资源表示](#5.1 资源表示)
      • [5.2 调度器比较](#5.2 调度器比较)
    • [6. Yarn 高可用性](#6. Yarn 高可用性)
      • [6.1 ResourceManager HA](#6.1 ResourceManager HA)
      • [6.2 故障恢复流程](#6.2 故障恢复流程)
    • [7. 实际应用案例:运行MapReduce作业](#7. 实际应用案例:运行MapReduce作业)
      • [7.1 提交MapReduce作业](#7.1 提交MapReduce作业)
      • [7.2 监控作业状态](#7.2 监控作业状态)
    • [8. 总结](#8. 总结)

1. Yarn 概述与背景

Apache Yarn(Yet Another Resource Negotiator)是Hadoop 2.0引入的核心组件,主要负责集群资源管理和作业调度。在Hadoop 1.0中,MapReduce既负责计算又负责资源管理,这种紧耦合架构存在扩展性差、资源利用率低等问题。Yarn的出现将资源管理与计算框架分离,使得Hadoop集群能够支持多种计算模型。

1.1 Yarn 的设计目标

  • 可扩展性:支持数千节点的大型集群
  • 高可用性:关键组件支持故障恢复
  • 多租户:支持多个用户和组织共享集群资源
  • 兼容性:保持对MapReduce作业的兼容
  • 灵活性:支持多种计算框架(MapReduce、Spark、Flink等)

2. Yarn 核心架构

Yarn采用主从(Master-Slave)架构,主要由ResourceManager、NodeManager、ApplicationMaster和Container等组件构成。
Client ResourceManager ApplicationMaster NodeManager 1 NodeManager 2 NodeManager 3 Container Container Container Container

2.1 架构组件关系图

上面的流程图清晰地展示了Yarn各组件之间的交互关系:

  • Client向ResourceManager提交应用
  • ResourceManager为应用分配ApplicationMaster
  • ApplicationMaster向ResourceManager申请资源
  • ApplicationMaster与NodeManager通信启动Container
  • Container执行具体的计算任务

3. Yarn 核心组件详解

3.1 ResourceManager(RM)

ResourceManager是Yarn集群的主节点,负责整个系统的资源管理和分配。它由两个主要组件构成:

3.1.1 Scheduler(调度器)

调度器纯负责资源分配,根据容量、队列等限制条件将系统资源分配给各个运行中的应用。调度器是一个可插拔的组件,Yarn提供了以下几种调度器:

  • FIFO Scheduler:先进先出调度器
  • Capacity Scheduler:容量调度器(默认)
  • Fair Scheduler:公平调度器
3.1.2 ApplicationsManager(应用管理器)

负责接收作业提交,为应用分配第一个Container来运行ApplicationMaster,并提供应用重启功能。

java 复制代码
// ResourceManager 核心配置示例
public class ResourceManagerConfig {
    public static void main(String[] args) {
        Configuration conf = new YarnConfiguration();
        
        // 设置ResourceManager地址
        conf.set("yarn.resourcemanager.address", "rm-host:8032");
        conf.set("yarn.resourcemanager.scheduler.address", "rm-host:8030");
        conf.set("yarn.resourcemanager.resource-tracker.address", "rm-host:8031");
        conf.set("yarn.resourcemanager.admin.address", "rm-host:8033");
        conf.set("yarn.resourcemanager.webapp.address", "rm-host:8088");
        
        // 设置调度器类型
        conf.set("yarn.resourcemanager.scheduler.class", 
                "org.apache.hadoop.yarn.server.resourcemanager.scheduler.capacity.CapacityScheduler");
        
        // 设置NodeManager资源
        conf.set("yarn.nodemanager.resource.memory-mb", "8192");
        conf.set("yarn.nodemanager.resource.cpu-vcores", "8");
    }
}

3.2 NodeManager(NM)

NodeManager是Yarn集群的从节点,负责单个节点的资源管理和任务执行。主要功能包括:

  • 定时向ResourceManager汇报本节点资源使用情况
  • 接收并处理来自ApplicationMaster的Container启动/停止请求
  • 管理Container的生命周期
  • 监控Container的资源使用情况
java 复制代码
// NodeManager 配置示例
public class NodeManagerConfig {
    public static void main(String[] args) {
        Configuration conf = new YarnConfiguration();
        
        // 设置资源分配
        conf.set("yarn.nodemanager.resource.memory-mb", "16384");
        conf.set("yarn.nodemanager.resource.cpu-vcores", "16");
        conf.set("yarn.nodemanager.vmem-pmem-ratio", "2.1");
        
        // 设置本地目录
        conf.set("yarn.nodemanager.local-dirs", "/hadoop/yarn/local");
        conf.set("yarn.nodemanager.log-dirs", "/hadoop/yarn/log");
        
        // 设置Container执行器
        conf.set("yarn.nodemanager.container-executor.class", 
                "org.apache.hadoop.yarn.server.nodemanager.DefaultContainerExecutor");
        
        // 健康检查配置
        conf.set("yarn.nodemanager.health-checker.script.path", 
                "/hadoop/yarn/healthcheck/health-check.sh");
        conf.set("yarn.nodemanager.health-checker.interval-ms", "135000");
    }
}

3.3 ApplicationMaster(AM)

ApplicationMaster是应用级别的"管理者",每个应用对应一个AM实例,负责:

  • 与ResourceManager协商资源
  • 与NodeManager通信启动/停止Container
  • 监控应用执行状态和进度
  • 在应用失败时向ResourceManager申请重启
java 复制代码
// 自定义ApplicationMaster示例
public class CustomApplicationMaster {
    
    private AMRMClientAsync<AMRMClient.ContainerRequest> resourceManager;
    private NMClientAsync nodeManager;
    private String appMasterHostname;
    private int appMasterRpcPort;
    private String appMasterTrackingUrl;
    
    public void run() throws Exception {
        // 初始化AM
        init();
        
        // 注册AM到RM
        registerApplicationMaster();
        
        // 申请容器
        allocateContainers();
        
        // 监控应用进度
        monitorApplication();
        
        // 应用完成,注销AM
        unregisterApplicationMaster();
    }
    
    private void init() {
        // 创建AMRMClient
        AMRMClientAsync.CallbackHandler allocListener = new RMCallbackHandler();
        resourceManager = AMRMClientAsync.createAMRMClientAsync(1000, allocListener);
        resourceManager.init(conf);
        resourceManager.start();
        
        // 创建NMClient
        NMClientAsync.CallbackHandler containerListener = new NMCallbackHandler();
        nodeManager = NMClientAsync.createNMClientAsync(containerListener);
        nodeManager.init(conf);
        nodeManager.start();
    }
    
    private void registerApplicationMaster() throws Exception {
        appMasterHostname = NetUtils.getHostname();
        RegisterApplicationMasterResponse response = 
            resourceManager.registerApplicationMaster(appMasterHostname, appMasterRpcPort, appMasterTrackingUrl);
        
        // 处理注册响应
        int maxMem = response.getMaximumResourceCapability().getMemory();
        int maxVCores = response.getMaximumResourceCapability().getVirtualCores();
        System.out.println("Max mem capability: " + maxMem + ", Max vcores capability: " + maxVCores);
    }
    
    // 其他方法实现...
}

3.4 Container

Container是Yarn中的资源抽象,封装了某个节点上的多维度资源,如内存、CPU、磁盘、网络等。Container具有以下特点:

  • 动态分配:由ResourceManager按需分配
  • 资源隔离:使用cgroups等技术实现资源隔离
  • 生命周期:由ApplicationMaster管理创建和销毁

4. Yarn 应用执行流程

4.1 详细执行流程图

Client ResourceManager ApplicationMaster NodeManager Container submitApplication() 创建AppContext startContainer(AMContainer) launch Container ApplicationMaster启动 registerApplicationMaster() request Containers allocate Containers startContainer(TaskContainer) launch Container 执行任务 汇报状态 汇报进度 unregisterApplicationMaster() 应用完成通知 Client ResourceManager ApplicationMaster NodeManager Container

4.2 执行步骤详解

步骤1:应用提交

客户端调用ResourceManager的submitApplication()方法提交应用。

java 复制代码
// 应用提交代码示例
public class YarnApplicationClient {
    public static void main(String[] args) throws Exception {
        // 创建Yarn客户端
        YarnClient yarnClient = YarnClient.createYarnClient();
        Configuration conf = new YarnConfiguration();
        yarnClient.init(conf);
        yarnClient.start();
        
        // 创建应用
        YarnClientApplication app = yarnClient.createApplication();
        GetNewApplicationResponse appResponse = app.getNewApplicationResponse();
        
        // 设置应用提交上下文
        ApplicationSubmissionContext appContext = app.getApplicationSubmissionContext();
        ApplicationId appId = appContext.getApplicationId();
        
        // 设置应用名称
        appContext.setApplicationName("custom-yarn-app");
        
        // 设置Container启动上下文
        ContainerLaunchContext amContainer = Records.newRecord(ContainerLaunchContext.class);
        
        // 设置本地资源(jar包、配置文件等)
        Map<String, LocalResource> localResources = new HashMap<>();
        
        // 设置CLASSPATH
        Map<String, String> appMasterEnv = new HashMap<>();
        setupAppMasterEnv(appMasterEnv);
        
        // 设置ApplicationMaster命令
        Vector<CharSequence> vargs = new Vector<>(30);
        vargs.add(Environment.JAVA_HOME.$() + "/bin/java");
        vargs.add("-Xmx256m");
        vargs.add("com.example.CustomApplicationMaster");
        vargs.add("1><LOG_DIR>/AppMaster.stdout");
        vargs.add("2><LOG_DIR>/AppMaster.stderr");
        
        List<String> commands = new ArrayList<>();
        for (CharSequence str : vargs) {
            commands.add(str.toString());
        }
        
        amContainer.setCommands(commands);
        
        // 设置资源能力
        Resource capability = Records.newRecord(Resource.class);
        capability.setMemory(256);
        capability.setVirtualCores(1);
        appContext.setResource(capability);
        
        // 设置队列
        appContext.setQueue("default");
        
        // 提交应用
        yarnClient.submitApplication(appContext);
        
        // 监控应用状态
        monitorApplication(appId, yarnClient);
        
        yarnClient.stop();
    }
    
    private static void setupAppMasterEnv(Map<String, String> env) {
        // 添加CLASSPATH
        StringBuilder classPathEnv = new StringBuilder()
            .append(Environment.CLASSPATH.$()).append(File.pathSeparator)
            .append("./*");
        for (String c : conf.getStrings(YarnConfiguration.YARN_APPLICATION_CLASSPATH, 
                YarnConfiguration.DEFAULT_YARN_APPLICATION_CLASSPATH)) {
            classPathEnv.append(File.pathSeparator);
            classPathEnv.append(c.trim());
        }
        env.put("CLASSPATH", classPathEnv.toString());
    }
    
    private static void monitorApplication(ApplicationId appId, YarnClient yarnClient) throws Exception {
        while (true) {
            ApplicationReport report = yarnClient.getApplicationReport(appId);
            YarnApplicationState state = report.getYarnApplicationState();
            
            System.out.println("Application State: " + state);
            
            if (state == YarnApplicationState.FINISHED || 
                state == YarnApplicationState.KILLED || 
                state == YarnApplicationState.FAILED) {
                break;
            }
            
            Thread.sleep(1000);
        }
    }
}
步骤2:ApplicationMaster启动

ResourceManager选择一个NodeManager启动ApplicationMaster容器。

步骤3:应用注册

ApplicationMaster向ResourceManager注册自己。

java 复制代码
// ApplicationMaster注册实现
public class ApplicationMasterImpl {
    public void registerWithRM() throws Exception {
        RegisterApplicationMasterResponse response = 
            amRMClient.registerApplicationMaster(appMasterHostname, appMasterRpcPort, appMasterTrackingUrl);
        
        // 从响应中获取集群资源信息
        Resource maxCapability = response.getMaximumResourceCapability();
        System.out.println("Max cluster capability: " + 
            maxCapability.getMemory() + " MB memory, " + 
            maxCapability.getVirtualCores() + " vcores");
    }
}
步骤4:资源请求与分配

ApplicationMaster根据应用需求向ResourceManager申请资源。

java 复制代码
// 资源请求示例
public class ResourceAllocation {
    public void requestContainers(int containerCount, int memory, int vCores) {
        for (int i = 0; i < containerCount; i++) {
            Priority priority = Records.newRecord(Priority.class);
            priority.setPriority(0);
            
            Resource capability = Records.newRecord(Resource.class);
            capability.setMemory(memory);
            capability.setVirtualCores(vCores);
            
            // 创建容器请求
            AMRMClient.ContainerRequest containerRequest = 
                new AMRMClient.ContainerRequest(capability, null, null, priority);
            
            // 发送资源请求
            amRMClient.addContainerRequest(containerRequest);
        }
    }
}
步骤5:容器启动与任务执行

ApplicationMaster在分配的容器中启动具体任务。

java 复制代码
// 容器启动实现
public class ContainerLauncher {
    public void launchContainer(Container container, String command) {
        ContainerLaunchContext ctx = Records.newRecord(ContainerLaunchContext.class);
        
        // 设置环境变量
        Map<String, String> containerEnv = new HashMap<>();
        containerEnv.put("CLASSPATH", "./*:$CLASSPATH");
        
        // 设置启动命令
        Vector<CharSequence> commands = new Vector<>();
        commands.add(command);
        List<String> cmds = new ArrayList<>();
        for (CharSequence cmd : commands) {
            cmds.add(cmd.toString());
        }
        ctx.setCommands(cmds);
        
        // 启动容器
        nmClientAsync.startContainerAsync(container, ctx);
    }
}
步骤6:进度监控与完成处理

ApplicationMaster监控任务进度,在完成后向ResourceManager注销。

java 复制代码
// 应用完成处理
public class ApplicationCompletion {
    public void completeApplication() {
        try {
            // 应用成功完成
            amRMClient.unregisterApplicationMaster(
                FinalApplicationStatus.SUCCEEDED, "Application completed successfully", null);
        } catch (Exception ex) {
            // 处理异常情况
            amRMClient.unregisterApplicationMaster(
                FinalApplicationStatus.FAILED, "Application failed: " + ex.getMessage(), null);
        }
    }
}

5. Yarn 资源调度模型

5.1 资源表示

Yarn使用多维资源模型,主要包括:

  • 内存(Memory):以MB为单位
  • CPU(vCores):虚拟核心数
  • 扩展资源:GPU、FPGA等特殊资源
xml 复制代码
<!-- yarn-site.xml 资源配置 -->
<configuration>
  <property>
    <name>yarn.nodemanager.resource.memory-mb</name>
    <value>16384</value>
    <description>NodeManager可用物理内存</description>
  </property>
  
  <property>
    <name>yarn.nodemanager.resource.cpu-vcores</name>
    <value>16</value>
    <description>NodeManager可用虚拟核心数</description>
  </property>
  
  <property>
    <name>yarn.scheduler.minimum-allocation-mb</name>
    <value>1024</value>
    <description>单个容器最小内存分配</description>
  </property>
  
  <property>
    <name>yarn.scheduler.maximum-allocation-mb</name>
    <value>16384</value>
    <description>单个容器最大内存分配</description>
  </property>
</configuration>

5.2 调度器比较

调度器类型 优点 缺点 适用场景
FIFO 简单、开销小 不适合多用户、小作业容易饿死 测试环境、单用户
Capacity 资源保障、多租户支持 配置复杂、资源可能闲置 生产环境、多部门共享
Fair 动态资源分配、公平性 配置复杂、性能波动 多用户、交互式查询

6. Yarn 高可用性

Yarn通过以下机制实现高可用:

6.1 ResourceManager HA

xml 复制代码
<!-- RM高可用配置 -->
<configuration>
  <property>
    <name>yarn.resourcemanager.ha.enabled</name>
    <value>true</value>
  </property>
  
  <property>
    <name>yarn.resourcemanager.ha.rm-ids</name>
    <value>rm1,rm2</value>
  </property>
  
  <property>
    <name>yarn.resourcemanager.hostname.rm1</name>
    <value>rm1-host.com</value>
  </property>
  
  <property>
    <name>yarn.resourcemanager.hostname.rm2</name>
    <value>rm2-host.com</value>
  </property>
  
  <property>
    <name>yarn.resourcemanager.zk-address</name>
    <value>zk1:2181,zk2:2181,zk3:2181</value>
  </property>
</configuration>

6.2 故障恢复流程

ActiveRM StandbyRM ZooKeeper NodeManager ApplicationMaster 正常状态 保持活跃状态 监控活跃状态 发生故障 连接断开 检测到故障 转换为Active 重新同步状态 汇报容器状态 重新建立连接 恢复资源请求 ActiveRM StandbyRM ZooKeeper NodeManager ApplicationMaster

7. 实际应用案例:运行MapReduce作业

7.1 提交MapReduce作业

bash 复制代码
# 提交WordCount作业到Yarn
hadoop jar $HADOOP_HOME/share/hadoop/mapreduce/hadoop-mapreduce-examples-*.jar \
  wordcount \
  -D mapreduce.job.queuename=default \
  -D mapreduce.job.name=WordCountExample \
  input output

7.2 监控作业状态

java 复制代码
// 通过Yarn API监控作业
public class JobMonitor {
    public static void monitorJob(ApplicationId appId) throws Exception {
        YarnClient yarnClient = YarnClient.createYarnClient();
        yarnClient.init(new YarnConfiguration());
        yarnClient.start();
        
        while (true) {
            ApplicationReport report = yarnClient.getApplicationReport(appId);
            System.out.println("Application ID: " + appId);
            System.out.println("Application State: " + report.getYarnApplicationState());
            System.out.println("Final Status: " + report.getFinalApplicationStatus());
            System.out.println("Progress: " + report.getProgress() * 100 + "%");
            
            if (report.getYarnApplicationState() == YarnApplicationState.FINISHED ||
                report.getYarnApplicationState() == YarnApplicationState.FAILED ||
                report.getYarnApplicationState() == YarnApplicationState.KILLED) {
                break;
            }
            
            Thread.sleep(5000);
        }
        
        yarnClient.stop();
    }
}

8. 总结

Apache Yarn作为Hadoop生态系统中的资源管理平台,通过将资源管理与计算框架分离,实现了集群资源的高效利用和多计算框架的支持。其核心架构包含ResourceManager、NodeManager、ApplicationMaster和Container等组件,通过精心设计的交互协议实现分布式应用的调度和执行。

Yarn的优势主要体现在:

  • 资源利用率高:通过细粒度资源分配提高集群利用率
  • 扩展性强:支持数千节点的大规模集群
  • 多框架支持:可运行MapReduce、Spark、Flink等多种计算框架
  • 高可用性:关键组件支持故障自动恢复

随着大数据技术的不断发展,Yarn继续在云原生、容器化等方向演进,为大数据应用提供更加灵活、高效的资源管理能力。

相关推荐
碧海潮生_CC1 小时前
【CUDA笔记】03 CUDA GPU 架构与一般的程序优化思路(下)
笔记·架构·cuda
XSKY星辰天合1 小时前
星飞全闪以架构创新对冲 SSD 涨价,实现更低 TCO
架构·分布式存储·星飞·全闪
pengzhuofan3 小时前
Gateway微服务网关
微服务·架构·gateway
川Princess4 小时前
【面试经验】百度Agent架构研发工程师一面
面试·职场和发展·架构·agent
Tezign_space5 小时前
技术方案|构建品牌KOS内容中台:三种架构模式与AI赋能实践
人工智能·架构·数字化转型·小红书·kos·内容营销·内容科技
e***95646 小时前
springboot项目架构
spring boot·后端·架构
平凡之大路7 小时前
【企业架构】TOGAF架构标准规范-实现治理
架构·togaf
鹏北海8 小时前
从“版本号打架”到 30 秒内提醒用户刷新:一个微前端团队的实践
前端·面试·架构
喜欢你,还有大家9 小时前
DaemonSet && service && ingress的
linux·架构·kubernetes