1、容量调度器案例
1.1 多队列概念
默认情况
只有一个default队列
多队列好处
1. 防止员工写递归死循环代码,把公司的资源全部耗尽
2. 可以给任务设置优先级
多队列命名依据
按照部门、业务模块划分,如:管会、资本(主流)
按照任务运行框架划分,如:hive/spark/flink/mr(用得不是特别多,常用于中小型公司,或者任务量不多的公司)
1.2 容量调度器案例——多队列
1.2.1 需求分析
配置两个队列,default 和 hive
- default队列占总内存的40%,最大资源容量占总资源60%(指可以和别人多借20%资源)
- hive队列占总内存的60%,最大资源容量占总资源80%
1.2.2 配置 capacity-scheduler.xml
a、修改如下配置
队列都是从root开始的,root下默认只有一个default队列,需要增加一个hive队列,同时修改两个队列内存占用比值和最大资源容量占用率
- 将 default 改成 default,hive
<property>
<name>yarn.scheduler.capacity.root.queues</name>
<value>default,hive</value>
<description>
The queues at the this level (root is the root queue).
</description>
</property>
- 降低default队列资源额定容量为40%,默认100%
<property>
<name>yarn.scheduler.capacity.root.default.capacity</name>
<value>40</value>
</property>
- 降低default队列资源最大容量为60%,默认100%
<property>
<name>yarn.scheduler.capacity.root.default.maximum-capacity</name>
<value>60</value>
</property>
b、添加如下hive队列必要配置
- 指定hive队列的资源额定容量
100 - 40(default占用) = 60
<property>
<name>yarn.scheduler.capacity.root.hive.capacity</name>
<value>60</value>
</property>
- 队列下的单个用户,提交任务时,最多可以使用多少队列资源
1表示可以100%使用队列所有资源
如果担心同队列的同事,写了递归死循环代码,可以改成 0.5 - 0.8
<property>
<name>yarn.scheduler.capacity.root.hive.user-limit-factor</name>
<value>1</value>
</property>
- 指定hive队列的资源最大容量
<property>
<name>yarn.scheduler.capacity.root.hive.maximum-capacity</name>
<value>80</value>
</property>
- 启动hive队列
<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>
- 任务最大的生命周期
像Yarn提交任务时,可以设置任务超时时间
当任务指定了超时时间,则提交到该队列的任务能够指定的最大超时时间不能超过该值
-1指没有时间上限
yarn application -appId appId -updateLifetime Timeout
<property>
<name>yarn.scheduler.capacity.root.hive.maximum-application-lifetime</name>
<value>-1</value>
</property>
- 默认任务超时时间
如果任务没指定超时时间,则用 default-application-lifetime 作为默认值
-1指没有时间上限
<property>
<name>yarn.scheduler.capacity.root.hive.default-application-lifetime</name>
<value>-1</value>
</property>
1.2.3 配置步骤
- 进入 capacity-scheduler.xml 存储路径
cd /opt/module/hadoop-3.1.3/etc/hadoop
- 修改或者新增capacity-scheduler.xml配置
- 分发配置
- 集群无需重新启动,直接刷新队列,执行yarn rmadmin -refreshQueues
可以看到上面配置已被修改
修改前:
修改后:
注意:yarn rmadmin -refreshQueues 只能更新队列相关的参数,该参数位于 capacity-scheduler.xml 中。如果是修改 yarn-site.xml 里的相关Yarn参数,只能重新启动集群,才会更新配置
- 向hive队列提交任务, -D表示运行时改变参数值
[atguigu@hadoop102 hadoop-3.1.3]$ hadoop jar share/hadoop/mapreduce/hadoop-mapreduce-examples-3.1.3.jar wordcount -D mapreduce.job.queuename=hive /input /output
1.3 配置队列案例——优先级
1.3.1 需求分析
背景
容量调度器的单队列默认是先进先出,按照时间的先后顺序执行,可以给其设置优先级,自主调整任务执行顺序
需求
给提交的任务配置优先级
1.3.2 配置步骤
配置优先级
- 默认情况下,全部任务的优先级都是0
<property>
<description>
Defines maximum application priority in a cluster.
If an application is submitted with a priority higher than this value, it will be
reset to this maximum value.
</description>
<name>yarn.cluster.max-application-priority</name>
<value>0</value>
</property>
- 如果需要启动优先级,需要将 yarn.cluster.max-application-priority 调高,如:设置成5
- 分发配置,重启Yarn(刷新队列配置不会生效)
- 先使用求 Π 命令,模拟集群资源紧张情况
hadoop jar /opt/module/hadoop-3.1.3/share/hadoop/mapreduce/hadoop-mapreduce-examples-3.1.3.jar pi 5 2000000
- 再提交一个优先级为5的任务,可以看到后提交但优先级较高的任务,会先执行。在资源紧张时,优先级高的任务将优先获取资源
[atguigu@hadoop102 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
2、公平调度器案例
2.1 队列
默认情况
只有一个default队列
2.2 公平调度器案例——多队列
2.2.1 需求分析
- 配置三个队列,default 、test 和 atguigu
- test用户任务提交到test队列中,atguigu用户提交atguigu队列中
2.2.2 配置文件
公平调度器的配置涉及到两个文件,一个是yarn-site.xml,另一个是公平调度器队列分配文件fair-scheduler.xml(文件名可自定义)
2.2.3 配置步骤
参考资料
链接1: Hadoop官网配置公平调度器步骤
链接2: CDH官网任务队列放置规则
CDH是收费的,文档比较好,不仅会教我们怎么配置,还会教我们怎么配置更好
提炼参考资料,整理出配置步骤
配置文件
a、修改yarn-site.xml文件
- 配置使用公平调度器
<property>
<name>yarn.resourcemanager.scheduler.class</name>
<value>org.apache.hadoop.yarn.server.resourcemanager.scheduler.fair.FairScheduler</value>
</property>
b、在yarn-site.xml文件加入以下参数
- 指明公平调度器队列分配配置文件
<property>
<name>yarn.scheduler.fair.allocation.file</name>
<value>/opt/module/hadoop-3.1.3/etc/hadoop/fair-scheduler.xml</value>
</property>
- 禁止队列间互相借资源
<property>
<name>yarn.scheduler.fair.preemption</name>
<value>false</value>
</property>
c、 配置 fair-scheduler.xml ,公平调度器具体配置
-
queueMaxAMShareDefault : 启动单个队列中Application Master所用的资源比例,此服务器为 4G * 0.5 = 2G,如果设置成 0.1,启动任务有点吃力。公司中一般设置成 0.1 ,使用 128G * 0.1 = 12.8G
-
queueMaxResourcesDefault : 单个队列使用的最大资源
计算步骤
a、服务器资源:4G内存,4核CPU * 3台 = 12G内存 ,12核CPU
b、除三台队列:12G内存 ,12核CPU / 3(3个队列) = 4G内存,4核CPU -
queue 相关参数:名称、最小资源、最大资源、单个队列最多同时跑任务数(根据单节点4核4G来推测,给4)、启动单个队列中Application Master所用的资源比例、默认权重(都是1.0,即不设置权重)、队列资源分配规则(fair)
-
任务队列分配策略:
a. 不允许自动创建,当提交任务时,未找到与该用户名称一致的队列时,则自动创建队列
例如:当前有 default 、test 和 atguigu 三个队列,当ss用户提交时,默认情况下会创建一个ss队列,选择false,禁止该功能
b. 设置优先提交到同用户名的队列下
c. 如果不是 test 或者 atguigu 用户提交的任务,可以选择拒绝或者提交到 default 队列中
<?xml version="1.0"?>
<allocations>
<!-- 单个队列中Application Master占用资源的最大比例,取值0-1 ,企业一般配置0.1 -->
<queueMaxAMShareDefault>0.5</queueMaxAMShareDefault>
<!-- 单个队列最大资源的默认值 test atguigu default -->
<queueMaxResourcesDefault>4096mb,4vcores</queueMaxResourcesDefault>
<!-- 增加一个队列test -->
<queue name="test">
<!-- 队列最小资源 -->
<minResources>2048mb,2vcores</minResources>
<!-- 队列最大资源 -->
<maxResources>4096mb,4vcores</maxResources>
<!-- 队列中最多同时运行的应用数,默认50,根据线程数配置 -->
<maxRunningApps>4</maxRunningApps>
<!-- 队列中Application Master占用资源的最大比例 -->
<maxAMShare>0.5</maxAMShare>
<!-- 该队列资源权重,默认值为1.0 -->
<weight>1.0</weight>
<!-- 队列内部的资源分配策略 -->
<schedulingPolicy>fair</schedulingPolicy>
</queue>
<!-- 增加一个队列atguigu -->
<queue name="atguigu" type="parent">
<!-- 队列最小资源 -->
<minResources>2048mb,2vcores</minResources>
<!-- 队列最大资源 -->
<maxResources>4096mb,4vcores</maxResources>
<!-- 队列中最多同时运行的应用数,默认50,根据线程数配置 -->
<maxRunningApps>4</maxRunningApps>
<!-- 队列中Application Master占用资源的最大比例 -->
<maxAMShare>0.5</maxAMShare>
<!-- 该队列资源权重,默认值为1.0 -->
<weight>1.0</weight>
<!-- 队列内部的资源分配策略 -->
<schedulingPolicy>fair</schedulingPolicy>
</queue>
<!-- 任务队列分配策略,可配置多层规则,从第一个规则开始匹配,直到匹配成功 -->
<queuePlacementPolicy>
<!-- 提交任务时指定队列,如未指定提交队列,则继续匹配下一个规则; false表示:如果指定队列不存在,不允许自动创建-->
<rule name="specified" create="false"/>
<!-- 提交到root.group.username队列,若root.group不存在,不允许自动创建;若root.group.user不存在,允许自动创建 -->
<rule name="nestedUserQueue" create="true">
<rule name="primaryGroup" create="false"/>
</rule>
<!-- 最后一个规则必须为reject或者default。Reject表示拒绝创建提交失败,default表示把任务提交到default队列 -->
<rule name="reject" />
</queuePlacementPolicy>
</allocations>
d、分发配置
[atguigu@hadoop102 hadoop]$ xsync yarn-site.xml fair-scheduler.xml
e、重新启动 Yarn
[atguigu@hadoop103 hadoop-3.1.3]$ sbin/stop-yarn.sh
[atguigu@hadoop103 hadoop-3.1.3]$ sbin/start-yarn.sh
f、可以看到三条队列(default 、test 和 atguigu),均分整个集群资源
2.2.4 测试提交任务
测试1. 使用atguigu账号,向 test 队列提交任务,则任务提交到了 test 队列中
[atguigu@hadoop102 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
测试2. 使用atguigu账号,不指定队列提交任务,则任务提交到了 atguigu 队列中
[atguigu@hadoop102 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
3、Yarn Tool 接口案例
3.1 需求
向Hadoop集群提交Jar包时,可以指定提交的队列参数
3.2 分析
3.2.1 之前自定义的wc.jar提交命令
[atguigu@hadoop102 hadoop-3.1.3]$ hadoop jar wc.jar com.atguigu.mapreduce.workcount2.WordCountDriver /input /output7
可以正常运行
3.2.2 官网WordCount提交命令
hadoop jar share/hadoop/mapreduce/hadoop-mapreduce-examples-3.1.3.jar wordcount /input /output7
- Jar包后面的三个参数除了输入、输出路径之外,还有一个wordcount
- wordcount用于生成特定的Tool,万一需要指定队列,则可以在wordcount 后面加上 -Dmapreduce.job.queuename=root.test,命令如下,这时会有四个参数
[atguigu@hadoop102 hadoop-3.1.3]$ hadoop jar share/hadoop/mapreduce/hadoop-mapreduce-examples-3.1.3.jar wordcount -Dmapreduce.job.queuename=root.test /input /output8
3.2.3 之前自定义的wc.jar加上队列参数
[atguigu@hadoop102 hadoop-3.1.3]$ hadoop jar wc.jar com.atguigu.mapreduce.workcount2.WordCountDriver -Dmapreduce.job.queuename=root.test /input /output7
2022-10-30 15:11:47,463 INFO client.RMProxy: Connecting to ResourceManager at hadoop103/192.168.10.103:8032
Exception in thread "main" org.apache.hadoop.mapred.FileAlreadyExistsException: Output directory hdfs://hadoop102:8020/input already exists
at org.apache.hadoop.mapreduce.lib.output.FileOutputFormat.checkOutputSpecs(FileOutputFormat.java:164)
at org.apache.hadoop.mapreduce.JobSubmitter.checkSpecs(JobSubmitter.java:277)
at org.apache.hadoop.mapreduce.JobSubmitter.submitJobInternal(JobSubmitter.java:143)
at org.apache.hadoop.mapreduce.Job$11.run(Job.java:1570)
at org.apache.hadoop.mapreduce.Job$11.run(Job.java:1567)
at java.security.AccessController.doPrivileged(Native Method)
at javax.security.auth.Subject.doAs(Subject.java:422)
at org.apache.hadoop.security.UserGroupInformation.doAs(UserGroupInformation.java:1729)
at org.apache.hadoop.mapreduce.Job.submit(Job.java:1567)
at org.apache.hadoop.mapreduce.Job.waitForCompletion(Job.java:1588)
at com.atguigu.mapreduce.workcount2.WordCountDriver.main(WordCountDriver.java:41)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.apache.hadoop.util.RunJar.run(RunJar.java:318)
at org.apache.hadoop.util.RunJar.main(RunJar.java:232)
会报一个输入路径已经存在的错误,因为命令把/input当做第二个参数,为输出路径
3.2.4 解决方式
采用Tool接口
3.3 代码
3.3.1 pom.xml
<dependencies>
<dependency>
<groupId>org.apache.hadoop</groupId>
<artifactId>hadoop-client</artifactId>
<version>3.1.3</version>
</dependency>
</dependencies>
3.3.2 完成Mapper、Reducer和部分驱动代码
public class WordCount implements Tool {
// 在 get set 方法中给 conf 赋值
private Configuration conf;
// 核心驱动(conf 需要传入)
@Override
public int run(String[] args) throws Exception {
Job job = Job.getInstance(conf);
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(args[0]));
FileOutputFormat.setOutputPath(job,new Path(args[1]));
return job.waitForCompletion(true)?0:1;
}
@Override
public void setConf(Configuration conf) {
this.conf = conf;
}
@Override
public Configuration getConf() {
return conf;
}
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[] words = line.split(" ");
for (String word : words) {
outK.set(word);
context.write(outK, outV);
}
}
}
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);
}
}
}
Mapper和Reducer与之前的代码无异
3.3.3 驱动代码
public class WordCountDriver {
private static Tool tool;
public static void main(String[] args) throws Exception {
// 1. 创建配置
Configuration conf = new Configuration();
// 2. 判断是否有 tool 接口
switch (args[0]){
case "wordcount":
tool = new WordCount();
break;
default:
throw new RuntimeException(" No such tool:" + args[0]);
}
// 3. 用 Tool 执行程序
int run = ToolRunner.run(conf, tool, Arrays.copyOfRange(args, 1, args.length));
System.exit(run);
}
}
3.4 结果
- 不指定队列——成功运行
[atguigu@hadoop102 hadoop-3.1.3]$ hadoop jar YarnDemo.jar com.atguigu.yarn.WordCountDriver wordcount /input /output4
- 指定队列——成功运行
[atguigu@hadoop102 hadoop-3.1.3]$ hadoop jar YarnDemo.jar com.atguigu.yarn.WordCountDriver wordcount -Dmapreduce.job.queuename=root.test /input /output5
- 故意输错Tool接口名,把wordcount改成wordcount1
报该Tool接口不存在的错误
[atguigu@hadoop102 hadoop-3.1.3]$ hadoop jar YarnDemo.jar com.atguigu.yarn.WordCountDriver wordcount1 -Dmapreduce.job.queuename=root.test /input /output5
Exception in thread "main" java.lang.RuntimeException: No such tool:wordcount1