Yarn 是一个资源调度平台,负责为运算程序提供服务器运算资源,相当于一个分布式的操作系统平台
,而 MapReduce 等运算程序则相当于运行于操作系统之上的应用程序
。
YARN 主要由 ResourceManager、NodeManager、ApplicationMaster 和 Container 等组件 构成。
(2)YarnRunner 向 ResourceManager 申请一个 Application。
(3)RM 将该应用程序的资源路径返回给 YarnRunner。
(4)该程序将运行所需资源提交到 HDFS 上。
(5)程序资源提交完毕后,申请运行 mrAppMaster。
(6)RM 将用户的请求初始化成一个 Task。
(7)其中一个 NodeManager 领取到 Task 任务。
(8)该 NodeManager 创建容器 Container,并产生 MRAppmaster。
(9)Container 从 HDFS 上拷贝资源到本地。
(10)MRAppmaster 向 RM 申请运行 MapTask 资源。
(11)RM 将运行 MapTask 任务分配给另外两个 NodeManager,另两个 NodeManager 分 别领取任务并创建容器。
(12)MR 向两个接收到任务的 NodeManager 发送程序启动脚本,这两个 NodeManager 分别启动 MapTask,MapTask 对数据分区排序。
(13)MrAppMaster 等待所有 MapTask 运行完毕后,向 RM 申请容器,运行 ReduceTask。
(14)ReduceTask 向 MapTask 获取相应分区的数据。
(15)程序运行完毕后,MR 会向 RM 申请注销自己。
(1)作业提交
第 1 步:Client 调用 job.waitForCompletion 方法,向整个集群提交 MapReduce 作业。
第 2 步:Client 向 RM 申请一个作业 id。
第 3 步:RM 给 Client 返回该 job 资源的提交路径和作业 id。
第 4 步:Client 提交 jar 包、切片信息和配置文件到指定的资源提交路径。
第 5 步:Client 提交完资源后,向 RM 申请运行 MrAppMaster。
(2)作业初始化
第 6 步:当 RM 收到 Client 的请求后,将该 job 添加到容量调度器中。
第 7 步:某一个空闲的 NM 领取到该 Job。
第 8 步:该 NM 创建 Container,并产生 MRAppmaster。
第 9 步:下载 Client 提交的资源到本地。
(3)任务分配
第 10 步:MrAppMaster 向 RM 申请运行多个 MapTask 任务资源。
第 11 步:RM 将运行 MapTask 任务分配给另外两个 NodeManager,另两个 NodeManager 分别领取任务并创建容器。
(4)任务运行
第 12 步:MR 向两个接收到任务的 NodeManager 发送程序启动脚本,这两个 NodeManager 分别启动 MapTask,MapTask 对数据分区排序。
第13步:MrAppMaster等待所有MapTask运行完毕后,向RM申请容器,运行ReduceTask。
第 14 步:ReduceTask 向 MapTask 获取相应分区的数据。
第 15 步:程序运行完毕后,MR 会向 RM 申请注销自己。
(5)进度和状态更新 YARN 中的任务将其进度和状态(包括 counter)返回给应用管理器, 客户端每秒(通过 mapreduce.client.progressmonitor.pollinterval 设置)向应用管理器请求进度更新, 展示给用户。
(6)作业完成 除了向应用管理器请求作业进度外, 客户端每 5 秒都会通过调用 waitForCompletion()来 检查作业是否完成。时间间隔可以通过 mapreduce.client.completion.pollinterval 来设置。作业 完成之后, 应用管理器和 Container 会清理工作状态。作业的信息会被作业历史服务器存储 以备之后用户核查。
目前,Hadoop 作业调度器主要有三种:FIFO、容量(Capacity Scheduler)和公平(Fair Scheduler)。Apache Hadoop3.1.3 默认的资源调度器是 Capacity Scheduler。
具体设置详见:yarn-default.xml 文件
<property>
<description>The class to use as the resource scheduler.description>
<name>yarn.resourcemanager.scheduler.classname>
<value>org.apache.hadoop.yarn.server.resourcemanager.scheduler.capacity.CapacitySchedulervalue>
property>
FIFO 调度器(First In First Out):单队列,根据提交作业的先后顺序,先来先服务。
优点:简单易懂;
缺点:不支持多队列,生产环境很少使用;
Capacity Scheduler 是 Yahoo 开发的多用户调度器。
(1)容量调度器特点
1、多队列:每个队列可配置一定的资源量,每个队列采用FIFO调度策略。
2、容量保证:管理员可为每个队列设置资源最低保证和资源使用上限
3、灵活性:如果一个队列中的资源有剩余,可以暂时共享给那些需要资源的队列,而一旦该队列有新的应用 程序提交,则其他队列借调的资源会归还给该队列。
4、多租户: 支持多用户共享集群和多应用程序同时运行。 为了防止同一个用户的作业独占队列中的资源,该调度器会对同一用户提交的作业所占资源量进行限定。
Fair Schedulere 是 Facebook 开发的多用户调度器。
1)与容量调度器相同点
(1)多队列:支持多队列多作业
(2)容量保证:管理员可为每个队列设置资源最低保证和资源使用上线
(3)灵活性:如果一个队列中的资源有剩余,可以暂时共享给那些需要资源的队列,而一旦该队列有新的应用程序提 交,则其他队列借调的资源会归还给该队列。
(4)多租户:支持多用户共享集群和多应用程序同时运行;为了防止同一个用户的作业独占队列中的资源,该调度器 会对同一用户提交的作业所占资源量进行限定。
2)与容量调度器不同点
(1)核心调度策略不同
容量调度器:优先选择资源利用率低的队列
公平调度器:优先选择对资源的缺额比例大的
(2)每个队列可以单独设置资源分配方式
容量调度器:FIFO、 DRF
公平调度器:FIFO、FAIR、DRF
公平调度器队列资源分配方式
公平调度器资源分配算法
公平调度器队列资源分配方式
3)DRF策略
DRF(Dominant Resource Fairness),我们之前说的资源,都是单一标准,例如只考虑内存(也是Yarn默 认的情况)。但是很多时候我们资源有很多种,例如内存,CPU,网络带宽等,这样我们很难衡量两个应用 应该分配的资源比例。
那么在YARN中,我们用DRF来决定如何调度:
假设集群一共有100 CPU和10T 内存,而应用A需要(2 CPU, 300GB),应用B需要(6 CPU,100GB)。 则两个应用分别需要A(2%CPU, 3%内存)和B(6%CPU, 1%内存)的资源,这就意味着A是内存主导的, B是 CPU主导的,针对这种情况,我们可以选择DRF策略对不同应用进行不同资源(CPU和内存)的一个不同比 例的限制。
Yarn 状态的查询,除了可以在 hadoop103:8088 页面查看外,还可以通过命令操作。常 见的命令操作如下所示:
(1)列出所有 Application(运行状态才能查到):
yarn application -list
(2)根据 Application 状态过滤:
# ALL、NEW、NEW_SAVING、SUBMITTED、ACCEPTED、RUNNING、FINISHED、FAILED、KILLED
yarn application -list -appStates 状态 #如: FINISHED
(3)Kill 掉 Application:
yarn application -kill application_1624374869321_0004
(1)查询 Application 日志:yarn logs -applicationId < ApplicationId >
yarn logs -applicationId application_1624374869321_0004
(2)查询 Container 日志:yarn logs -applicationId < ApplicationId > -containerId < ContainerId >
yarn logs -applicationId application_1624374869321_0004 -containerId container_1624374869321_0004_01_000001
(1)列出所有 Application 尝试的列表:yarn applicationattempt -list < ApplicationId >
能查到 applicationattemptid 和 ContainerId
yarn applicationattempt -list application_1624374869321_0004
(2)打印 ApplicationAttemp 状态:yarn applicationattempt -status < ApplicationAttemptId >
yarn applicationattempt -status appattempt_1624374869321_0004_000001
ApplicationId 和 ApplicationAttemptId 是不一样的
(1)列出所有 Container:yarn container -list < ApplicationAttemptId >
yarn container -list appattempt_1624374869321_0004_000001
(2)打印 Container 状态:yarn container -status < ContainerId >
yarn container -status container_1624374869321_0004_01_000001
列出所有节点:yarn node -list -all
yarn node -list -all
加载队列配置:yarn rmadmin -refreshQueues
yarn rmadmin -refreshQueues
打印队列信息:yarn queue -status < QueueName >
yarn queue -status default
注:调整下列参数之前尽量拍摄 Linux 快照,否则后续的案例,还需要重写准备集群。
1)需求:从 1G 数据中,统计每个单词出现次数。服务器 3 台,每台配置 4G 内存,4 核 CPU,4 线程。
2)需求分析:
1G / 128m = 8 个 MapTask;1 个 ReduceTask;1 个 mrAppMaster
平均每个节点运行 10 个 / 3 台 ≈ 3 个任务(4 3 3)
3)修改 yarn-site.xml 配置参数如下:
<property>
<name>yarn.resourcemanager.scheduler.classname>
<value>org.apache.hadoop.yarn.server.resourcemanager.scheduler.capacity.CapacitySchedulervalue>
property>
<property>
<name>yarn.resourcemanager.scheduler.client.thread-countname>
<value>8value>
property>
<property>
<name>yarn.nodemanager.resource.detect-hardware-capabilitiesname>
<value>falsevalue>
property>
<property>
<name>yarn.nodemanager.resource.count-logical-processors-ascoresname>
<value>falsevalue>
property>
<property>
<name>yarn.nodemanager.resource.pcores-vcores-multipliername>
<value>1.0value>
property>
<property>
<name>yarn.nodemanager.resource.memory-mbname>
<value>4096value>
property>
<property>
<name>yarn.nodemanager.resource.cpu-vcoresname>
<value>4value>
property>
<property>
<name>yarn.scheduler.minimum-allocation-mbname>
<value>1024value>
property>
<property>
<name>yarn.scheduler.maximum-allocation-mbname>
<value>2048value>
property>
<property>
<name>yarn.scheduler.minimum-allocation-vcoresname>
<value>1value>
property>
<property>
<name>yarn.scheduler.maximum-allocation-vcoresname>
<value>2value>
property>
<property>
<name>yarn.nodemanager.vmem-check-enabledname>
<value>falsevalue>
property>
<property>
<name>yarn.nodemanager.vmem-pmem-rationame>
<value>2.1value>
property>
4)分发配置。
xsync yarn-site.xml
注意:如果集群的硬件资源不一致,要每个 NodeManager 单独配置
5)重启集群
6)执行 WordCount 程序
hadoop jar share/hadoop/mapreduce/hadoop-mapreduce-examples-3.1.3.jar wordcount /qingguo /output
1)在生产环境怎么创建队列?
(1)调度器默认就 1 个 default 队列,不能满足生产要求。
(2)按照框架:hive /spark/ flink 每个框架的任务放入指定的队列(企业用的不是特别 多)
(3)按照业务模块:登录注册、购物车、下单、业务部门 1、业务部门 2
2)创建多队列的好处?
(1)因为担心员工不小心,写递归死循环代码,把所有资源全部耗尽。
(2)实现任务的降级使用,特殊时期保证重要的任务队列资源充足。11.11 6.18
业务部门 1(重要)=》业务部门 2(比较重要)=》下单(一般)=》购物车(一般)=》 登录注册(次要)
需求 1:default 队列占总内存的 40%,最大资源容量占总资源 60%,hive 队列占总内存 的 60%,最大资源容量占总资源 80%。
需求 2:配置队列优先级
1)在 capacity-scheduler.xml 中配置如下:
(1)修改如下配置
<property>
<name>yarn.scheduler.capacity.root.queuesname>
<value>default,hivevalue>
property>
<property>
<name>yarn.scheduler.capacity.root.default.capacityname>
<value>40value>
property>
<property>
<name>yarn.scheduler.capacity.root.default.maximum-capacityname>
<value>60value>
property>
(2)为新加队列添加必要属性:
<property>
<name>yarn.scheduler.capacity.root.hive.capacityname>
<value>60value>
property>
<property>
<name>yarn.scheduler.capacity.root.hive.user-limit-factorname>
<value>1value>
property>
<property>
<name>yarn.scheduler.capacity.root.hive.maximum-capacityname>
<value>80value>
property>
<property>
<name>yarn.scheduler.capacity.root.hive.statename>
<value>RUNNINGvalue>
property>
<property>
<name>yarn.scheduler.capacity.root.hive.acl_submit_applicationsname>
<value>*value>
property>
<property>
<name>yarn.scheduler.capacity.root.hive.acl_administer_queuename>
<value>*value>
property>
<property>
<name>yarn.scheduler.capacity.root.hive.acl_application_max_priorityname>
<value>*value>
property>
<property>
<name>yarn.scheduler.capacity.root.hive.maximum-applicationlifetimename>
<value>-1value>
property>
<property>
<name>yarn.scheduler.capacity.root.hive.default-applicationlifetimename>
<value>-1value>
property>
2)分发配置文件
xsync capacity-scheduler.xml
3)重启 Yarn 或者执行 yarn rmadmin -refreshQueues( 刷新队列 ),就可以看到两条队列:
1)hadoop jar 的方式
hadoop jar share/hadoop/mapreduce/hadoop-mapreduce-examples-3.1.3.jar wordcount -Dmapreduce.job.queuename=hive /qingguo /output
注: -D 表示运行时改变参数值 . mapreduce 没有r
2)打 jar 包的方式
默认的任务提交都是提交到 default 队列的。如果希望向其他队列提交任务,需要在 Driver 中声明:
public class WcDrvier {
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 b = job.waitForCompletion(true);
System.exit(b ? 0 : 1);
}
}
这样,这个任务在集群提交时,就会提交到 hive 队列
容量调度器,支持任务优先级的配置,在资源紧张时,优先级高的任务将优先获取资源。 默认情况,Yarn 将所有任务的优先级限制为 0,若想使用任务的优先级功能,须开放该限制。
1)修改 yarn-site.xml 文件,增加以下参数
<property>
<name>yarn.cluster.max-application-priorityname>
<value>5value>
property>
2)分发配置,并重启 Yarn
xsync yarn-site.xml
sbin/stop-yarn.sh
sbin/start-yarn.sh
3)模拟资源紧张环境,可连续提交以下任务,直到新提交的任务申请不到资源为止。
hadoop jar share/hadoop/mapreduce/hadoop-mapreduce-examples-3.1.3.jar pi 5 2000000
4)再次重新提交优先级高的任务
hadoop jar share/hadoop/mapreduce/hadoop-mapreduce-examples-3.1.3.jar pi -Dmapreduce.job.priority=5 5 2000000
yarn application -appID < ApplicationID > -updatePriority 优先级
yarn application -appID application_1611133087930_0009 -updatePriority 5
创建两个队列,分别是 zhou 和 chen(以用户所属组命名)。期望实现以下效果:若用 户提交任务时指定队列,则任务提交到指定队列运行;若未指定队列,zhou 用户提交的任务 到 root.group.zhou 队列运行,chen 提交的任务到 root.group.chen 队列运行(注:group 为用户所属组)。
公平调度器的配置涉及到两个文件,一个是 yarn-site.xml,另一个是公平调度器队列分 配文件 fair-scheduler.xml(文件名可自定义)。
(1)配置文件参考资料:
(2)任务队列放置规则参考资料:
1)修改 yarn-site.xml 文件,加入以下参数
<property>
<name>yarn.resourcemanager.scheduler.classname>
<value>org.apache.hadoop.yarn.server.resourcemanager.scheduler.fair.FairSchedulervalue>
property>
<property>
<name>yarn.scheduler.fair.allocation.filename>
<value>/opt/hadoop-3.1.3/etc/hadoop/fair-scheduler.xmlvalue>
property>
<property>
<name>yarn.scheduler.fair.preemptionname>
<value>falsevalue>
property>
2)配置 fair-scheduler.xml
<allocations>
<queueMaxAMShareDefault>0.5queueMaxAMShareDefault>
<queueMaxResourcesDefault>4096mb,4vcoresqueueMaxResourcesDefault>
<queue name="zhou">
<minResources>2048mb,2vcoresminResources>
<maxResources>4096mb,4vcoresmaxResources>
<maxRunningApps>4maxRunningApps>
<maxAMShare>0.5maxAMShare>
<weight>1.0weight>
<schedulingPolicy>fairschedulingPolicy>
queue>
<queue name="chen" type="parent">
<minResources>2048mb,2vcoresminResources>
<maxResources>4096mb,4vcoresmaxResources>
<maxRunningApps>4maxRunningApps>
<maxAMShare>0.5maxAMShare>
<weight>1.0weight>
<schedulingPolicy>fairschedulingPolicy>
queue>
<queuePlacementPolicy>
<rule name="specified" create="false"/>
<rule name="nestedUserQueue" create="true">
<rule name="primaryGroup" create="false"/>
rule>
<rule name="reject" />
queuePlacementPolicy>
allocations>
3)分发配置并重启 Yarn
xsync yarn-site.xml fair-scheduler.xml
sbin/stop-yarn.sh
sbin/start-yarn.sh
1)提交任务时指定队列,按照配置规则,任务会到指定的 root.test 队列
hadoop jar share/hadoop/mapreduce/hadoop-mapreduce-examples-3.1.3.jar pi -Dmapreduce.job.queuename=root.zhou 1 1
hadoop jar share/hadoop/mapreduce/hadoop-mapreduce-examples-3.1.3.jar pi 1 1
0)回顾:
hadoop jar MapReduce-Test-1.0-SNAPSHOT.jar com.cssl.WorldCountDriver /qingguo /output
期望可以动态传参,结果报错,误认为是第一个输入参数。
hadoop jar MapReduce-Test-1.0-SNAPSHOT.jar com.cssl.WorldCountDriver -Dmapreduce.job.queuename=root.zhou /qingguo /output1
1)需求:自己写的程序也可以动态修改参数。编写 Yarn 的 Tool 接口。
(1)创建类 WordCount 并实现 Tool 接口:
public class WordCount implements Tool {
private Configuration configuration;
//核心驱动(conf 需要传入)
@Override
public int run(String[] strings) throws Exception {
Job job = Job.getInstance(configuration);
job.setJarByClass(WordCountDriver.class);
job.setMapperClass(WordCountMapper.class);
job.setReducerClass(WordCountReducer.class);
job.setMapOutputKeyClass(Text.class);
job.setMapOutputValueClass(IntWritable.class);
job.setOutputKeyClass(Text.class);
job.setOutputValueClass(IntWritable.class);
FileInputFormat.setInputPaths(job, new Path(strings[0]));
FileOutputFormat.setOutputPath(job, new Path(strings[1]));
return job.waitForCompletion(true)?0:1;
}
@Override
public void setConf(Configuration configuration) {
this.configuration=configuration;
}
@Override
public Configuration getConf() {
return configuration;
}
//mapper
public static class WordCountMapper extends Mapper<LongWritable, Text,Text, IntWritable>{
private Text outK=new Text();
private IntWritable outV=new IntWritable(1);
@Override
protected void map(LongWritable key, Text value, Context context) throws IOException, InterruptedException {
String line = value.toString();
String[] split = line.split(" ");
for (String s : split) {
outK.set(s);
context.write(outK, outV);
}
}
}
//reducer
public static class WordCountReducer extends Reducer<Text,IntWritable,Text,IntWritable>{
private IntWritable outV=new IntWritable();
@Override
protected void reduce(Text key, Iterable<IntWritable> values, Context context) throws IOException, InterruptedException {
int sum=0;
for (IntWritable value : values) {
sum+=value.get();
}
outV.set(sum);
context.write(key, outV);
}
}
}
(2)新建 WordCountDriver
public class WordCountDriver {
private static Tool tool;
public static void main(String[] args) throws Exception {
//创建配置
Configuration configuration = new Configuration();
switch (args[0]){
case "wordcount":
tool = new WordCount();
break;
default:
throw new RuntimeException("no such tool" + args[0]);
}
//执行程序
int run = ToolRunner.run(configuration, tool, Arrays.copyOfRange(args, 1, args.length));
System.exit(run);
}
}
3)在 HDFS 上准备输入文件,假设为/input 目录,向集群提交该 Jar 包
hadoop jar tool-test.jar com.cssl.tool.WordCountDriver wordcount /qingguo /output
注意此时提交的 3 个参数,第一个用于生成特定的 Tool,第二个和第三个为输入输出目 录。此时如果我们希望加入设置参数,可以在 wordcount 后面添加参数,例如:
hadoop jar tool-test.jar com.cssl.tool.WordCountDriver wordcount -Dmapreduce.job.queuename=root.zhou /qingguo /output
4)注:以上操作全部做完过后,快照回去或者手动将配置文件修改成之前的状态,因为本 身资源就不够,分成了这么多,不方便以后测试。
文章主要内容来自尚硅谷