Spark中Client源碼分析(二)

繼續前一篇的內容。前一篇內容為:

Spark中Client源碼分析(一)http://www.lxweimin.com/p/339fde3aff5d

DriverClient中的代碼比較簡單,它只有一個main函數,同時,和AppClient一樣,它也有一個ClientEndpoint,只是兩者的用途不一樣。

1.Client

Client中唯一的main方法如下:
<code>
def main(args: Array[String]) {
if (!sys.props.contains("SPARK_SUBMIT")) {
println("WARNING: This client is deprecated and will be removed in a future version of Spark")
println("Use ./bin/spark-submit with "--master spark://host:port"")
}
val conf = new SparkConf()
val driverArgs = new ClientArguments(args)
if (!driverArgs.logLevel.isGreaterOrEqual(Level.WARN)) {
conf.set("spark.akka.logLifecycleEvents", "true")
}
conf.set("spark.rpc.askTimeout", "10")
conf.set("akka.loglevel", driverArgs.logLevel.toString.replace("WARN", "WARNING"))
Logger.getRootLogger.setLevel(driverArgs.logLevel)
//創建一個driverClient的Rpc環境,并將得到Master和client的遠程引用
val rpcEnv =
RpcEnv.create("driverClient", Utils.localHostName(), 0, conf, new SecurityManager(conf))
val masterEndpoints = driverArgs.masters.map(RpcAddress.fromSparkURL).
map(rpcEnv.setupEndpointRef(Master.SYSTEM_NAME, _, Master.ENDPOINT_NAME))
//clientpoint
rpcEnv.setupEndpoint("client", new ClientEndpoint(rpcEnv, driverArgs, masterEndpoints, conf))
//啟動rpc環境
rpcEnv.awaitTermination()
}
</code>

2.ClientEndpoint

ClientEndPoint可以看作給Driver傳遞消息的代理
屬性簡單,直接略過。
(1)構造函數為ClientEndPoint主構造函數
(2)onstart方法如下,
<code>
override def onStart(): Unit = {
driverArgs.cmd match {
case "launch" =>
//driver包裝類,使得Worker和Driver的Rpc環境一樣,做到共進退
val mainClass = "org.apache.spark.deploy.worker.DriverWrapper"
//driver類路徑
val classPathConf = "spark.driver.extraClassPath"
val classPathEntries = sys.props.get(classPathConf).toSeq.flatMap { cp =>
cp.split(java.io.File.pathSeparator)
}
//driver庫路徑
val libraryPathConf = "spark.driver.extraLibraryPath"
val libraryPathEntries = sys.props.get(libraryPathConf).toSeq.flatMap { cp =>
cp.split(java.io.File.pathSeparator)
}
//driver Jvm參數
val extraJavaOptsConf = "spark.driver.extraJavaOptions"
val extraJavaOpts = sys.props.get(extraJavaOptsConf)
.map(Utils.splitCommandString).getOrElse(Seq.empty)
//將所有的在SparkConf中設置的屬性賦值給java options的序列
val sparkJavaOpts = Utils.sparkJavaOpts(conf)
//所有的javaOpts
val javaOpts = sparkJavaOpts ++ extraJavaOpts
val command = new Command(mainClass,
Seq("{{WORKER_URL}}", "{{USER_JAR}}", driverArgs.mainClass) ++ driverArgs.driverOptions,
sys.env, classPathEntries, libraryPathEntries, javaOpts)
//將以上所有的信息封裝在DriverDescription中
val driverDescription = new DriverDescription(
driverArgs.jarUrl,
driverArgs.memory,
driverArgs.cores,
driverArgs.supervise,
command)
//異步請求給master發送Driver的信息
ayncSendToMasterAndForwardReplySubmitDriverResponse
case "kill" =>
val driverId = driverArgs.driverId
ayncSendToMasterAndForwardReplyKillDriverResponse
}
}
</code>
(3)onstop方法簡單,略過。
(4)receive方法如下,
<code>
override def receive: PartialFunction[Any, Unit] = {
//收到master的響應回來的Driver信息,因為master是管家,Client是老板
case SubmitDriverResponse(master, success, driverId, message) =>
logInfo(message)
if (success) {
//將當前的activeMasterEndpoint設置為響應消息的master
activeMasterEndpoint = master
//找到driver的信息然后退出JVM
pollAndReportStatus(driverId.get)
} else if (!Utils.responseFromBackup(message)) {
System.exit(-1)
}
case KillDriverResponse(master, driverId, success, message) =>
logInfo(message)
if (success) {
activeMasterEndpoint = master
pollAndReportStatus(driverId),詳見下①
} else if (!Utils.responseFromBackup(message)) {
System.exit(-1)
}
}
</code>
①pollAndReportStatus方法如下,用于找到driver的信息然后退出JVM
<code>
def pollAndReportStatus(driverId: String) {
logInfo("... waiting before polling master for driver state")
Thread.sleep(5000)
logInfo("... polling master for driver state")
//master請求得到Driver的信息
val statusResponse =
activeMasterEndpoint.askWithRetryDriverStatusResponse
statusResponse.found match {
case false =>
logError(s"ERROR: Cluster master did not recognize $driverId")
System.exit(-1)
case true =>
logInfo(s"State of $driverId is ${statusResponse.state.get}")
//返回的其實是worker的信息
(statusResponse.workerId, statusResponse.workerHostPort, statusResponse.state) match {
case (Some(id), Some(hostPort), Some(DriverState.RUNNING)) =>
logInfo(s"Driver running on $hostPort ($id)")
case _ =>
}
statusResponse.exception.map { e =>
logError(s"Exception from cluster was: $e")
e.printStackTrace()
System.exit(-1)
}
System.exit(0)
}
}
</code>

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容