Hadoop 中的大数据技术:Yarn
第一章 YARN资源调度器
思考:
- 如何有效地管理集群资源?
- 如何合理地为任务分配资源?
YARN(Yet Another Resource Negotiator)是一个分布式资源管理系统,它为各种计算任务提供统一的资源管理和调度。可以将YARN视作一个分布式的操作系统平台,而像MapReduce这样的计算框架则相当于在其上运行的应用程序。
1.1 YARN的基础架构
YARN主要由以下几个核心组件构成:
- ResourceManager (RM):集群资源管理器,负责整个集群资源的管理和调度。
- NodeManager (NM):单个节点上的资源管理器,执行具体的资源管理和监控。
- ApplicationMaster (AM):每个应用程序的管理者,负责应用程序的任务调度和协调。
- Container:封装了计算任务所需的资源(如内存、CPU等),是资源分配的基本单位。
1.2 YARN的工作机制
以下是YARN处理MapReduce作业的一般流程:
- 作业提交 :
- 第一步:客户端调用
job.waitForCompletion
方法,向集群提交MapReduce作业。 - 第二步:客户端向ResourceManager申请一个作业ID。
- 第三步:ResourceManager返回作业资源的提交路径和作业ID。
- 第四步:客户端将jar包、切片信息及配置文件提交到指定的资源提交路径。
- 第五步:客户端向ResourceManager申请运行ApplicationMaster。
- 第一步:客户端调用
- 作业初始化 :
- 第六步:ResourceManager将作业添加到调度器中。
- 第七步:某个空闲的NodeManager领取到该作业。
- 第八步:该NodeManager创建Container,并启动ApplicationMaster。
- 第九步:Container从HDFS下载客户端提交的资源。
- 任务分配 :
- 第十步:ApplicationMaster向ResourceManager申请运行MapTask的资源。
- 第十一步:ResourceManager将MapTask分配给其他NodeManager,后者创建相应的Containers。
- 任务运行 :
- 第十二步:ApplicationMaster指示NodeManager启动MapTasks,执行数据分区和排序。
- 第十三步:ApplicationMaster等待所有MapTasks完成后,再向ResourceManager申请运行ReduceTasks的容器。
- 第十四步:ReduceTasks从MapTasks获取数据分区。
- 第十五步:任务完成后,ApplicationMaster向ResourceManager申请注销。
- 进度与状态更新 :
- 任务进程会将其进度和状态返回给ApplicationMaster,客户端定期向ApplicationMaster请求进度更新并展示给用户。
- 作业完成 :
- 除了定期请求作业进度外,客户端还会周期性地通过调用
waitForCompletion
检查作业是否完成。一旦作业完成,ApplicationMaster和Containers会进行清理工作,作业信息会被保存到作业历史服务器供日后查阅。
- 除了定期请求作业进度外,客户端还会周期性地通过调用
1.3 调度器与调度算法
Hadoop支持多种调度器,主要包括:
-
FIFO调度器:
单队列调度器,按提交顺序处理作业。
- 优点:实现简单。
- 缺点:不支持多队列,不适合生产环境。
-
容量调度器 (Capacity Scheduler):多队列调度器,支持队列间的资源共享。
-
公平调度器 (Fair Scheduler):多队列调度器,支持动态资源分配,保证资源公平使用。
在Hadoop 3.1.3版本中,默认使用的资源调度器是Capacity Scheduler,而在CDH框架中,默认调度器是Fair Scheduler。调度器的具体配置可以在yarn-default.xml
文件中找到。
1.4 YARN 常用命令
YARN 提供了一系列命令行工具来帮助管理员和开发者监控和管理集群中的应用程序。下面是一些常用的 YARN 命令及其用途。
1.4.1 查看应用程序状态
-
列出所有应用程序:
yarn application -list
-
根据状态过滤应用程序:
yarn application -list -appStates <状态>
其中
<状态>
可以是ALL
,NEW
,NEW_SAVING
,SUBMITTED
,ACCEPTED
,RUNNING
,FINISHED
,FAILED
,KILLED
。 -
终止应用程序:
yarn application -kill <ApplicationId>
1.4.2 查看日志
-
查询应用程序日志:
yarn logs -applicationId <ApplicationId>
-
查询容器日志:
yarn logs -applicationId <ApplicationId> -containerId <ContainerId>
1.4.3 查看应用程序尝试
-
列出应用程序的所有尝试:
yarn applicationattempt -list <ApplicationId>
-
查看应用程序尝试的状态:
yarn applicationattempt -status <ApplicationAttemptId>
1.4.4 查看容器
-
列出所有容器:
yarn container -list <ApplicationAttemptId>
-
查看容器状态:
yarn container -status <ContainerId>
1.4.5 查看节点状态
-
列出所有节点:
yarn node -list -all
1.4.6 更新配置
-
刷新队列配置:
yarn rmadmin -refreshQueues
1.4.7 查看队列信息
-
打印队列信息:
yarn queue -status <QueueName>
第二章 Yarn案例实操
2.1YARN 生产环境核心参数配置实践
概要
本章节旨在通过调整 YARN 集群的关键参数来优化一项典型的大数据处理作业------统计1GB数据集中每个单词的出现次数。我们的集群由三台服务器组成,每台服务器配备4GB内存和4核CPU(4线程)。
分析
- MapTask 数量: 1GB数据集按128MB为单位分割,大约需要8个MapTask。
- ReduceTask 数量: 1个ReduceTask用于汇总最终结果。
- 任务分配: 每台服务器平均运行3个任务左右(MapTask + ReduceTask + MR AppMaster)。
参数配置
为了实现上述目标,我们需要调整yarn-site.xml
中的相关配置项。
1. 选择调度器
<property>
<name>yarn.resourcemanager.scheduler.class</name>
<value>org.apache.hadoop.yarn.server.resourcemanager.scheduler.capacity.CapacityScheduler</value>
</property>
2. ResourceManager调度请求处理线程数
<property>
<name>yarn.resourcemanager.scheduler.client.thread-count</name>
<value>8</value>
</property>
3. 禁用硬件配置自动检测
<property>
<name>yarn.nodemanager.resource.detect-hardware-capabilities</name>
<value>false</value>
</property>
4. 不计算逻辑处理器作为核心
<property>
<name>yarn.nodemanager.resource.count-logical-processors-as-cores</name>
<value>false</value>
</property>
5. 虚拟核心数与物理核心数的乘数
<property>
<name>yarn.nodemanager.resource.pcores-vcores-multiplier</name>
<value>1.0</value>
</property>
6. NodeManager可用内存
<property>
<name>yarn.nodemanager.resource.memory-mb</name>
<value>4096</value>
</property>
7. NodeManager的CPU核数
<property>
<name>yarn.nodemanager.resource.cpu-vcores</name>
<value>4</value>
</property>
8. 容器最小内存
<property>
<name>yarn.scheduler.minimum-allocation-mb</name>
<value>1024</value>
</property>
9. 容器最大内存
<property>
<name>yarn.scheduler.maximum-allocation-mb</name>
<value>2048</value>
</property>
10. 容器最小CPU核数
<property>
<name>yarn.scheduler.minimum-allocation-vcores</name>
<value>1</value>
</property>
11. 容器最大CPU核数
<property>
<name>yarn.scheduler.maximum-allocation-vcores</name>
<value>2</value>
</property>
12. 禁用虚拟内存检查
<property>
<name>yarn.nodemanager.vmem-check-enabled</name>
<value>false</value>
</property>
13. 虚拟内存与物理内存比例
<property>
<name>yarn.nodemanager.vmem-pmem-ratio</name>
<value>2.1</value>
</property>
分发配置
- 注意:如果集群内的各个节点硬件资源不同,则需要针对每个
NodeManager
单独配置。
重启集群
-
停止 YARN 服务
[lzl@hadoop12 hadoop-3.1.3]$ sbin/stop-yarn.sh
-
启动 YARN 服务
[lzl@hadoop13 hadoop-3.1.3]$ sbin/start-yarn.sh
执行WordCount程序
[lzl@hadoop12 hadoop-3.1.3]$ hadoop jar share/hadoop/mapreduce/hadoop-mapreduce-examples-3.1.3.jar wordcount /input /output
观察YARN任务执行情况
-
通过访问以下 URL 查看 YARN 任务执行页面:
http://hadoop13:8088/cluster/apps
2.2多队列容量调度器配置及应用案例
概要
在生产环境中,单一的默认队列往往难以满足复杂资源管理和任务调度的需求。通过创建多个队列,可以更精细地控制资源分配,确保关键任务得到优先执行。
创建多队列的原因
- 单一队列可能无法满足不同框架或业务的需求。
- 可以根据框架(如 Hive、Spark、Flink)或业务模块(如登录注册、购物车、下单等)划分队列。
- 防止意外的资源耗尽问题。
- 实现任务优先级管理,在特殊时期保障重要任务的资源供应。
需求
- 需求1 :配置
default
队列占用总内存的40%,最大资源容量为总资源的60%;hive
队列占用总内存的60%,最大资源容量为总资源的80%。 - 需求2:配置队列优先级。
配置步骤
-
修改
capacity-scheduler.xml
定义队列
<property> <name>yarn.scheduler.capacity.root.queues</name> <value>default,hive</value> </property>
调整
default
队列资源<property> <name>yarn.scheduler.capacity.root.default.capacity</name> <value>40</value> </property> <property> <name>yarn.scheduler.capacity.root.default.maximum-capacity</name> <value>60</value> </property>
新增
hive
队列配置<property> <name>yarn.scheduler.capacity.root.hive.capacity</name> <value>60</value> </property> property> <name>yarn.scheduler.capacity.root.hive.user-limit-factor</name> <value>1</value> </property> <property> <name>yarn.scheduler.capacity.root.hive.maximum-capacity</name> <value>80</value> </property> <property> <name>yarn.scheduler.capacity.root.hive.state</name> <value>RUNNING</value> </property> <property> <name>yarn.scheduler.capacity.root.hive.acl_submit_applications</name> <value>*</value> </property> <property> <name>yarn.scheduler.capacity.root.hive.acl_administer_queue</name> <value>*</value> </property> <property> <name>yarn.scheduler.capacity.root.hive.acl_application_max_priority</name> <value>*</value> </property> <property> <name>yarn.scheduler.capacity.root.hive.maximum-application-lifetime</name> <value>-1</value> </property> <property> <name>yarn.scheduler.capacity.root.hive.default-application-lifetime</name> <value>-1</value> </property>
-
分发配置文件
确保所有节点上的配置文件保持一致。
-
重启YARN或刷新队列
[lzl@hadoop12 hadoop-3.1.3]$ yarn rmadmin -refreshQueues
向hive
队列提交任务
-
使用
hadoop jar
命令[lzl@hadoop12 hadoop-3.1.3]$ hadoop jar share/hadoop/mapreduce/hadoop-mapreduce-examples-3.1.3.jar wordcount -D mapreduce.job.queuename=hive /input /output
-
使用Java Driver方式
public class WcDriver { public static void main(String[] args) throws IOException, ClassNotFoundException, InterruptedException { Configuration conf = new Configuration(); conf.set("mapreduce.job.queuename", "hive"); // 1. 获取Job实例 Job job = Job.getInstance(conf); // ... 其他配置 ... // 6. 提交Job boolean result = job.waitForCompletion(true); System.exit(result ? 0 : 1); } }
配置任务优先级
-
修改
yarn-site.xml
<property> <name>yarn.cluster.max-application-priority</name> <value>5</value> </property>
-
分发配置并重启YARN
[lzl@hadoop12 hadoop]$ xsync yarn-site.xml [lzl@hadoop13 hadoop-3.1.3]$ sbin/stop-yarn.sh [lzl@hadoop13 hadoop-3.1.3]$ sbin/start-yarn.sh
-
模拟资源紧张环境
[lzl@hadoop12 hadoop-3.1.3]$ hadoop jar /opt/module/hadoop-3.1.3/share/hadoop/mapreduce/hadoop-mapreduce-examples-3.1.3.jar pi 5 2000000
-
提交高优先级任务
[lzl@hadoop12 hadoop-3.1.3]$ hadoop jar /opt/module/hadoop-3.1.3/share/hadoop/mapreduce/hadoop-mapreduce-examples-3.1.3.jar pi -D mapreduce.job.priority=5 5 2000000
-
更新正在执行任务的优先级
[lzl@hadoop12 hadoop-3.1.3]$ yarn application -appID <ApplicationID> -updatePriority 5
2.3 公平调度器案例
需求概述
本节将指导您如何配置公平调度器来创建两个队列,分别为 test
和 lzl
,以满足以下需求:
- 如果用户提交任务时指定了队列,则任务将在指定的队列中运行。
- 如果用户未指定队列,
test
用户提交的任务将运行在root.group.test
队列中,而lzl
用户提交的任务将运行在root.group.lzl
队列中。
配置多队列的公平调度器
-
修改
yarn-site.xml
文件:<configuration> <property> <name>yarn.resourcemanager.scheduler.class</name> <value>org.apache.hadoop.yarn.server.resourcemanager.scheduler.fair.FairScheduler</value> <description>配置使用公平调度器</description> </property> <property> <name>yarn.scheduler.fair.allocation.file</name> <value>/opt/module/hadoop-3.1.3/etc/hadoop/fair-scheduler.xml</value> <description>指明公平调度器队列分配配置文件</description> </property> <property> <name>yarn.scheduler.fair.preemption</name> <value>false</value> <description>禁止队列间资源抢占</description> </property> </configuration>
-
配置
fair-scheduler.xml
文件:<?xml version="1.0"?> <allocations> <queueMaxAMShareDefault>0.5</queueMaxAMShareDefault> <queueMaxResourcesDefault>4096mb,4vcores</queueMaxResourcesDefault> <queue name="test"> <minResources>2048mb,2vcores</minResources> <maxResources>4096mb,4vcores</maxResources> <maxRunningApps>4</maxRunningApps> <maxAMShare>0.5</maxAMShare> <weight>1.0</weight> <schedulingPolicy>fair</schedulingPolicy> </queue> <queue name="lzl" type="parent"> <minResources>2048mb,2vcores</minResources> <maxResources>4096mb,4vcores</maxResources> <maxRunningApps>4</maxRunningApps> <maxAMShare>0.5</maxAMShare> <weight>1.0</weight> <schedulingPolicy>fair</schedulingPolicy> </queue> <queuePlacementPolicy> <rule name="specified" create="false"/> <rule name="nestedUserQueue" create="true"> <rule name="primaryGroup" create="false"/> </rule> <rule name="reject" /> </queuePlacementPolicy> </allocations>
-
分发配置并重启 YARN:
[lzl@hadoop12 hadoop]$ xsync yarn-site.xml [lzl@hadoop12 hadoop]$ xsync fair-scheduler.xml [lzl@hadoop13 hadoop-3.1.3]$ sbin/stop-yarn.sh [lzl@hadoop13 hadoop-3.1.3]$ sbin/start-yarn.sh
测试提交任务
-
提交任务时指定队列:
[lzl@hadoop12 hadoop-3.1.3]$ hadoop jar /opt/module/hadoop-3.1.3/share/hadoop/mapreduce/hadoop-mapreduce-examples-3.1.3.jar pi -Dmapreduce.job.queuename=root.test 1 1
-
提交任务时不指定队列:
[lzl@hadoop12 hadoop-3.1.3]$ hadoop jar /opt/module/hadoop-3.1.3/share/hadoop/mapreduce/hadoop-mapreduce-examples-3.1.3.jar pi 1 1
2.4 YARN 的 Tool 接口案例
-
需求: 实现一个能够动态接收参数的 MapReduce 应用程序,以便灵活地指定队列和其他配置选项。
-
具体步骤:
创建 Maven 项目
YarnDemo
:<?xml version="1.0" encoding="UTF-8"?> <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.lzl.hadoop</groupId> <artifactId>yarn_tool_test</artifactId> <version>1.0-SNAPSHOT</version> <dependencies> <dependency> <groupId>org.apache.hadoop</groupId> <artifactId>hadoop-client</artifactId> <version>3.1.3</version> </dependency> </dependencies> </project>
创建
WordCount
类实现Tool
接口:package com.lzl.yarn; import org.apache.hadoop.conf.Configuration; import org.apache.hadoop.fs.Path; import org.apache.hadoop.io.IntWritable; import org.apache.hadoop.io.LongWritable; import org.apache.hadoop.io.Text; import org.apache.hadoop.mapreduce.Job; import org.apache.hadoop.mapreduce.Mapper; import org.apache.hadoop.mapreduce.Reducer; import org.apache.hadoop.mapreduce.lib.input.FileInputFormat; import org.apache.hadoop.mapreduce.lib.output.FileOutputFormat; import org.apache.hadoop.util.Tool; import java.io.IOException; public class WordCount implements Tool { private Configuration conf; @Override public int run(String[] args) throws Exception { // ... (省略代码) } @Override public void setConf(Configuration conf) { this.conf = conf; } @Override public Configuration getConf() { return conf; } // ... (Mapper, Reducer classes) }
创建
WordCountDriver
类:package com.lzl.yarn; import org.apache.hadoop.conf.Configuration; import org.apache.hadoop.util.Tool; import org.apache.hadoop.util.ToolRunner; public class WordCountDriver { private static Tool tool; public static void main(String[] args) throws Exception { // ... (省略代码) } }
在 HDFS 上准备输入文件:
[lzl@hadoop12 hadoop-3.1.3]$ yarn jar YarnDemo.jar com.lzl.yarn.WordCountDriver wordcount /input /output
示例:添加队列参数:
[lzl@hadoop12 hadoop-3.1.3]$ yarn jar YarnDemo.jar com.lzl.yarn.WordCountDriver wordcount -Dmapreduce.job.queuename=root.test /input /output1
注意事项: 完成上述操作后,建议恢复到之前的配置状态,因为当前的资源分配可能会影响后续的测试。