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. 02-命令篇——基础命令&常用命令

    基础命令 docker 启动与停止 启动docker systemctl start docker 停止docker systemctl stop docker 重启docker systemctl ...

  2. jQuery获取父窗口的元素

    js获取父页面的元素可以用 $(window.parent.document).find("#customer_id").val();这里的customer_id表示父页面某一个元 ...

  3. BZOJ 3864 Hero meet devil (状压DP)

    最近写状压写的有点多,什么LIS,LCSLIS,LCSLIS,LCS全都用状压写了-这道题就是一道状压LCSLCSLCS 题意 给出一个长度为n(n<=15)n(n<=15)n(n< ...

  4. SQL的左连接与右链接

    1.准备工作 Oracle  外连接(OUTER JOIN)包括以下: 左外连接(左边的表不加限制) 右外连接(右边的表不加限制) 全外连接(左右两表都不加限制) 对应SQL:LEFT/RIGHT/F ...

  5. 使用docker 起容器配置负载均衡(加权)

    首先要准备三个nginx的容器: 第二个容器: 第三个容器: 进入第一个容器(主容器)  要配置的容器(docker exec -it 容器id /bin/bash)  vi/etc/nginx/ng ...

  6. Shiro (包含权限满足其中一个就通过的用法)

    方法/步骤 1 web.xml添加配置 <!-- shiro过滤器 --> <filter> <filter-name>shiroFilter</filter ...

  7. ps/top

    ps -e 显示所有进程,环境变量 -f 全格式显示 -a 显示所有用户的所有进程(包括其他用户) -u 按用户名和启动时间的顺序显示进程 -x 显示无控制终端的进程 -w 显示加宽可以显示较多信息 ...

  8. MySQL数据分析—(4)关系数据库的三个逻辑框架

    (一)前面课程逻辑梳理 任何一门数据的软件也好,数据构架也好,或者说是数据学科也好,最终都是要解决实际问题的,大家说是不是? 前面jacky讲为什么要引入数据库的时候,举了一个案例,大家还记的吗?大家 ...

  9. https服务

    版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明.本文链接:https://blog.csdn.net/bright69/article/deta ...

  10. SSRF漏洞攻击利用从浅到深

    梳理一下ssrf 不详细 简单记录 0x01 SSRF成因和基本利用0x02 内网打未授权redis0x03 关于ssrf打授权的redis0x04 写redis shell和密钥的一点问题0x05 ...