什么是YARN,有什么作用
YARN(分布式运算资源调度系统)
我们知道我们的分布式文件存储系统HDFS,是将文件进行切块(默认128M)、备份(3份)分布式的存储在集群的各个机器上的;
海量的数据需要运算 ,那如果我们写的java程序,只运行在一个机器上进行处理这些数据块的话,明显是不可取的,所以我们得让程序分布式 并行的在各个机器上(mapreduce)运算;
而这些程序运行具体使用哪一台的运算资源(CPU、内存、IO、网络等),使用多少,很显然,人为分配这些资源,是很难做到公平和合理的。
而资源的不合理、不公平分配将造成资源的浪费、机器的压力(资源差的机器却承担着超大量的数据处理任务,可能会导致内存溢出等问题)、
job任务执行过长(最终的执行时间需要等待那个处理最慢的)而影响整个流程效率
而YARN恰恰可以很好的解决资源分配问题,将job任务提交到YARN上进行,YARN根据一定的调度策略,将它所管理的集群中的运算资源分配给这些job任务使用(集群上不单单存在着mapreduce
的job任务,还可能存在着Spark、flink、storm、hive等等),同时采取隔离措施,使得各种服务之间不会因为争夺资源而发生相互干扰的现象,这样每个服务,每个应用就能发挥出自己最大的作用,
同时YARN还能进行任务的监控,任务的运行、运行的结果都能实时监控,总而言之,YARN能够接收Job任务、进行集群运算资源的调度、集群运算资源的管理、任务的监控等。
你怎么理解的
我觉得YARN的概念有点像HDFS ,也是一个整体,有一个Resourcemanager(主)节点和多个Nodemanager(次)节点。YARN就像一个管家,管理着它集群上面所有的机器的运算资源(CPU、内存、IO、网络等),有新的机器加入,将向YARN主节点报备自己的运算资源。当有job任务被提交给了YARN后,YARN 根据一定的调度资源,分配相应的运算资源给他们进行使用,同时监控着这些job的运行。
YARN的安装和配置
添加配置
vi /opt/apps/hadoop-3.1.1/etc/hadoop/yarn-site.xml 配置如下信息
<configuration> <!-- resource,manager主节点所在机器 --> <property> <name>yarn.resourcemanager.hostname</name> <value>doit001</value> </property> <!-- 为mr程序提供shuffle服务 --> <property> <name>yarn.nodemanager.aux-services</name> <value>mapreduce_shuffle</value> </property> <!-- 一台NodeManager的总可用内存资源 --> <property> <name>yarn.nodemanager.resource.memory-mb</name> <value>2048</value> </property> <!-- 一台NodeManager的总可用(逻辑)cpu核数 --> <property> <name>yarn.nodemanager.resource.cpu-vcores</name> <value>2</value> </property> <!-- 是否检查容器的虚拟内存使用超标情况 --> <property> <name>yarn.nodemanager.vmem-check-enabled</name> <value>false</value> </property> <!-- 容器的虚拟内存使用上限:与物理内存的比率 --> <property> <name>yarn.nodemanager.vmem-pmem-ratio</name> <value>2.1</value> </property> </configuration>
启动yarn并查看进程
start-yarn.sh 注:需要在sbin目录下执行
这样子。另外两台机器应该也启动了,因为我们之前在workers中配置了主机名,一键启停应该是可以的,查看另外两台进程状态
在页面上查看YARN运行情况
在Linux上将Job提交给YARN执行
任务及运行类:
package cn.doit19.hadoop.review.join;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.io.LongWritable;
import org.apache.hadoop.io.NullWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Job;
import org.apache.hadoop.mapreduce.Mapper;
import org.apache.hadoop.mapreduce.lib.input.FileInputFormat;
import org.apache.hadoop.mapreduce.lib.output.FileOutputFormat;
import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.net.URI;
import java.util.*;
/**
* @author:tom
* @Date:Created in 21:43 2020/11/17
*/
@SuppressWarnings("all")
public class JoinApp {
static class JoinMap extends Mapper<LongWritable, Text, Text, NullWritable> {
String fileName = null;
Text k = new Text();
Map<String, String> map = null;
@Override
protected void setup(Context context) throws IOException, InterruptedException {
map = new HashMap<>();
BufferedReader br = new BufferedReader(new FileReader("user.txt"));
String line = null;
while ((line = br.readLine()) != null) {
String[] split = line.split(",");
map.put(split[0], split[1] + "," + split[2] + "," + split[3] + "," + split[4]);
}
}
@Override
protected void map(LongWritable key, Text value, Context context) throws IOException, InterruptedException {
String line = value.toString();
//处理order.txt
String[] split = line.split(",");
String user = map.getOrDefault(split[1], "null,null,null,null");
String s = split[0] + "," + user;
k.set(s);
context.write(k, NullWritable.get());
}
}
public static void main(String[] args) throws Exception {
//初始化配置对象
Configuration conf = new Configuration();
// 设置程序默认启动方式 yarn 默认为本地
conf.set("mapreduce.framework.name", "yarn");
// yarn的resourcemanager的位置
conf.set("yarn.resourcemanager.hostname", "linux01");
//创建job对象
Job job = Job.getInstance(conf,"joincase");
// 将 HDFS 上的 user.txt 分布式缓存到执行maptask任务的机器上
job.addCacheFile(new URI("/data/user.txt"));
// 设置访问的集群的位置
// conf.set("fs.defaultFS", "hdfs://doit01:9000");
// 设置MapReduce程序运行在windows上的跨平台参数
// conf.set("mapreduce.app-submission.cross-platform","true");
//设置map task 类
job.setMapperClass(JoinMap.class);
//设置reduce 最终输出类型 kv
job.setOutputKeyClass(Text.class);
job.setOutputValueClass(NullWritable.class);
//设置jar包 通过类名找到位置
job.setJarByClass(JoinApp.class);
//设置输入路径
FileInputFormat.setInputPaths(job, new Path("/mr/in"));
//设置输出路径
FileOutputFormat.setOutputPath(job, new Path("/mr/out"));
//提交任务
boolean s = job.waitForCompletion(true);
}
}
代码解析:
1)设置user.txt 分布式缓存进行处理
这里,我去除了reduce端,将文件不大的user.txt 分布式缓存到了执行maptask的各个机器上,这样可以提高效率,最重要的是避免了数据倾斜(这个后面会说),之前是采用的user.txt和order.txt
都在map里面进行处理;
2)setup中处理user.txt
因为将user.txt 分布式缓存到了(如何缓存,见下图,加一句代码),意思是将HDFS上根目录下/data/的user.txt 给分布式缓存到执行map任务的各个机器上
这样,每个maptask在循环执行任务,所处理的都是同样的user.txt 所以只需要在循环之前进行处理user.txt即可,即重写setup方法,在setup里面进行逻辑处理
3)main方法中设置参数
设置程序默认启动方式为yarn 我们要用yarn来分布式启动我们的java程序
告诉mapreduce yarn的resourcemanager的位置
设置jar包的类型 这样yarn就可以通过类型找到 这个类,并执行jar包程序
打包jar包并上传到集群上
在maven中先clean一下,再package打包一下
接着会在左边出现target的文件夹,里面有一个jar包
弄出来重命名join.jar,并上传到集群上
执行命令,提交java程序给YARN运行
去输出路径cat 内容
再去页面查看相关YARN运行程序情况
注意点:如果错误,需要你去补充配置文件,请进行补充:
更多学习、面试资料尽在微信公众号:Hadoop大数据开发