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的更多相关文章

  1. Spark源码剖析 - SparkContext的初始化(二)_创建执行环境SparkEnv

    2. 创建执行环境SparkEnv SparkEnv是Spark的执行环境对象,其中包括众多与Executor执行相关的对象.由于在local模式下Driver会创建Executor,local-cl ...

  2. Spark源码分析:多种部署方式之间的区别与联系(转)

    原文链接:Spark源码分析:多种部署方式之间的区别与联系(1) 从官方的文档我们可以知道,Spark的部署方式有很多种:local.Standalone.Mesos.YARN.....不同部署方式的 ...

  3. Spark源码分析之九:内存管理模型

    Spark是现在很流行的一个基于内存的分布式计算框架,既然是基于内存,那么自然而然的,内存的管理就是Spark存储管理的重中之重了.那么,Spark究竟采用什么样的内存管理模型呢?本文就为大家揭开Sp ...

  4. Spark源码分析之八:Task运行(二)

    在<Spark源码分析之七:Task运行(一)>一文中,我们详细叙述了Task运行的整体流程,最终Task被传输到Executor上,启动一个对应的TaskRunner线程,并且在线程池中 ...

  5. Spark源码分析之五:Task调度(一)

    在前四篇博文中,我们分析了Job提交运行总流程的第一阶段Stage划分与提交,它又被细化为三个分阶段: 1.Job的调度模型与运行反馈: 2.Stage划分: 3.Stage提交:对应TaskSet的 ...

  6. spark 源码分析之四 -- TaskScheduler的创建和启动过程

    在 spark 源码分析之二 -- SparkContext 的初始化过程 中,第 14 步 和 16 步分别描述了 TaskScheduler的 初始化 和 启动过程. 话分两头,先说 TaskSc ...

  7. spark源码单步跟踪阅读-从毛片说起

    想当年读大学时,那时毛片还叫毛片,现在有文明的叫法了,叫小电影或者爱情动作片.那时宿舍有位大神,喜欢看各种毛片,当我们纠结于毛片上的马赛克时,大神大手一挥说道:这算啥,阅尽天下毛片,心中自然无码!突然 ...

  8. spark源码分析以及优化

    第一章.spark源码分析之RDD四种依赖关系 一.RDD四种依赖关系 RDD四种依赖关系,分别是 ShuffleDependency.PrunDependency.RangeDependency和O ...

  9. Spark 源码浅读-SparkSubmit

    Spark 源码浅读-任务提交SparkSubmit main方法 main方法主要用于初始化日志,然后接着调用doSubmit方法. override def main(args: Array[St ...

随机推荐

  1. Android笔记-Activity相关+内存泄漏+Fragment+service

    看了下,上次学习android还是17年的事情,,,,两年过去了我现在终于来搞android了... 官网有一段基础描述: https://developer.android.google.cn/gu ...

  2. Alpha项目测试--个人第五次作业

    img {border:solid 1px black} 这个作业属于哪个课程 <https://edu.cnblogs.com/campus/xnsy/2019autumnsystemanal ...

  3. hudson 使用节点打包出现ClassNotFoundException: org.jvnet.hudson.maven3.agent.Maven3Main 错误

    java.lang.NoClassDefFoundError: org/jvnet/hudson/maven3/agent/Maven3Main Caused by: java.lang.ClassN ...

  4. 如何使用python异常---runtimeError方法

    RuntimeError def ilove(name): if name=='陈培昌': print('i love {0}'.format(name)) elif name == '程劲': pr ...

  5. [Functional Programming] Using ComposeK for both get State and modify State

    We have State like this: const state = { cards: [ { id: "green-square", color: "green ...

  6. [git]用户名,邮箱

    1.查看当前的用户名,邮箱 git config user.name git config user.email 2. 修改当前用户名,邮箱 git config --global user.name ...

  7. php注意事项|要点

    1. 用单引号代替双引号来包含字符串,这样做会更快一些.因为 PHP 会在双引号包围的 字符串中搜寻变量,单引号则不会,注意:只有 echo 能这么做,它是一种可以把多个字符 串当作参数的“函数”(译 ...

  8. Ubuntu 蓝牙鼠标的问题

    问题: 我有一个小巧的蓝牙鼠标,但有一个问题. 当它不使用一段时间时,它会关闭. 好的我得按按钮把它打开. 但是我发现,在我在蓝牙小程序下单击"连接"之前,它不会再被Ubuntu识 ...

  9. 薛的lca讲课配到题解

    2.15 LCA Nearest Common Ancestors POJ 1330 题意:给出一棵树, 询问两个点的最近公共祖先. 思路: $LCA$模板题,请各位掏出各式各样的模板A穿它. #in ...

  10. ansible-cmdb 解析(ansible all -m setup )收集过来的信息并以html方式显示。

    首先安装 ansible-cmdb 直接pip install ansible-cmdb 安装 然后执行收集信息命令 ansible all -m setup >/tmp/out/ 修改下ans ...