Spark配置——SparkConf源码剖析

Spark配置

任何优秀的软件或服务都会提供一些配置参数,这些配置参数有些是内置的,有些则是可以由用户配置的。Spark作为一款优秀的计算框架,也配置了各种各样的系统配置参数。SparkConf是Spark的配置类,这个类在Spark的历史版本中已经存在很久了,Spark中的每一个组件都直接或者间接地使用着它所存储的属性,这些属性都存储在如下的数据结构中:

private val settings = new ConcurrentHashMap[String, String]()

由以上代码的泛型可以看出,Spark的所有配置,无论是key还是value都是String类型。Spark的配置通过以下3种方式获取:

  • 来源于系统参数(即使用System.getProperties获取的属性)中以spark. 作为前缀的那部分属性;
  • 使用SparkConf的API进行设置;
  • 从其它SparkConf中克隆。

下面将具体说明这3种方式的实现

1、系统属性中的配置

在SparkConf中有一个Boolean类型的构造器属性loadDefaults,当loadDefaults为 true 时,将会从系统属性中加载Spark配置,代码如下:

/** Create a SparkConf that loads defaults from system properties and the classpath */
def this() = this(true) //构造方法

if (loadDefaults) {
    loadFromSystemProperties(false)
}

private[spark] def loadFromSystemProperties(silent: Boolean): SparkConf = {
  // Load any spark.* system properties 加载以spark. 开头的系统属性
  for ((key, value) <- Utils.getSystemProperties if key.startsWith("spark.")) {
    set(key, value, silent)
  }
  this
}

以上代码调用了 Utils 工具类的getSystemProperties方法,其作用为获取系统的键值对属性。loadFromSystemProperties方法在获取了系统属性后,使用Scala守卫过滤出其中以“spark.”字符串为前缀的key和value并且调用 set 方法,最终设置到setting中。

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
}

2、使用SparkConf配置的API

给SparkConf添加配置的一种常见方式是使用SparkConf中提供的API。其中有些API最终实际调用了set的重载方法,如:

/** Set a configuration variable. */
def set(key: String, value: String): SparkConf = {
  set(key, value, false)
}

SparkConf中的setMaster、setAppName、setJars、setExecutorEnv、setSparkHome、setAll等方法最终都是通过上述的set方法完成Spark配置的,如setMaster和setAppName:

/**
 * The master URL to connect to, such as "local" to run locally with one thread, "local[4]" to
 * run locally with 4 cores, or "spark://master:7077" to run on a Spark standalone cluster.
 */
def setMaster(master: String): SparkConf = {
  set("spark.master", master)
}

/** Set a name for your application. Shown in the Spark web UI. */
def setAppName(name: String): SparkConf = {
  set("spark.app.name", name)
}

3、克隆SparkConf配置

有些情况下,同一个SparkConf实例中的配置信息需要被Spark中的多个组件共用,而我们往往首先想到的方法是将SparkConf实例定义为全局变量或者通过参数传递给其它组件,但是这会引入并发问题。虽然setting是线程安全的ConcurrentHashMap类,而且ConcurrentHashMap也被证明是高并发下性能表现不错的数据结构,但是只要存在并发,就一定会有性能的损失问题。也可以新建一个SparkConf实例b,并将a中的配置信息全部拷贝到b中,这种方式显然不是最优雅的,复制代码会散落在程序的各个角落。

SparkConf继承了Cloneable物质并实现了实现clone方法,可通过Cloneable物质提高了代码的可利用性。

class SparkConf(loadDefaults: Boolean) extends Cloneable with Logging {
    def this() = this(true)

    /** Copy this object */
    override def clone: SparkConf = {
      val cloned = new SparkConf(false)
      settings.entrySet().asScala.foreach { e =>
        cloned.set(e.getKey(), e.getValue(), true)
      }
      cloned
    }
}

猜你喜欢

转载自blog.csdn.net/LINBE_blazers/article/details/87829645