Spark执行过程【源码分析+图示】——启动脚本(standalone模式)

文章目录前言1. 执行start-master.sh脚本1.1 源码分析1.2 图示2. 执行start-slaves.sh脚本2.1 源码分析2.1.1 Worker的main方法2.1.2 Worker执行onStart方法(内部发送消息去Master注册)2.1.3 Master收到RegisterWorker消息2.1.4 Worker注册成功收到RegisteredWorker消息2.1...
摘要由CSDN通过智能技术生成

前言

start-all.sh脚本:

if [ -z "${SPARK_HOME}" ]; then
  export SPARK_HOME="$(cd "`dirname "$0"`"/..; pwd)"
fi

# Load the Spark configuration
. "${SPARK_HOME}/sbin/spark-config.sh"

# Start Master
"${SPARK_HOME}/sbin"/start-master.sh

# Start Workers
"${SPARK_HOME}/sbin"/start-slaves.sh

以上的脚本会启动start-master.sh和start-slaves.sh两个脚本
其中start-master.sh启动的是“org.apache.spark.deploy.master.Master”这个类,也就是说要去执行它的main方法。而start-slaves.sh脚本是启动conf/slaves中指定的每一个slave:【./start-slave.sh spark://10.47.85.111:port】。

我们讨论Standalone集群部署模式,Master节点:Master机器;Slave节点:Slave1机器、Slave2机器。

1. 执行start-master.sh脚本

1.1 源码分析

main方法如下:

def main(argStrings: Array[String]) {
  Utils.initDaemon(log)
  val conf = new SparkConf
  val args = new MasterArguments(argStrings, conf)
  val (rpcEnv, _, _) = startRpcEnvAndEndpoint(args.host, args.port, args.webUiPort, conf)
  rpcEnv.awaitTermination()
}

其中args中的host、port是Master的地址和端口号,然后是内部的startRpcEnvAndEndpoint方法:

def startRpcEnvAndEndpoint(
    host: String,
    port: Int,
    webUiPort: Int,
    conf: SparkConf): (RpcEnv, Int, Option[Int]) = {
  val securityMgr = new SecurityManager(conf)
  val rpcEnv = RpcEnv.create(SYSTEM_NAME, host, port, conf, securityMgr)
  //构造Master时候,会初始化StandaloneRestServer(RestSubmissionServer的子类)这个Server,并执行它的start方法。
  val masterEndpoint = rpcEnv.setupEndpoint(ENDPOINT_NAME,
    new Master(rpcEnv, rpcEnv.address, webUiPort, securityMgr, conf))
  /*给Master发送BoundPortsRequest消息,构造一个BoundPortsResponse对象*/
  val portsResponse = masterEndpoint.askSync[BoundPortsResponse](BoundPortsRequest)
    //返回值
  (rpcEnv, portsResponse.webUIPort, portsResponse.restPort)
}

Master对象在被new完之后,会执行其内部的onStart方法,这里只需要知道会执行这个方法,具体原因另外解释。

val portsResponse = masterEndpoint.askSync[BoundPortsResponse](BoundPortsRequest)

表示通过Master的ref【需要注意的是这里的masterEndpoint变量其实不是RpcEndpoint类型,而是RpcEndpointRef类型的】给Master这个endpoint发送一个BoundPortsRequest类型的消息,Master是一个RpcEndpoint类型的对象,所以我们在它的receiveAndReply方法可以看到它对该类型消息的处理,如下:

case BoundPortsRequest =>
  context.reply(BoundPortsResponse(address.port, webUi.boundPort, restServerBoundPort))

可以看到这里构造了一个BoundPortsResponse类型的对象,里面有一个重要的参数restServerBoundPort,它是Master内部的一个变量,定义如下:

if (restServerEnabled) {
  val port = conf.getInt("spark.master.rest.port", 6066)
  restServer = Some(new StandaloneRestServer(address.host, port, conf, self, masterUrl))
}
restServerBoundPort = restServer.map(_.start())

这里我们就启动了这个Server(当然"spark.master.rest.enabled"参数要为true)。这个Server和我们后面说提交的时候的RestSubmissionClient是对应的。

1.2 图示

执行完Master的main方法,此时的Master机器中的进程
在这里插入图片描述

2. 执行start-slaves.sh脚本

2.1 源码分析

2.1.1 Worker的main方法

Worker中的main方法:

def main(argStrings: Array[String]) {
  Utils.initDaemon(log)
  val conf = new SparkConf
  val args = new WorkerArguments(argStrings, conf)
  val rpcEnv = startRpcEnvAndEndpoint(args.host, args.port, args.webUiPort, args.cores,
    args.memory, args.masters, args.workDir, conf = conf)
  rpcEnv.awaitTermination()
}

构造WorkerArguments对象,这个对象里面会获取机器的核心数、内存大小。接着看startRpcEnvAndEndpoint方法,如下:

def startRpcEnvAndEndpoint(
    host: String,
    port: Int,
    webUiPort: Int,
    cores: Int,
    memory: Int,
    masterUrls: Array[String],
    workDir: String,
    workerNumber: Option[Int] = None,
    conf: SparkConf = new SparkConf): RpcEnv = {

  // The LocalSparkCluster runs multiple local sparkWorkerX RPC Environments
  val systemName = SYSTEM_NAME + workerNumber.map(_.toString).getOrElse("")
  val securityMgr = new SecurityManager(conf)
  val rpcEnv = RpcEnv.create(systemName, host, port, conf, securityMgr)
  val masterAddresses = masterUrls.map(RpcAddress.fromSparkURL(_))
  rpcEnv.setupEndpoint(ENDPOINT_NAME, new Worker(rpcEnv, webUiPort, cores, memory,
    masterAddresses, ENDPOINT_NAME, workDir, conf, securityMgr))
  rpcEnv
}

这里构造了Worker对象,将其当做参数设置到rpcEnv中。

2.1.2 Worker执行onStart方法(内部发送消息去Master注册)

按照上面的说法,Worker也会执行自己的onStart方法:

override def onStart() {
...
  registerWithMaster()
...
}

我们暂时关注registerWithMaster方法:

private def registerWithMaster() {
  // onDisconnected may be triggered multiple times, so don't attempt reg
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值