MapReduce作业提交时连接集群是通过Job的connect()方法实现的,它实际上是构造集群Cluster实例cluster,代码如下:

  1. private synchronized void connect()
  2. throws IOException, InterruptedException, ClassNotFoundException {
  3. // 如果cluster为null,构造Cluster实例cluster,
  4. // Cluster为连接MapReduce集群的一种工具,提供了一种获取MapReduce集群信息的方法
  5. if (cluster == null) {
  6. cluster =
  7. ugi.doAs(new PrivilegedExceptionAction<Cluster>() {
  8. public Cluster run()
  9. throws IOException, InterruptedException,
  10. ClassNotFoundException {
  11. return new Cluster(getConfiguration());
  12. }
  13. });
  14. }
  15. }

这个方法用synchronized关键字标识,处理逻辑为:如果cluster为null,构造Cluster实例cluster。

Cluster为连接MapReduce集群的一种工具,提供了一种获取MapReduce集群信息的方法,我们看下它的成员变量,如下所示:

  1. // 客户端通信协议提供者
  2. private ClientProtocolProvider clientProtocolProvider;
  3. // 客户端通信协议实例
  4. private ClientProtocol client;
  5. // 用户信息
  6. private UserGroupInformation ugi;
  7. // 配置信息
  8. private Configuration conf;
  9. // 文件系统实例
  10. private FileSystem fs = null;
  11. // 系统路径
  12. private Path sysDir = null;
  13. // 阶段区域路径
  14. private Path stagingAreaDir = null;
  15. // 作业历史路径
  16. private Path jobHistoryDir = null;
  17. // 日志
  18. private static final Log LOG = LogFactory.getLog(Cluster.class);
  19. // 客户端通信协议提供者加载器
  20. private static ServiceLoader<ClientProtocolProvider> frameworkLoader =
  21. ServiceLoader.load(ClientProtocolProvider.class);

Cluster最重要的两个成员变量是客户端通信协议提供者ClientProtocolProvider实例clientProtocolProvider,客户端通信协议ClientProtocol实例client,而后者是依托前者的create()方法生成的。

Cluster提供了两个构造函数,如下:

  1. public Cluster(Configuration conf) throws IOException {
  2. this(null, conf);
  3. }
  4. public Cluster(InetSocketAddress jobTrackAddr, Configuration conf)
  5. throws IOException {
  6. <span style="white-space:pre">    </span>// 设置配置信息
  7. this.conf = conf;
  8. // 获取当前用户
  9. this.ugi = UserGroupInformation.getCurrentUser();
  10. // 调用initialize()方法完成初始化
  11. initialize(jobTrackAddr, conf);
  12. }

最终会调用initialize()方法完成初始化,代码如下:

  1. // 确定客户端ClientProtocol实例client
  2. private void initialize(InetSocketAddress jobTrackAddr, Configuration conf)
  3. throws IOException {
  4. synchronized (frameworkLoader) {
  5. // 取出每个ClientProtocolProvider实例provider,通过其create()方法,
  6. // 构造ClientProtocol实例clientProtocol,
  7. // 并将两者赋值给对类应成员变量,退出循环
  8. for (ClientProtocolProvider provider : frameworkLoader) {
  9. LOG.debug("Trying ClientProtocolProvider : "
  10. + provider.getClass().getName());
  11. ClientProtocol clientProtocol = null;
  12. try {
  13. // 通过ClientProtocolProvider的create()方法,获取客户端与集群通讯ClientProtocol实例clientProtocol
  14. if (jobTrackAddr == null) {
  15. clientProtocol = provider.create(conf);
  16. } else {
  17. clientProtocol = provider.create(jobTrackAddr, conf);
  18. }
  19. // 设置类成员变量clientProtocolProvider、client,并退出循环
  20. if (clientProtocol != null) {
  21. clientProtocolProvider = provider;
  22. client = clientProtocol;
  23. // 记录debug级别日志信息
  24. LOG.debug("Picked " + provider.getClass().getName()
  25. + " as the ClientProtocolProvider");
  26. break;
  27. }
  28. else {
  29. // 记录debug级别日志信息
  30. LOG.debug("Cannot pick " + provider.getClass().getName()
  31. + " as the ClientProtocolProvider - returned null protocol");
  32. }
  33. }
  34. catch (Exception e) {
  35. LOG.info("Failed to use " + provider.getClass().getName()
  36. + " due to error: " + e.getMessage());
  37. }
  38. }
  39. }
  40. // 如果clientProtocolProvider、client任一为空,直接抛出IO异常
  41. if (null == clientProtocolProvider || null == client) {
  42. throw new IOException(
  43. "Cannot initialize Cluster. Please check your configuration for "
  44. + MRConfig.FRAMEWORK_NAME
  45. + " and the correspond server addresses.");
  46. }
  47. }

initialize()方法唯一的一个任务就是确定客户端通信协议提供者clientProtocolProvider,并通过其create()方法构造客户端通信协议ClientProtocol实例client。

MapReduce中,ClientProtocolProvider抽象类的实现共有YarnClientProtocolProvider、LocalClientProtocolProvider两种,前者为Yarn模式,而后者为Local模式。

我们先看下Yarn模式,看下YarnClientProtocolProvider的create()方法,代码如下:

  1. @Override
  2. public ClientProtocol create(Configuration conf) throws IOException {
  3. // 如果参数mapreduce.framework.name配置的为yarn,构造一个YARNRunner实例并返回,否则返回null
  4. if (MRConfig.YARN_FRAMEWORK_NAME.equals(conf.get(MRConfig.FRAMEWORK_NAME))) {
  5. return new YARNRunner(conf);
  6. }
  7. return null;
  8. }

Yarn模式下,如果参数mapreduce.framework.name配置的为yarn,构造一个YARNRunner实例并返回,否则返回null,关于YARNRunner,我们待会再讲,我们接着再看下Local模式,LocalClientProtocolProvider的create()方法,代码如下:

  1. @Override
  2. public ClientProtocol create(Configuration conf) throws IOException {
  3. // 初始化framework:取参数mapreduce.framework.name,参数未配置默认为local
  4. String framework =
  5. conf.get(MRConfig.FRAMEWORK_NAME, MRConfig.LOCAL_FRAMEWORK_NAME);
  6. // 如果framework是local,,则返回LocalJobRunner实例,并设置map任务数量为1,否则返回null
  7. if (!MRConfig.LOCAL_FRAMEWORK_NAME.equals(framework)) {
  8. return null;
  9. }
  10. conf.setInt(JobContext.NUM_MAPS, 1);
  11. return new LocalJobRunner(conf);
  12. }

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的实现,先看下它的成员变量,如下:

  1. // 记录工厂RecordFactory实例
  2. private final RecordFactory recordFactory = RecordFactoryProvider.getRecordFactory(null);
  3. // ResourceManager代理ResourceMgrDelegate实例
  4. private ResourceMgrDelegate resMgrDelegate;
  5. // 客户端缓存ClientCache实例
  6. private ClientCache clientCache;
  7. // 配置信息Configuration实例
  8. private Configuration conf;
  9. // 文件上下文FileContext实例
  10. private final FileContext defaultFileContext;

其中,最重要的一个变量就是ResourceManager代理ResourceMgrDelegate实例resMgrDelegate,Yarn模式下整个MapReduce客户端就是由它负责与Yarn集群进行通信,完成诸如作业提交、作业状态查询等过程,通过它获取集群的信息,其内部有一个YarnClient实例YarnClient,负责与Yarn进行通信,还有ApplicationId、ApplicationSubmissionContext等与特定应用程序相关的成员变量。关于ResourceMgrDelegate的详细介绍,请阅读《MapReduce源码分析ResourceMgrDelegate》一文,这里不再做详细介绍。

另外一个比较重要的变量就是客户端缓存ClientCache实例clientCache,

接下来,我们看下YARNRunner的构造函数,如下:

  1. /**
  2. * Yarn runner incapsulates the client interface of
  3. * yarn
  4. * @param conf the configuration object for the client
  5. */
  6. public YARNRunner(Configuration conf) {
  7. // 先构造ResourceManager代理ResourceMgrDelegate实例,然后再调用两个参数的构造函数
  8. this(conf, new ResourceMgrDelegate(new YarnConfiguration(conf)));
  9. }
  10. /**
  11. * Similar to {@link #YARNRunner(Configuration)} but allowing injecting
  12. * {@link ResourceMgrDelegate}. Enables mocking and testing.
  13. * @param conf the configuration object for the client
  14. * @param resMgrDelegate the resourcemanager client handle.
  15. */
  16. public YARNRunner(Configuration conf, ResourceMgrDelegate resMgrDelegate) {
  17. // 先构造客户端缓存ClientCache实例,然后再调用三个参数的构造函数
  18. this(conf, resMgrDelegate, new ClientCache(conf, resMgrDelegate));
  19. }
  20. /**
  21. * Similar to {@link YARNRunner#YARNRunner(Configuration, ResourceMgrDelegate)}
  22. * but allowing injecting {@link ClientCache}. Enable mocking and testing.
  23. * @param conf the configuration object
  24. * @param resMgrDelegate the resource manager delegate
  25. * @param clientCache the client cache object.
  26. */
  27. public YARNRunner(Configuration conf, ResourceMgrDelegate resMgrDelegate,
  28. ClientCache clientCache) {
  29. // 成员变量赋值
  30. this.conf = conf;
  31. try {
  32. this.resMgrDelegate = resMgrDelegate;
  33. this.clientCache = clientCache;
  34. // 获取文件山下文FileContext实例defaultFileContext
  35. this.defaultFileContext = FileContext.getFileContext(this.conf);
  36. } catch (UnsupportedFileSystemException ufe) {
  37. throw new RuntimeException("Error in instantiating YarnClient", ufe);
  38. }
  39. }

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作业提交(二):连接集群的更多相关文章

  1. MapReduce源码分析之JobSubmitter(一)

    JobSubmitter,顾名思义,它是MapReduce中作业提交者,而实际上JobSubmitter除了构造方法外,对外提供的唯一一个非private成员变量或方法就是submitJobInter ...

  2. Yarn源码分析之如何确定作业运行方式Uber or Non-Uber?

    在MRAppMaster中,当MapReduce作业初始化时,它会通过作业状态机JobImpl中InitTransition的transition()方法,进行MapReduce作业初始化相关操作,而 ...

  3. MapReduce源码分析之LocatedFileStatusFetcher

    LocatedFileStatusFetcher是MapReduce中一个针对给定输入路径数组,使用配置的线程数目来获取数据块位置的实用类.它的主要作用就是利用多线程技术,每个线程对应一个任务,每个任 ...

  4. heapster源码分析——kubelet的api调用分析

    一.heapster简介 什么是Heapster? Heapster是容器集群监控和性能分析工具,天然的支持Kubernetes和CoreOS.Kubernetes有个出名的监控agent---cAd ...

  5. Spark源码分析之六:Task调度(二)

    话说在<Spark源码分析之五:Task调度(一)>一文中,我们对Task调度分析到了DriverEndpoint的makeOffers()方法.这个方法针对接收到的ReviveOffer ...

  6. 【spring源码分析】IOC容器初始化(二)

    前言:在[spring源码分析]IOC容器初始化(一)文末中已经提出loadBeanDefinitions(DefaultListableBeanFactory)的重要性,本文将以此为切入点继续分析. ...

  7. springMVC源码分析--视图AbstractView和InternalResourceView(二)

    上一篇博客springMVC源码分析--视图View(一)中我们介绍了简单介绍了View的结构实现及运行流程,接下来我们介绍一下View的实现类做的处理操作. AbstractView实现了rende ...

  8. Mybatis源码分析之SqlSession和Excutor(二)

    通过上一篇文章的分析我们,我初步了解了它是如何创建sessionFactory的(地址:Mybatis源码分析之SqlSessionFactory(一)), 今天我们分析下Mybatis如何创建Sql ...

  9. springMVC源码分析--HttpMessageConverter参数read操作(二)

    上一篇博客springMVC源码分析--HttpMessageConverter数据转化(一)中我们简单介绍了一下HttpMessageConverter接口提供的几个方法,主要有以下几个方法: (1 ...

随机推荐

  1. Tarjan缩点【p1726】上白泽慧音

    Description 在幻想乡,上白泽慧音是以知识渊博闻名的老师.春雪异变导致人间之里的很多道路都被大雪堵塞,使有的学生不能顺利地到达慧音所在的村庄.因此慧音决定换一个能够聚集最多人数的村庄作为新的 ...

  2. 洛谷—— P1022 计算器的改良

    P1022 计算器的改良 题目背景 NCL是一家专门从事计算器改良与升级的实验室,最近该实验室收到了某公司所委托的一个任务:需要在该公司某型号的计算器上加上解一元一次方程的功能.实验室将这个任务交给了 ...

  3. VisualStudio Shell简介 — 集成插件

    Visual Studio Shell只是提供了一个内核,我们还需要在其基础上补充功能,从而实现我们自己的IDE.Visual Studio Shell的插件开发和Visual Studio插件开发是 ...

  4. 资源相互引用时 需添加 PerformSubstitution=True

    获取或设置一个布尔值,该值确定在对由 WebResourceAttribute 类引用的嵌入式资源的处理过程中是否分析其他 Web 资源 URL,并用到该资源的完整路径替换. 如:一个CSS文件引用其 ...

  5. Android应用程序窗体设计框架介绍

    在Android系统中,一个Activity相应一个应用程序窗体.不论什么一个Activity的启动都是由AMS服务和应用程序进程相互配合来完毕的.AMS服务统一调度系统中全部进程的Activity启 ...

  6. 数据库读写锁的实现(C++)

    一.基本概念 在数据库中,对某数据的两个基本操作为写和读.分布有两种锁控制:排它锁(X锁).共享锁(S锁). 排它锁(x锁):若事务T对数据D加X锁,则其他不论什么事务都不能再对D加不论什么类型的锁. ...

  7. JWT笔记(2)

    上文对JWT模块进行了一个简单的分析.这篇文章稍微做出一些深入的了解. 一,Header篡改攻击 因为JWT的Header是强制有效并且是明文传输(Base64URL编码,几乎等同于明文).那么恶意用 ...

  8. asp.net服务器数据源控件学习笔记

    1.数据绑定控件的DataSource属性只能接受三种接口类型的数据 (IListSource,IEnumerable,IDataSource) 2.要手动在已经绑定数据的数据绑定控件上添加自定义的数 ...

  9. 初识Nginx及编译安装Nginx

    初识Nginx及编译安装Nginx 环境说明: 系统版本    CentOS 6.9 x86_64 软件版本    nginx-1.12.2 1.什么是Nginx? 如果你听说或使用过Apache软件 ...

  10. bzoj2115【WC2001】Xor

    2115: [Wc2011] Xor Time Limit: 10 Sec  Memory Limit: 259 MB Submit: 2059  Solved: 856 [Submit][Statu ...