当脚本启动Master流程走到最后的时候,是解析成命令后返回给spark-class的 exec ${CMD[@]} 真正执行,也就是在这里真正开始初始化Master。
这里的命令是:
java -cp ../jar/* org.apache.spark.deploy.master.Master --port 7077 --webui-port 8080
org.apache.spark.deploy.master.Master
先进入master伴生类object master看看。
private[deploy] object Master extends Logging {
val SYSTEM_NAME = "sparkMaster"
val ENDPOINT_NAME = "Master"
// spark-class传入参数:--port 7077 --webui-port 8080
def main(argStrings: Array[String]) {
Thread.setDefaultUncaughtExceptionHandler(new SparkUncaughtExceptionHandler(
exitOnUncaughtException = false))
// 初始化日志输出
Utils.initDaemon(log)
// 创建conf对象其实是读取Spark默认配置的参数
val conf = new SparkConf
// 解析配置,初始化RPC服务和终端
// 通过MasterArguments解析RPC需要的参数:host,port,webui-port
val args = new MasterArguments(argStrings, conf)
val (rpcEnv, _, _) = startRpcEnvAndEndpoint(args.host, args.port, args.webUiPort, conf)
rpcEnv.awaitTermination()
}
/**
* Start the Master and return a three tuple of:
* (1) The Master RpcEnv
* (2) The web UI bound port
* (3) The REST server bound port, if any
*/
// 上面有说明,startRpcEnvAndEndpoint会返回一个元组包含,RPC,webui,rest服务的绑定端口
// 那么这里主要是初始化SecurityManager,RPC,及rest绑定端口
def startRpcEnvAndEndpoint(
host: String,
port: Int,
webUiPort: Int,
conf: SparkConf): (RpcEnv, Int, Option[Int]) = {
// 初始化securityManager
val securityMgr = new SecurityManager(conf)
// 初始化RPC
val rpcEnv = RpcEnv.create(SYSTEM_NAME, host, port, conf, securityMgr)
// 向RPC注册master终端
// 这里new Master的时候进行了Master的实例化
val masterEndpoint = rpcEnv.setupEndpoint(ENDPOINT_NAME,
new Master(rpcEnv, rpcEnv.address, webUiPort, securityMgr, conf))
// rest的绑定端口
val portsResponse = masterEndpoint.askSync[BoundPortsResponse](BoundPortsRequest)
(rpcEnv, portsResponse.webUIPort, portsResponse.restPort)
}
}
SparkConf
可以看到,加载默认配置的时候,是以spark.匹配,只要是spark.开头的配置都加载了。其实就是之前加载的spark-config.sh,将conf目录下导入到环境变量中的所有spark配置,主要是spark-default.conf文件中的设置,下面大概列举了conf文件的配置。
class SparkConf(loadDefaults: Boolean) extends Cloneable with Logging with Serializable {
import SparkConf._
/** Create a SparkConf that loads defaults from system properties and the classpath */
def this() = this(true)
private val settings = new ConcurrentHashMap[String, String]()
@transient private lazy val reader: ConfigReader = {
val _reader = new ConfigReader(new SparkConfigProvider(settings))
_reader.bindEnv(new ConfigProvider {
override def get(key: String): Option[String] = Option(getenv(key))
})
_reader
}
if (loadDefaults) {
loadFromSystemProperties(false)
}
// 加载之前调用spark-config.sh导入的环境变量,匹配以spark.开头的所有配置
private[spark] def loadFromSystemProperties(silent: Boolean): SparkConf = {
// Load any spark.* system properties
for ((key, value) <- Utils.getSystemProperties if key.startsWith("spark.")) {
set(key, value, silent)
}
this
}
}
Spark-default.conf
HA环境下,spark-env.sh中的相关配置也会导入到conf中。
# Example:
# spark.master spark://master:7077
# spark.eventLog.enabled true
# spark.eventLog.dir hdfs://namenode:8021/directory
# spark.serializer org.apache.spark.serializer.KryoSerializer
# spark.driver.memory 5g
# spark.executor.extraJavaOptions -XX:+PrintGCDetails -Dkey=value -Dnumbers="one two three"
spark.eventLog.enabled true
spark.eventLog.dir hdfs://spark/sparklog
MasterArguments
接着Master中,MasterArguments方法这里传入了spark-class传入的参数,及默认配置conf,将这些配置进行合并。
private[master] class MasterArguments(args: Array[String], conf: SparkConf) extends Logging {
// 这里获取了hostname,及默认定义port7077,webuiport8080
var host = Utils.localHostName()
var port = 7077
var webUiPort = 8080
var propertiesFile: String = null
// Check for settings in environment variables
// spark-env.sh配置的参数
// 通过load-spark-env.sh导入到环境变量中,在这里会加载
// 加载环境变量中的配置,获取hostname,如果设置了IP,会提示使用hostname
if (System.getenv("SPARK_MASTER_IP") != null) {
logWarning("SPARK_MASTER_IP is deprecated, please use SPARK_MASTER_HOST")
host = System.getenv("SPARK_MASTER_IP")
}
if (System.getenv("