在Spark Standalone中我们所谓的Client,它的任务其实是由AppClient和DriverClient共同完成的。AppClient是一个允许app(Client)和Spark集群通信的中间人,接受master URL、app的信息、一个集群事件的监听器以及事件监听的回调函数,主要和Master交互App相关的信息,DriverClient主要用于和Master交互Driver相关的信息,比如启动、停止及运行状况等,本篇先介绍AppClient。

1.AppClient类主要字段、方法如下:


由上图我们可以知道,ClientEndpoint是作为AppClient的一个私有类存在的。
(1)stop方法如下所示,主要用于向master发送消息,停止并注销app。

def stop() {
if (endpoint != null) {
try {
//返回Rpc ask的超时时间120s
val timeout = RpcUtils.askRpcTimeout(conf)
//client向master发送注销app的信息,在120s内如果不响应,那么将抛RpcTimeoutException
timeout.awaitResult(endpoint.askBoolean)
} catch {
case e: TimeoutException =>
logInfo("Stop request to Master timed out; it may already be shut down.")
}
endpoint = null
}
}

下面我们重点看ClientEndpoint,它是线程安全的。

2.ClientEndpoint

2.1属性

(1)//设置一个boolean标识,用于避免多次调用listener.disconnected()
private var alreadyDisconnected = false
(2)//app向master申请注册的线程池,因为被maser注册是一个阻塞操作,所以线程池的个数是"masterRpcAddresses.size",这样app就能同时被所有的master注册
private val registerMasterThreadPool = new ThreadPoolExecutor(
0,
masterRpcAddresses.size, // Make sure we can register with all masters at the same time
60L, TimeUnit.SECONDS,
new SynchronousQueueRunnable,
ThreadUtils.namedThreadFactory("appclient-register-master-threadpool"))
(3)一个守护单线程用于申请注册操作
private val registrationRetryThread =
ThreadUtils.newDaemonSingleThreadScheduledExecutor("appclient-registration-retry-thread")

2.2方法

(1)构造函数为ClientEndpoint的主构造器。
(2)onStart方法,用于将App注册到所有的Master上

override def onStart(): Unit = {
try {
//“1”表示第几次注册,最大次数不超过3次,第n次申请注册到master上
registerWithMaster(1)详见下①
} catch {
case e: Exception =>
logWarning("Failed to connect to master", e)
//监听器停止并将boolen状态标识设置为true
markDisconnected()
//停止rpcendpoint
stop()
}
}

①registerWithMaster方法如下,用于异步注册到所有的master上,如果没有超过再次注册的次数(3次),那么每20s将会重新调用该方法申请注册,如果注册成功,所有的调用work和futures将会被取消。

private def registerWithMaster(nthRetry: Int) {
registerMasterFutures = tryRegisterAllMasters()
registrationRetryTimer = registrationRetryThread.scheduleAtFixedRate(new Runnable {
override def run(): Unit = {
Utils.tryOrExit {
if (registered) {
registerMasterFutures.foreach(.cancel(true))
registerMasterThreadPool.shutdownNow()
} else if (nthRetry >= REGISTRATION_RETRIES) {
markDead("All masters are unresponsive! Giving up.")
} else {
registerMasterFutures.foreach(
.cancel(true))
registerWithMaster(nthRetry + 1)
}
}
}
}, REGISTRATION_TIMEOUT_SECONDS, REGISTRATION_TIMEOUT_SECONDS, TimeUnit.SECONDS)
}

(3)onstop方法如下,释放资源。

override def onStop(): Unit = {
if (registrationRetryTimer != null) {
registrationRetryTimer.cancel(true)
}
registrationRetryThread.shutdownNow()
registerMasterFutures.foreach(_.cancel(true))
registerMasterThreadPool.shutdownNow()
}

(4)receive方法,receive接受到的消息分为5种,分别为

  • (1)app被master成功注册,并将注册成功的app添加到监听器中

    case RegisteredApplication(appId_, masterRef) => appId = appId_ registered = true master = Some(masterRef) listener.connected(appId)
  • (2)移除app,停止rpcendpoint

    case ApplicationRemoved(message) => markDead("Master removed our application: %s".format(message))
    stop()
  • (3)向master申请为app添加executor,并添加到监听器中

    case ExecutorAdded(id: Int, workerId: String, hostPort: String, cores: Int, memory: Int) =>val fullId = appId + "/" + id
    logInfo("Executor added: %s on %s (%s) with %d cores".format(fullId, workerId, hostPort, cores))
    sendToMaster(ExecutorStateChanged(appId, id, ExecutorState.RUNNING, None, None))
    listener.executorAdded(fullId, workerId, hostPort, cores, memory)
  • (4)Executor的信息发生改变,记录到日志中
    case ExecutorUpdated(id, state, message, exitStatus) =>
    val fullId = appId + "/" + id
    val messageText = message.map(s => " (" + s + ")").getOrElse("")
    logInfo("Executor updated: %s is now %s%s".format(fullId, state, messageText))
    if (ExecutorState.isFinished(state)) {
    listener.executorRemoved(fullId, message.getOrElse(""), exitStatus) }
  • (5)HA机制,为app更换master

    case MasterChanged(masterRef, masterWebUiUrl) =>
    logInfo("Master has changed, new master is at " + masterRef.address.toSparkURL)
    master = Some(masterRef)
    alreadyDisconnected = false
    masterRef.send(MasterChangeAcknowledged(appId))

【原】Spark中Client源码分析(一)的更多相关文章

  1. 【原】Spark中Client源码分析(二)

    继续前一篇的内容.前一篇内容为: Spark中Client源码分析(一)http://www.cnblogs.com/yourarebest/p/5313006.html DriverClient中的 ...

  2. 【原】Spark中Master源码分析(二)

    继续上一篇的内容.上一篇的内容为: Spark中Master源码分析(一) http://www.cnblogs.com/yourarebest/p/5312965.html 4.receive方法, ...

  3. 【原】 Spark中Worker源码分析(二)

    继续前一篇的内容.前一篇内容为: Spark中Worker源码分析(一)http://www.cnblogs.com/yourarebest/p/5300202.html 4.receive方法, r ...

  4. 【原】Spark中Master源码分析(一)

    Master作为集群的Manager,对于集群的健壮运行发挥着十分重要的作用.下面,我们一起了解一下Master是听从Client(Leader)的号召,如何管理好Worker的吧. 1.家当(静态属 ...

  5. Spark中决策树源码分析

    1.Example 使用Spark MLlib中决策树分类器API,训练出一个决策树模型,使用Python开发. """ Decision Tree Classifica ...

  6. 【原】 Spark中Worker源码分析(一)

    Worker作为对于Spark集群的健壮运行起着举足轻重的作用,作为Master的奴隶,每15s向Master告诉自己还活着,一旦主人(Master>有了任务(Application),立马交给 ...

  7. Spark Scheduler模块源码分析之TaskScheduler和SchedulerBackend

    本文是Scheduler模块源码分析的第二篇,第一篇Spark Scheduler模块源码分析之DAGScheduler主要分析了DAGScheduler.本文接下来结合Spark-1.6.0的源码继 ...

  8. Spark Scheduler模块源码分析之DAGScheduler

    本文主要结合Spark-1.6.0的源码,对Spark中任务调度模块的执行过程进行分析.Spark Application在遇到Action操作时才会真正的提交任务并进行计算.这时Spark会根据Ac ...

  9. Spark RPC框架源码分析(一)简述

    Spark RPC系列: Spark RPC框架源码分析(一)运行时序 Spark RPC框架源码分析(二)运行时序 Spark RPC框架源码分析(三)运行时序 一. Spark rpc框架概述 S ...

随机推荐

  1. 线程池原理及创建并C++实现

    本文给出了一个通用的线程池框架,该框架将与线程执行相关的任务进行了高层次的抽象,使之与具体的执行任务无关.另外该线程池具有动态伸缩性,它能根据执行任务的轻重自动调整线程池中线程的数量.文章的最后,我们 ...

  2. 51nod贪心算法入门-----任务分配问题

    任务执行顺序 有N个任务需要执行,第i个任务计算时占R[i]个空间,而后会释放一部分,最后储存计算结果需要占据O[i]个空间(O[i] < R[i]). 分析: 可以抽象成,从一个整数开始,每次 ...

  3. Tomcat安装与配置图文教程

    安装Tomcat之前先配置JDK,JDK的JAVA_HOME变量都必须设置好,以便Tomcat找到JDK.关闭防火墙等. 一:安装版Tomcat 1. 先下载tomcat,到http://tomcat ...

  4. 【jpa】 引用包的问题

    Hibernate使用Annotation(注解)需加                         hibernate-jpa-2.0-api-1.0.0.Final.jar Hibernate3 ...

  5. 一步步学习NHibernate(8)——HQL查询(2)

    请注明转载地址:http://www.cnblogs.com/arhat 在上一章中,老魏带着大家学习了HQL语句,发现HQL语句还是非常不错的,尤其是在懒加载的时候,书写起来比较的舒服,但是这里老魏 ...

  6. Qt 5 如何修改打包好的应用程序图标

    修改的方法是:首先准备个ICO图标.例如:A.ico,网上有很多图标文件.用记事本新建个txt里面就写一行:IDI_ICON1 ICON DISCARDABLE "A.ico" 保 ...

  7. Core管道中的处理流程3

    通过重建Hosting系统理解HTTP请求在ASP.NET Core管道中的处理流程[下]:管道是如何构建起来的? 在<中篇>中,我们对管道的构成以及它对请求的处理流程进行了详细介绍,接下 ...

  8. 转 scrollLeft,scrollWidth,clientWidth,offsetWidth之完全详解

    scrollHeight: 获取对象的滚动高度. scrollLeft:设置或获取位于对象左边界和窗口中目前可见内容的最左端之间的距离 scrollTop:设置或获取位于对象最顶端和窗口中可见内容的最 ...

  9. WebService积累

    1.缺点,无法传输复杂对象:如无法序列化key/value结构的类型参数以及相关一维集合接口(Hashtable等打上标签[Serializable]即可序列化,不过继承的IDictionary并不可 ...

  10. 在C#中关于excel的导入和导出操作

    一.先来看看最常见的导入操作吧! private void Import() { //打开excel选择框 OpenFileDialog frm = new OpenFileDialog(); frm ...