2. 创建执行环境SparkEnv

SparkEnv是Spark的执行环境对象,其中包括众多与Executor执行相关的对象。由于在local模式下Driver会创建Executor,local-cluster部署模式或者Standalone部署模式下Worker另起的CoarseGrainedExecutorBackend进程中也会创建Executor,所以SparkEnv存在于Driver或者CoarseGrainedExecutorBackend进程中。创建SparkEnv主要使用SparkEnv的createDriverEnv,SparkEnv.createDriverEnv方法有三个参数:conf、isLocal和listenerBus。

上面代码中的_conf是对SparkConf的复制,isLocal标识是否是单机模式,listenerBus采用监听器模式维护各类事件的处理。

SparkEnv的方法createDriverEnv最终调用create创建SparkEnv。SparkEnv的构造步骤如下:

  1. 创建安全管理器SecurityManager;
  2. 创建基于Netty的RPC通信工厂RpcEnv
  3. 创建广播管理器BroadcastManager;
  4. 创建Map任务输出跟踪器mapOutputTracker;
  5. 实例化ShuffleManager;
  6. 创建MemoryManager;
  7. 创建块传输服务BlockTransferService;
  8. 创建BlockManagerMaster;
  9. 创建块管理器BlockManager;
  10. 创建测量系统MetricsSystem;
  11. 创建SparkEnv;

2.1 安全管理器SecurityManager

SecurityManager主要对权限、账户进行设置,如果使用Hadoop YARN作为集群管理器,则需要使用证书生成secret key登录,最后给当前系统设置默认的口令认证实例,此实例采用匿名内部类实现,如图:

2.2 创建基于Netty的RPC通信RpcEnv

Netty是Spark中最基础的设施。....

2.3 创建广播管理器BroadcastManager

BroadcastManager用于将配置信息和序列化后的RDD、Job以及ShuffleDependency等信息在本地存储。如果为了容灾,也会复制到其他节点上。创建BroadcastManager的代码如下:

BoradcastManager必须在其初始化方法initialize被调用后,才能生效。initialize方法实际利用发射生成广播工厂示例broadcastFactory(可以配置属性spark.broadcast.factory指定,默认为org.apache.spark.broadcast.TorrentBroadcastFactory)。BroadcastManager的广播方法new Broadcast实际代理了工厂broadcastFactory的new Broadcast方法来生成广播对象。unbroadcast方法实际代理了工厂broadcastFactory的unbroadcast方法生成非广播对象。BroadcastManager的initialize、unbroadcast及new Broadcast方法见代码:

2.4 创建Map任务输出跟踪器mapOutputTracker

mapOutputTracker用于跟踪map阶段任务的输出状态,此状态便于reduce阶段任务获取地址及中间输出结果。每个map任务或者reduce任务都会有其唯一标识,分别为mapId和reduceId。每个reduce任务的输入可能是多个map任务的输出,reduce会到各个map任务的所在节点上拉取Block,这一过程叫做shuffle。每批shuffle过程都有唯一的标识shuffleId。

这里先介绍下MapOutputTrackerMaster。MapOutputTrackerMaster内部使用mapStatuses:ConcurrentHashMap[Int, Array[MapStatus]]来维护跟踪各个map任务的输出状态。其中key对应shuffleId,Array存储各个map任务对应的状态信息MapStatus。由于MapStatus维护了map输出Block的地址BlockManagerId,所以reduce任务知道从何处获取map任务的中间输出。MapOutputTrackerMaster还使用cachedSerializedStatuses:ConcurrentHashMap[Int, Array[Byte]]维护序列化后的各个map任务的输出状态。其中key对应shuffleId,Array存储各个序列化MapStatus生成的字节数组。

Driver和Executor处理MapOutputTracker的方式有所不同。

  • 如果当前应用程序是Driver,则创建MapOutputTrackerMaster,然后创建MapOutputTrackerMasterEndpoint,并且注册到RpcEnv中。
  • 如果当前应用程序是Executor,则创建MapOutputTrackerWorker,并从RpcEnv中找到MapOutputTrackerMasterEndpoint的引用。

无论是Driver还是Executor,最后都由mapOutputTracker的属性trackerEndpoint持有MapOutputTrackerMasterEndpoint的引用,代码如图:

map任务的状态正是由Executor向持有的MapOutputTrackerMasterEndpoint发送消息,将map任务状态同步到mapOutputTracker的mapStatuses和cachedSerializedStatuses的。Executor究竟是如何找到MapOutputTrackerMasterEndpoint的?registerOrLookupEndpoint方法通过调用RpcUtils.makeDriverRef找到MapOutputTrackerMasterEndpoint,实际正是利用RpcEnv提供的分布式消息机制实现的。

2.5 实例化ShuffleManager

ShuffleManager负责管理本地及远程的block数据的shuffle操作。ShuffleManager默认为通过反射方式生成的SortShuffleManager实例。SortShuffleManager通过持有的IndexShuffleBlockManager间接操作BlockManager中的DiskBlockManager将map结果写入本地,并根据shuffleId、mapId写入索引文件,也能通过MapOutputTrackerMaster种种那个维护的mapStatuses从本地或者其他远程节点读取文件。Spark作为并行计算框架,同一个作业会被划分为多个任务在多个节点上并行执行,reduce的输入可能存在于多个节点上,因此需要通过“洗牌”将所有reduce的输入汇总起来,这个过程就是shuffle。

shuffleManager和MemoryManager的创建。

2.6 内存管理器MemoryManager

用于管理最大Execution内存和最大Storage内存,可以通过spark.memory.useLegacyMode选择StaticMemoryManager模式还是UnifiedMemoryManager模式。一般默认是UnifiedMemoryManager模式。对于StaticMemoryManager和UnifiedMemoryManager模式可以通过spark.executor.memory、spark.shuffle.memoryFraction、spark.shuffle.safetyFraction配置属性控制内存。

getMaxMemory方法用于获取shuffle所有线程占用的最大内存,实现如下:

MemoryManager通常运行在Executor中,Driver中的MemoryManager只有在local模式下才起作用。

2.7 创建块传输服务BlockTransferService

BlockTransferService默认为NettyBlockTransferService,它使用Netty提供的异步事件驱动的网络应用框架,提供web服务及客户端,获取远程节点上Block的集合。

2.8 BlockManagerMaster介绍

BlockManagerMaster负责对Block的管理和协调,具体操作依赖于BlockManagerMasterEndpoint。Driver和Executor处理BlockManagerMaster的方式不同:

  • 如果当前应用程序是Driver,则创建BlockManagerMasterEndpoint,并且注册到RpcEnv中。
  • 如果当前应用程序是Executor,则从RpcEnv中找到BlockManagerMasterEndpoint。

无论是Driver还是Executor,最后BlockManagerMaster的属性driverEndpoint将持有对BlockManagerMasterEndpoint的引用。BlockManagerMaster的创建代码如下:

registerOrLookupEndpoint已在2.4出现过,不再介绍。

2.9 创建块管理器BlockManager

BlockManager负责对Block的管理,只有在BlockManager的初始化方法initialize调用后,它才是有效的。BlockManager是存储系统的一部分。BlockManager的创建代码如下:

2.10 创建测量系统MetricsSystem

MetricsSystem是Spark的测量系统,创建MetricsSystem的代码如下:

上面调用的createMetricsSystem方法实际创建了MetricsSystem,代码如下:

构造MetricsSystem的过程最重要的是调用了MetricsConfig的initialize方法,见代码如下:

从以上实现可以看出,MetricsConfig的initialize方法主要负责加载metrics.properties文件中的属性配置,并对属性进行初始化转换。

例如,将属性

("*.sink.servlet.class"->"class1", "*.sink.servlet.path"->"path1")

转换为

Map("*" -> Properties("sink.servlet.class" -> "class1", "sink.servlet.path" -> "path1"))

2.11 创建SparkEnv

当所有的基础组件准备好后,最终使用下面的代码创建执行环境SparkEnv。

serializer和closureSerializer都是使用Class.forName反射生成的org.apache.spark.serializer.JavaSerializer类的实例,其中closureSerializer实例特别用来对Scala中的闭包进行序列化。

查看:Spark源码剖析——SparkContext的初始化

参考资料:

《深入理解Spark核心思想与源码分析》

Spark源码剖析 - SparkContext的初始化(二)_创建执行环境SparkEnv的更多相关文章

  1. Spark源码剖析 - SparkContext的初始化(三)_创建并初始化Spark UI

    3. 创建并初始化Spark UI 任何系统都需要提供监控功能,用浏览器能访问具有样式及布局并提供丰富监控数据的页面无疑是一种简单.高效的方式.SparkUI就是这样的服务. 在大型分布式系统中,采用 ...

  2. Spark源码剖析 - SparkContext的初始化(五)_创建任务调度器TaskScheduler

    5. 创建任务调度器TaskScheduler TaskScheduler也是SparkContext的重要组成部分,负责任务的提交,并且请求集群管理器对任务调度.TaskScheduler也可以看作 ...

  3. Spark源码剖析 - SparkContext的初始化(六)_创建和启动DAGScheduler

    6.创建和启动DAGScheduler DAGScheduler主要用于在任务正式交给TaskSchedulerImpl提交之前做一些准备工作,包括:创建Job,将DAG中的RDD划分到不同的Stag ...

  4. Spark源码剖析 - SparkContext的初始化(九)_启动测量系统MetricsSystem

    9. 启动测量系统MetricsSystem MetricsSystem使用codahale提供的第三方测量仓库Metrics.MetricsSystem中有三个概念: Instance:指定了谁在使 ...

  5. Spark源码剖析 - SparkContext的初始化(八)_初始化管理器BlockManager

    8.初始化管理器BlockManager 无论是Spark的初始化阶段还是任务提交.执行阶段,始终离不开存储体系.Spark为了避免Hadoop读写磁盘的I/O操作成为性能瓶颈,优先将配置信息.计算结 ...

  6. Spark源码剖析 - SparkContext的初始化(一)

    1. SparkContext概述 注意:SparkContext的初始化剖析是基于Spark2.1.0版本的 Spark Driver用于提交用户应用程序,实际可以看作Spark的客户端.了解Spa ...

  7. Spark源码剖析 - SparkContext的初始化(十)_Spark环境更新

    12. Spark环境更新 在SparkContext的初始化过程中,可能对其环境造成影响,所以需要更新环境,代码如下: SparkContext初始化过程中,如果设置了spark.jars属性,sp ...

  8. Spark源码剖析 - SparkContext的初始化(七)_TaskScheduler的启动

    7. TaskScheduler的启动 第五节介绍了TaskScheduler的创建,要想TaskScheduler发挥作用,必须要启动它,代码: TaskScheduler在启动的时候,实际调用了b ...

  9. Spark源码剖析 - SparkContext的初始化(四)_Hadoop相关配置及Executor环境变量

    4. Hadoop相关配置及Executor环境变量的设置 4.1 Hadoop相关配置信息 默认情况下,Spark使用HDFS作为分布式文件系统,所以需要获取Hadoop相关配置信息的代码如下: 获 ...

随机推荐

  1. 【BZOJ3142】[HNOI2013]数列(组合计数)

    [BZOJ3142][HNOI2013]数列(组合计数) 题面 BZOJ 洛谷 题解 唯一考虑的就是把一段值给分配给\(k-1\)天,假设这\(k-1\)天分配好了,第\(i\)天是\(a_i\),假 ...

  2. 「ZJOI2016」大森林 解题报告

    「ZJOI2016」大森林 神仙题... 很显然线段树搞不了 考虑离线操作 我们只搞一颗树,从位置1一直往后移动,然后维护它的形态试试 显然操作0,1都可以拆成差分的形式,就是加入和删除 因为保证了操 ...

  3. Apache虚拟主机+AD压力测试

    <Directory "/usr/local/awstats/wwwroot"> Options NoneAllowOverride None Order allow, ...

  4. 解题:NOI2018 你的名字(68pts暴力)

    题面 rt,如果省选没退役就补 SAM的优势:简单明了 先建S的SAM并标记所有节点,之后每次询问直接把T按广义SAM的方法插上去,统计新加的节点到根的状态代表的本质不同子串数,减掉被标记的部分就是T ...

  5. 百度地图API,展示地图和添加控件

    1.申请百度账号和AK 点我申请 2.准备页面 根据HTML标准,每一份HTML文档都应该声明正确的文档类型,我们建议您使用最新的符合HTML5规范的文档声明: <!DOCTYPE html&g ...

  6. 上pixiv解决法(保存)

    C:\Windows\System32\drivers\etc\hosts 127.0.0.1 localhost 127.0.0.1 advstat.xunlei.com 127.0.0.1 cl. ...

  7. 跟着underscore学防抖

    前言 在前端开发中会遇到一些频繁的事件触发,比如: window 的 resize.scroll mousedown.mousemove keyup.keydown -- 为此,我们举个示例代码来了解 ...

  8. Day27--Python--初识socket

    一. C\S架构, 客户端服务端架构 客户端(client): 享受服务端提供的服务 服务端(server): 给客户端提供服务 B\S 浏览器和服务端 B (browser) 二. 网络通信的整个流 ...

  9. Day18--Python--面向对象--类与类之间的关系

    1. 依赖关系 在方法中引入另一个类的对象 (最不紧密的一种关系) 依赖关系都是把另一个对象当做参数 class Elephant: def __init__(self, name): self.na ...

  10. Docker下安装Influxdb-1.6.1和Grafana5.2.2

    第一步.安装Influxdb 首先启动docker systemctl start docker 然后安装Influxdb(这里解释一下为啥用docker,因为官网下载的话需要FQ[fan-qiang ...