容错指的是一个系统在部分模块出现故障时还能否持续的对外提供服务,一个高可用(HA)的系统应该具有很高的容错性,系统不会因为一点小的错误导致系统性能严重下降或者造成系统瘫痪。
对于一个大的集群系统来说,机器故障、网络异常等都是很常见的,其不能因为这些原因造成集群系统不能提供服务。所以像Spark这样的大型分布式计算集群提供了很多的容错机制来提高整个系统的可用性,Spark的容错机制可以通过Executor、Worker和Master的异常处理来体现,下面分别对它们进行介绍。
在Spark中,Executor的作用是:负责执行任务的运行,并把任务运行状态发给Driver。下面以独立运行模式分析Executor出现异常的情况。Executor异常容错过程图如下:
其中虚线为正常运行的通信线路,实线为异常处理步骤。
流程如下:
(1)首先看Executor的启动过程
在集群中由Master给应用程序分配运行资源后,然后在Worker中启动 ExecutorRunner ,而 ExecutorRunner根据当前的运行模式启动CoarseGrainedExecutorBackend进程,当该进程会向 Driver 发送注册Executor信息。如果注册成功,则CoarseGraineaExecutorBackend在其内部启动Executor。Executor由 ExecutorRunner进行管理,当Executor出现异常时(如所运行容器CoarseGrainedExecutorBackend进程异常退出等),由 ExecutorRunner 捕获该异常并发送 ExecutorStateChanged消息给Worker。
(2) Worker 接收到ExecutorStateChanged消息
在Worker的 handleExecutorStateChanged方法中,根据Executor 状态进行信息更新,同时把 Executor状态信息转发给Master。
(3)Master 接收到 Executor状态变化消息
如果发现Executor 出现异常退出,则调用Master. schedule方法,尝试获取可用的 Worker 节点并启动Executor,而这个Worker很可能不是失败之前运行Executor 的 Worker 节点。该尝试系统会进行10次,如果超过10次,则标记该应用运行失败并移除集群中移除该应用。这种限定失败次数是为了避免提交的应用程序存在Bug而反复提交,进而挤占集群宝贵的资源。
以独立运行模式来讨论Worker异常。Spark的 独立运行模式采用的是Master/Slave的结构,其中Slave是由Worker来担任的其在运行的时候会发送心跳给Master,让 Master 知道Worker 的实时状态。另一方面Master也会检测注册的Worker是否连接超时,因为在集群运行过程中,可能由于机器宕机或者进程被杀死等原因造成Worker进程异常退出。Worker异常容错过程图如下:
(1)Master接收Worker的心疼来监测其实时状态,同时,Master中的onStart方法中也有检测Worker超时的线程。实现代码如下:
case Heartbeat(workerId, worker) =>
idToWorker.get(workerId) match {
case Some(workerInfo) =>
workerInfo.lastHeartbeat = System.currentTimeMillis()
case None =>
if (workers.map(_.id).contains(workerId)) {
logWarning(s"Got heartbeat from unregistered worker $workerId." +
" Asking it to re-register.")
worker.send(ReconnectWorker(masterUrl))
} else {
logWarning(s"Got heartbeat from unregistered worker $workerId." +
" This worker was never registered, so ignoring the heartbeat.")
}
}
override def onStart(): Unit = {
…
checkForWorkerTimeOutTask = forwardMessageThread.scheduleAtFixedRate(new Runnable {
override def run(): Unit = Utils.tryLogNonFatalError {
self.send(CheckForWorkerTimeOut)
}
}, 0, WORKER_TIMEOUT_MS, TimeUnit.MILLISECONDS)
…
}
(2)当Worker出现超时时,Master调用timeOutDeadWorkers方法进行处理。代码实现如下:
/** Check for, and remove, any timed-out workers */
private def timeOutDeadWorkers() {
// Copy the workers into an array so we don’t modify the hashset while iterating through it
val currentTime = System.currentTimeMillis()
val toRemove = workers.filter(_.lastHeartbeat < currentTime - WORKER_TIMEOUT_MS).toArray
for (worker <- toRemove) {
自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。
深知大多数Java工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!
因此收集整理了一份《2024年Java开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Java开发知识点,真正体系化!
由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且会持续更新!
如果你觉得这些内容对你有帮助,可以扫码获取!!(备注Java获取)
最后
最后,强调几点:
- 1. 一定要谨慎对待写在简历上的东西,一定要对简历上的东西非常熟悉。因为一般情况下,面试官都是会根据你的简历来问的; 能有一个上得了台面的项目也非常重要,这很可能是面试官会大量发问的地方,所以在面试之前好好回顾一下自己所做的项目;
- 2. 和面试官聊基础知识比如设计模式的使用、多线程的使用等等,可以结合具体的项目场景或者是自己在平时是如何使用的;
- 3. 注意自己开源的Github项目,面试官可能会挖你的Github项目提问;
我个人觉得面试也像是一场全新的征程,失败和胜利都是平常之事。所以,劝各位不要因为面试失败而灰心、丧失斗志。也不要因为面试通过而沾沾自喜,等待你的将是更美好的未来,继续加油!
以上面试专题的答小编案整理成面试文档了,文档里有答案详解,以及其他一些大厂面试题目。
面试答案
《互联网大厂面试真题解析、进阶开发核心学习笔记、全套讲解视频、实战项目源码讲义》点击传送门即可获取!
W-1713289156877)]
[外链图片转存中…(img-izmzoeDY-1713289156878)]
《互联网大厂面试真题解析、进阶开发核心学习笔记、全套讲解视频、实战项目源码讲义》点击传送门即可获取!