Spark源码(1): SparkConf
1. 简介
SparkConf类负责管理Spark的所有配置项。在我们使用Spark的过程中,经常需要灵活配置各种参数,来使程序更好、更快地运行,因此也必然要与SparkConf类频繁打交道。了解它的细节不无裨益。
2. SparkConf类的构造方法
下面先来看一看SparkConf类的构造方法。为了读起来清晰明了,可能会在不影响理解的前提下适当删去无关代码、注释,并调整顺序。
class SparkConf(loadDefaults: Boolean) extends Cloneable with Logging with Serializable {import SparkConf._ if (loadDefaults) { loadFromSystemProperties(false) }
def this() = this(true)
// ...}
代码中的import语句是从SparkConf类的伴生对象中导入一些东西,它们主要管理过期的、旧版本兼容的配置项,以及日志输出。Scala中没有Java的静态(static)概念,类的伴生对象中维护的成员和方法就可以视为类的静态成员和静态方法。
SparkConf类有一个主构造方法参数loadDefaults,它指示是否要从Java系统属性(即System.getProperties()取得的属性)加载默认的与Spark相关的配置。
3. Spark配置项的存储
SparkConf内部是采用ConcurrentHashMap来维护所有配置项键值的。
private val settings = new ConcurrentHashMap[String, String]()
这自然是考虑到了并发环境下的线程安全性问题。另外,它的键与值类型都为String,说明所有Spark配置项都以字符串形式存储。
3.1 设置配置项
要设置Spark配置项,有以下三种方法。
(1) 直接用Set类方法设置
这是我们开发过程中最常用的方法。SparkConf中提供了多种多样的Set类方法,最基础的set()方法重载如下。
def set(key: String, value: String): SparkConf = {set(key, value, false) }
private[spark] def set(key: String, value: String, silent: Boolean): SparkConf = {if (key == null) { throw new NullPointerException("null key") }if (value == null) { throw new NullPointerException("null value for " + key) }if (!silent) { logDeprecationWarning(key) } settings.put(key, value) this }
可见配置项的键值都不能为null。并且包括set()在内的所有Set类方法都返回this,所以支持链式调用,这样使用起来比较简洁。
另外,还有一些方法可以快速设置常用配置项,比如上篇代码#0.1中出现过的setMaster()与setAppName()。它们最终也会调用set()方法。
def setMaster(master: String): SparkConf = { set("spark.master", master) } def setAppName(name: String): SparkConf = { set("spark.app.name", name) }
(2) 通过系统属性加载
如果上述代码#1.1中的loadDefaults参数为true,那么SparkConf会从Java系统属性中加载配置项。如果调用无参的辅助构造方法,即直接new SparkConf()的话,也会将loadDefaults设为true。Java系统属性可以通过System.setProperty()方法在程序中动态设置。
来看代码#1.1中调用的loadFromSystemProperties()方法。
private[spark] def loadFromSystemProperties(silent: Boolean): SparkConf = {for ((key, value) <- Utils.getSystemProperties if key.startsWith("spark.")) {set(key, value, silent) }this }
它使用通用工具类Utils中的方法取得系统属性,过滤出以字符串“spark.”为前缀的键,然后调用set()方法设置键值。由于系统属性相关的参数是一次性初始化的,所以用Set类方法设置的值可以覆盖它们。
(3) 克隆SparkConf
SparkConf类继承了Cloneable特征(trait,类似于Java接口的增强版)并覆写了clone()方法,因此SparkConf是可以(深)克隆的。
override def clone: SparkConf = { val cloned = new SparkConf(false) settings.entrySet().asScala.foreach { e => cloned.set(e.getKey(), e.getValue(), true) } cloned }
虽然ConcurrentHashMap保证线程安全,不会影响SparkConf实例共享,但在高并发的情况下,锁机制可能会带来性能问题。我们就可以克隆SparkConf到多个组件中,以让它们获得相同的配置参数。
3.2 获取配置项
获取配置项只有一个途径,即调用Get类方法。Get类方法同样有很多实现,基础的get()与getOption()如下所示。
def get(key: String): String = { getOption(key).getOrElse(throw new NoSuchElementException(key)) } def get(key: String, defaultValue: String): String = { getOption(key).getOrElse(defaultValue) }
def getOption(key: String): Option[String] = { Option(settings.get(key)).orElse(getDeprecatedConfig(key, settings)) }
获取配置项时,会同时检查过期配置(getDeprecatedConfig()方法是伴生对象中定义的),并且会使用Scala Option来包装返回的结果,对于有值(Some)和无值(None)的情况可以灵活处理。
另外,Get类方法中有不少涉及数据类型转换和单位转换,如getDouble()、getLong()、getSizeAsMb()、getTimeAsSeconds()等等,都是为了使用方便,不再赘述。
3.3 校验配置项
SparkConf中有一个方法validateSettings(),用来校验配置项。它的源码很长,但是逻辑比较简单,主要是对过期配置项进行警告,以及对非法设置或不兼容的配置项抛出异常。
限于篇幅原因,这里就不贴出该方法的源码了。感兴趣的看官可以自己找找看,里面校验了大量之后一定会用到的配置项。
总结
本文通过SparkConf类的部分源码,简述了SparkConf的构造方法、配置存储,以及设置、获取、校验配置项的方法逻辑。
SparkConf是SparkContext初始化的必备前提。了解了SparkConf,就可以分析复杂得多的SparkContext了。
转自:https://mp.weixin.qq.com/s/8HXWhfl-w-UU-0Zy4YHl2g
Spark源码(1): SparkConf的更多相关文章
- Spark源码剖析 - SparkContext的初始化(二)_创建执行环境SparkEnv
2. 创建执行环境SparkEnv SparkEnv是Spark的执行环境对象,其中包括众多与Executor执行相关的对象.由于在local模式下Driver会创建Executor,local-cl ...
- Spark源码分析:多种部署方式之间的区别与联系(转)
原文链接:Spark源码分析:多种部署方式之间的区别与联系(1) 从官方的文档我们可以知道,Spark的部署方式有很多种:local.Standalone.Mesos.YARN.....不同部署方式的 ...
- Spark源码分析之九:内存管理模型
Spark是现在很流行的一个基于内存的分布式计算框架,既然是基于内存,那么自然而然的,内存的管理就是Spark存储管理的重中之重了.那么,Spark究竟采用什么样的内存管理模型呢?本文就为大家揭开Sp ...
- Spark源码分析之八:Task运行(二)
在<Spark源码分析之七:Task运行(一)>一文中,我们详细叙述了Task运行的整体流程,最终Task被传输到Executor上,启动一个对应的TaskRunner线程,并且在线程池中 ...
- Spark源码分析之五:Task调度(一)
在前四篇博文中,我们分析了Job提交运行总流程的第一阶段Stage划分与提交,它又被细化为三个分阶段: 1.Job的调度模型与运行反馈: 2.Stage划分: 3.Stage提交:对应TaskSet的 ...
- spark 源码分析之四 -- TaskScheduler的创建和启动过程
在 spark 源码分析之二 -- SparkContext 的初始化过程 中,第 14 步 和 16 步分别描述了 TaskScheduler的 初始化 和 启动过程. 话分两头,先说 TaskSc ...
- spark源码单步跟踪阅读-从毛片说起
想当年读大学时,那时毛片还叫毛片,现在有文明的叫法了,叫小电影或者爱情动作片.那时宿舍有位大神,喜欢看各种毛片,当我们纠结于毛片上的马赛克时,大神大手一挥说道:这算啥,阅尽天下毛片,心中自然无码!突然 ...
- spark源码分析以及优化
第一章.spark源码分析之RDD四种依赖关系 一.RDD四种依赖关系 RDD四种依赖关系,分别是 ShuffleDependency.PrunDependency.RangeDependency和O ...
- Spark 源码浅读-SparkSubmit
Spark 源码浅读-任务提交SparkSubmit main方法 main方法主要用于初始化日志,然后接着调用doSubmit方法. override def main(args: Array[St ...
随机推荐
- 2018/7/31--zznu-oj-问题 G: 方差 普拉斯--【两重暴力循环求方差即可!】
问题 G: 方差 普拉斯 时间限制: 1 Sec 内存限制: 128 MB提交: 94 解决: 17[提交] [状态] [讨论版] [命题人:admin] 题目描述 方差(样本方差)是每个样本值与 ...
- npm常规操作
1.如果想在当前文件下创建package.json,只要在当前目录下执行npm init 2.如果执行过程中缺少依赖,有两种途径 ①安装全局 npm install -g express ②在当前工程 ...
- js 同步 异步 宏任务 微任务 文章分享
分享一篇 写的很好的 宏任务 微任务 同步异步的文章 文章原地址: https://juejin.im/post/59e85eebf265da430d571f89 这一次,彻底弄懂 JavaScri ...
- 字符串的新方法——includes() padStart() padEnd()
ES6为字符串提供了一个新方法,叫做String.prototype.includes('要包含的字符串'),如果包含,则返回字符串,否则返回false 使用ES6中的字符串新方法String.pro ...
- 使用eclipse open type对话框
需要依赖jdt的相关插件(ui和core) 具体调用方法: Shell parent= JavaPlugin.getActiveWorkbenchShell(); OpenTypeSelectionD ...
- java开发时,eclipse设置编码
修改eclipse默认工作空间编码方式,General——Workspace——Text file encoding 修改工程编码方式,右击工程——Properties——Resource——Text ...
- SIGAI深度学习第九集 卷积神经网络3
讲授卷积神经网络面临的挑战包括梯度消失.退化问题,和改进方法包括卷积层.池化层的改进.激活函数.损失函数.网络结构的改 进.残差网络.全卷机网络.多尺度融合.批量归一化等 大纲: 面临的挑战梯度消失问 ...
- 012_Linux驱动之_wait_event_interruptible
1. 首先这篇博客讲解得挺好的,推荐 wait_event_interruptible 使用方法 2 .函数原型: #define wait_event_interruptible(wq, condi ...
- 彻底解决eslint与webstorm针对vue的script标签缩进处理方式冲突问题
彻底解决eslint与webstorm针对vue的script标签缩进处理方式冲突问题 2018年12月08日 21:58:26 Kevin395 阅读数 1753 背景不多介绍了,直接上代码. ...
- Oracle Index 索引监控
1.冗余索引的弊端 大量冗余和无用的索引导致整个数据库性能低下,耗用了大量的CPU与I/O开销,具体表现如下: a.耗用大量的存储空间(索引段的维护与管理) b.增加了DML完成的时间 c.耗用大量统 ...