MapReduce源码分析之新API作业提交(二):连接集群
MapReduce作业提交时连接集群是通过Job的connect()方法实现的,它实际上是构造集群Cluster实例cluster,代码如下:
- private synchronized void connect()
- throws IOException, InterruptedException, ClassNotFoundException {
- // 如果cluster为null,构造Cluster实例cluster,
- // Cluster为连接MapReduce集群的一种工具,提供了一种获取MapReduce集群信息的方法
- if (cluster == null) {
- cluster =
- ugi.doAs(new PrivilegedExceptionAction<Cluster>() {
- public Cluster run()
- throws IOException, InterruptedException,
- ClassNotFoundException {
- return new Cluster(getConfiguration());
- }
- });
- }
- }
这个方法用synchronized关键字标识,处理逻辑为:如果cluster为null,构造Cluster实例cluster。
Cluster为连接MapReduce集群的一种工具,提供了一种获取MapReduce集群信息的方法,我们看下它的成员变量,如下所示:
- // 客户端通信协议提供者
- private ClientProtocolProvider clientProtocolProvider;
- // 客户端通信协议实例
- private ClientProtocol client;
- // 用户信息
- private UserGroupInformation ugi;
- // 配置信息
- private Configuration conf;
- // 文件系统实例
- private FileSystem fs = null;
- // 系统路径
- private Path sysDir = null;
- // 阶段区域路径
- private Path stagingAreaDir = null;
- // 作业历史路径
- private Path jobHistoryDir = null;
- // 日志
- private static final Log LOG = LogFactory.getLog(Cluster.class);
- // 客户端通信协议提供者加载器
- private static ServiceLoader<ClientProtocolProvider> frameworkLoader =
- ServiceLoader.load(ClientProtocolProvider.class);
Cluster最重要的两个成员变量是客户端通信协议提供者ClientProtocolProvider实例clientProtocolProvider,客户端通信协议ClientProtocol实例client,而后者是依托前者的create()方法生成的。
Cluster提供了两个构造函数,如下:
- public Cluster(Configuration conf) throws IOException {
- this(null, conf);
- }
- public Cluster(InetSocketAddress jobTrackAddr, Configuration conf)
- throws IOException {
- <span style="white-space:pre"> </span>// 设置配置信息
- this.conf = conf;
- // 获取当前用户
- this.ugi = UserGroupInformation.getCurrentUser();
- // 调用initialize()方法完成初始化
- initialize(jobTrackAddr, conf);
- }
最终会调用initialize()方法完成初始化,代码如下:
- // 确定客户端ClientProtocol实例client
- private void initialize(InetSocketAddress jobTrackAddr, Configuration conf)
- throws IOException {
- synchronized (frameworkLoader) {
- // 取出每个ClientProtocolProvider实例provider,通过其create()方法,
- // 构造ClientProtocol实例clientProtocol,
- // 并将两者赋值给对类应成员变量,退出循环
- for (ClientProtocolProvider provider : frameworkLoader) {
- LOG.debug("Trying ClientProtocolProvider : "
- + provider.getClass().getName());
- ClientProtocol clientProtocol = null;
- try {
- // 通过ClientProtocolProvider的create()方法,获取客户端与集群通讯ClientProtocol实例clientProtocol
- if (jobTrackAddr == null) {
- clientProtocol = provider.create(conf);
- } else {
- clientProtocol = provider.create(jobTrackAddr, conf);
- }
- // 设置类成员变量clientProtocolProvider、client,并退出循环
- if (clientProtocol != null) {
- clientProtocolProvider = provider;
- client = clientProtocol;
- // 记录debug级别日志信息
- LOG.debug("Picked " + provider.getClass().getName()
- + " as the ClientProtocolProvider");
- break;
- }
- else {
- // 记录debug级别日志信息
- LOG.debug("Cannot pick " + provider.getClass().getName()
- + " as the ClientProtocolProvider - returned null protocol");
- }
- }
- catch (Exception e) {
- LOG.info("Failed to use " + provider.getClass().getName()
- + " due to error: " + e.getMessage());
- }
- }
- }
- // 如果clientProtocolProvider、client任一为空,直接抛出IO异常
- if (null == clientProtocolProvider || null == client) {
- throw new IOException(
- "Cannot initialize Cluster. Please check your configuration for "
- + MRConfig.FRAMEWORK_NAME
- + " and the correspond server addresses.");
- }
- }
initialize()方法唯一的一个任务就是确定客户端通信协议提供者clientProtocolProvider,并通过其create()方法构造客户端通信协议ClientProtocol实例client。
MapReduce中,ClientProtocolProvider抽象类的实现共有YarnClientProtocolProvider、LocalClientProtocolProvider两种,前者为Yarn模式,而后者为Local模式。
我们先看下Yarn模式,看下YarnClientProtocolProvider的create()方法,代码如下:
- @Override
- public ClientProtocol create(Configuration conf) throws IOException {
- // 如果参数mapreduce.framework.name配置的为yarn,构造一个YARNRunner实例并返回,否则返回null
- if (MRConfig.YARN_FRAMEWORK_NAME.equals(conf.get(MRConfig.FRAMEWORK_NAME))) {
- return new YARNRunner(conf);
- }
- return null;
- }
Yarn模式下,如果参数mapreduce.framework.name配置的为yarn,构造一个YARNRunner实例并返回,否则返回null,关于YARNRunner,我们待会再讲,我们接着再看下Local模式,LocalClientProtocolProvider的create()方法,代码如下:
- @Override
- public ClientProtocol create(Configuration conf) throws IOException {
- // 初始化framework:取参数mapreduce.framework.name,参数未配置默认为local
- String framework =
- conf.get(MRConfig.FRAMEWORK_NAME, MRConfig.LOCAL_FRAMEWORK_NAME);
- // 如果framework是local,,则返回LocalJobRunner实例,并设置map任务数量为1,否则返回null
- if (!MRConfig.LOCAL_FRAMEWORK_NAME.equals(framework)) {
- return null;
- }
- conf.setInt(JobContext.NUM_MAPS, 1);
- return new LocalJobRunner(conf);
- }
Local模式也是需要看参数mapreduce.framework.name的配置是否为local,是的话,返回LocalJobRunner实例,并设置map任务数量为1,否则返回null,值得一提的是,这里参数mapreduce.framework.name未配置的话,默认为local,也就是说,MapReduce需要看参数mapreduce.framework.name确定连接模式,但默认是Local模式的。
到了这里,我们就能够知道一个很重要的信息,Cluster中客户端通信协议ClientProtocol实例,要么是Yarn模式下的YARNRunner,要么就是Local模式下的LocalJobRunner,记住这点,对透彻了解MapReduce作业提交的整体流程非常重要。
好了,我们继续以Yarn模式来分析MapReduce集群连接,看下YARNRunner的实现,先看下它的成员变量,如下:
- // 记录工厂RecordFactory实例
- private final RecordFactory recordFactory = RecordFactoryProvider.getRecordFactory(null);
- // ResourceManager代理ResourceMgrDelegate实例
- private ResourceMgrDelegate resMgrDelegate;
- // 客户端缓存ClientCache实例
- private ClientCache clientCache;
- // 配置信息Configuration实例
- private Configuration conf;
- // 文件上下文FileContext实例
- private final FileContext defaultFileContext;
其中,最重要的一个变量就是ResourceManager代理ResourceMgrDelegate实例resMgrDelegate,Yarn模式下整个MapReduce客户端就是由它负责与Yarn集群进行通信,完成诸如作业提交、作业状态查询等过程,通过它获取集群的信息,其内部有一个YarnClient实例YarnClient,负责与Yarn进行通信,还有ApplicationId、ApplicationSubmissionContext等与特定应用程序相关的成员变量。关于ResourceMgrDelegate的详细介绍,请阅读《MapReduce源码分析ResourceMgrDelegate》一文,这里不再做详细介绍。
另外一个比较重要的变量就是客户端缓存ClientCache实例clientCache,
接下来,我们看下YARNRunner的构造函数,如下:
- /**
- * Yarn runner incapsulates the client interface of
- * yarn
- * @param conf the configuration object for the client
- */
- public YARNRunner(Configuration conf) {
- // 先构造ResourceManager代理ResourceMgrDelegate实例,然后再调用两个参数的构造函数
- this(conf, new ResourceMgrDelegate(new YarnConfiguration(conf)));
- }
- /**
- * Similar to {@link #YARNRunner(Configuration)} but allowing injecting
- * {@link ResourceMgrDelegate}. Enables mocking and testing.
- * @param conf the configuration object for the client
- * @param resMgrDelegate the resourcemanager client handle.
- */
- public YARNRunner(Configuration conf, ResourceMgrDelegate resMgrDelegate) {
- // 先构造客户端缓存ClientCache实例,然后再调用三个参数的构造函数
- this(conf, resMgrDelegate, new ClientCache(conf, resMgrDelegate));
- }
- /**
- * Similar to {@link YARNRunner#YARNRunner(Configuration, ResourceMgrDelegate)}
- * but allowing injecting {@link ClientCache}. Enable mocking and testing.
- * @param conf the configuration object
- * @param resMgrDelegate the resource manager delegate
- * @param clientCache the client cache object.
- */
- public YARNRunner(Configuration conf, ResourceMgrDelegate resMgrDelegate,
- ClientCache clientCache) {
- // 成员变量赋值
- this.conf = conf;
- try {
- this.resMgrDelegate = resMgrDelegate;
- this.clientCache = clientCache;
- // 获取文件山下文FileContext实例defaultFileContext
- this.defaultFileContext = FileContext.getFileContext(this.conf);
- } catch (UnsupportedFileSystemException ufe) {
- throw new RuntimeException("Error in instantiating YarnClient", ufe);
- }
- }
YARNRunner一共提供了三个构造函数,而我们之前说的WordCount作业提交时,其内部调用的是YARNRunner带有一个参数的构造函数,它会先构造ResourceManager代理ResourceMgrDelegate实例,然后再调用两个参数的构造函数,继而构造客户端缓存ClientCache实例,然后再调用三个参数的构造函数,而最终的构造函数只是进行简单的类成员变量赋值,然后通过FileContext的静态getFileContext()方法获取文件山下文FileContext实例defaultFileContext。
总结
MapReduce作业提交时连接集群是通过Job的connect()方法实现的,它实际上是构造集群Cluster实例cluster。Cluster为连接MapReduce集群的一种工具,提供了一种获取MapReduce集群信息的方法。在Cluster内部,有一个与集群进行通信的客户端通信协议ClientProtocol实例client,它由ClientProtocolProvider的静态create()方法构造,而Hadoop2.6.0中提供了两种模式的ClientProtocol,分别为Yarn模式的YARNRunner和Local模式的LocalJobRunner,Cluster实际上是由它们负责与集群进行通信的,而Yarn模式下,ClientProtocol实例YARNRunner对象内部有一个ResourceManager代理ResourceMgrDelegate实例resMgrDelegate,Yarn模式下整个MapReduce客户端就是由它负责与Yarn集群进行通信,完成诸如作业提交、作业状态查询等过程,通过它获取集群的信息。
MapReduce源码分析之新API作业提交(二):连接集群的更多相关文章
- MapReduce源码分析之JobSubmitter(一)
JobSubmitter,顾名思义,它是MapReduce中作业提交者,而实际上JobSubmitter除了构造方法外,对外提供的唯一一个非private成员变量或方法就是submitJobInter ...
- Yarn源码分析之如何确定作业运行方式Uber or Non-Uber?
在MRAppMaster中,当MapReduce作业初始化时,它会通过作业状态机JobImpl中InitTransition的transition()方法,进行MapReduce作业初始化相关操作,而 ...
- MapReduce源码分析之LocatedFileStatusFetcher
LocatedFileStatusFetcher是MapReduce中一个针对给定输入路径数组,使用配置的线程数目来获取数据块位置的实用类.它的主要作用就是利用多线程技术,每个线程对应一个任务,每个任 ...
- heapster源码分析——kubelet的api调用分析
一.heapster简介 什么是Heapster? Heapster是容器集群监控和性能分析工具,天然的支持Kubernetes和CoreOS.Kubernetes有个出名的监控agent---cAd ...
- Spark源码分析之六:Task调度(二)
话说在<Spark源码分析之五:Task调度(一)>一文中,我们对Task调度分析到了DriverEndpoint的makeOffers()方法.这个方法针对接收到的ReviveOffer ...
- 【spring源码分析】IOC容器初始化(二)
前言:在[spring源码分析]IOC容器初始化(一)文末中已经提出loadBeanDefinitions(DefaultListableBeanFactory)的重要性,本文将以此为切入点继续分析. ...
- springMVC源码分析--视图AbstractView和InternalResourceView(二)
上一篇博客springMVC源码分析--视图View(一)中我们介绍了简单介绍了View的结构实现及运行流程,接下来我们介绍一下View的实现类做的处理操作. AbstractView实现了rende ...
- Mybatis源码分析之SqlSession和Excutor(二)
通过上一篇文章的分析我们,我初步了解了它是如何创建sessionFactory的(地址:Mybatis源码分析之SqlSessionFactory(一)), 今天我们分析下Mybatis如何创建Sql ...
- springMVC源码分析--HttpMessageConverter参数read操作(二)
上一篇博客springMVC源码分析--HttpMessageConverter数据转化(一)中我们简单介绍了一下HttpMessageConverter接口提供的几个方法,主要有以下几个方法: (1 ...
随机推荐
- Sharepoint 查阅项字段和计算值字段的定义
查阅项字段定义 <Field Type="Lookup" DisplayName="test2" Required="FALSE" E ...
- 八. 输入输出(IO)操作3.面向字符的输出流
面向字符的输出流都是类 Writer 的子类,其类层次结构如图 10-5 所示. 图10-5 Writer的类层次结构图 表 10-3 列出了 Writer 的主要子类及说明. 表 10-3 Writ ...
- bin/...的访问被拒绝被拒绝的问题
复制到bin.... 对路径bin/.... 的访问被拒绝出现这们的问题,把源码管理器中项目的Bin目录删除,重新获取就要以了
- USING CHARLES FROM AN IPHONE
USING CHARLES FROM AN IPHONE 从系统偏好->高级来查看ip地址即可 To use Charles as your HTTP proxy on your iPhone ...
- mac如何挂载移动硬盘、存储设备、U盘
默认情况下Mac OSX对NTFS磁盘的挂载方式是只读(read-only)的,如何实现读写: 1.借助第三方软件:比如免费版的Mounty 2.因为OSX原生就是支持NTFS的,但是后来由于微软的限 ...
- IP分类:A,B,C,D,E五类
IP地址分为五类: IP地址分为五类:A类保留给政府机构,B类分配给中等规模的公司,C类分配给任何需要的人,D类用于组播,E类用于实验. 常用的三类IP地址 IP = 网路地址(网络号)+主机地址(主 ...
- 深入理解dataset及其用法
DataSet是ADO.NET的中心概念.可以把DataSet当成内存中的数据库,DataSet是不依赖于数据库的独立数据集合.所谓独立, 就是说,即使断开数据链路,或者关闭数据库,DataSet依然 ...
- 解决dubbo问题:forbid consumer(1)
原因: 1.dubbo服务没有起动起来 2.dubbo链接的地址出现异常 3.dubbo服务端更新了服务接口,没有发布 如果已上都没有问题,那么还有一个原因就是 “ 别人的代码有问题 阻碍了 你的程序 ...
- 遍历修改django bootstrap form 为 django bootstrap3
#!/usr/bin/env python # encoding: utf-8 import re import os fname = '' bt_pattern = re.compile(r'{% ...
- Android学习(十) SQLite 基于内置函数的操作方式
main.xml <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns ...