难题编者按:1.叙述工作台开发周期?2.天然资源是怎样运维的?

自动草稿

这一节他们积极探索了Spark工作台的运转操作过程,但没把整座操作过程描画,好,跟著我走吧,let you know!

自动草稿

他们先简述呵呵那个图,Driver Program是他们写的那个流程,它的核心理念是SparkContext,忆起呵呵,从api的采用视角,RDD都要透过它来赢得。

上面讲一讲它所不为知觉的另一面,它和其他模块是怎样可视化的。

Driver向Master注册登记Application操作过程

SparkContext示例化后,在外部示例化三个很关键的类,DAGScheduler和TaskScheduler。

在standalone的商业模式下,TaskScheduler的同时实现类是TaskSchedulerImpl,在调用它的这时候SparkContext会传至三个SparkDeploySchedulerBackend。

在SparkDeploySchedulerBackend的start方式里头开启了三个AppClient。

valcommand = Command(“org.apache.spark.executor.CoarseGrainedExecutorBackend”, args, sc.executorEnvs,
classPathEntries, libraryPathEntries, extraJavaOpts)valsparkHome = sc.getSparkHome()valappDesc = new ApplicationDescription(sc.appName, maxCores, sc.executorMemory, command,
sparkHome, sc.ui.appUIAddress, sc.eventLogger.map(_.logDir))
client = new AppClient(sc.env.actorSystem, masters, appDesc,this, conf)
client.start()

maxCores是由参数spark.cores.max来指定的,executorMemoy是由spark.executor.memory指定的。

AppClient开启后就会去向Master注册登记Applicatoin了,后面的操作过程我用图来表达。

自动草稿

上面的图中涉及到了三方通信,具体的操作过程如下:

1、Driver透过AppClient向Master发送了RegisterApplication消息来注册登记Application,Master收到消息后会发送RegisteredApplication通知Driver注册登记成功,Driver的接收类还是AppClient。

2、Master接受到RegisterApplication后会触发运维操作过程,在天然资源足够的情况下会向Woker和Driver分别发送LaunchExecutor、ExecutorAdded消息。

3、Worker接收到LaunchExecutor消息后,会执行消息中携带的命令,执行CoarseGrainedExecutorBackend类(图中仅以它继承的接口ExecutorBackend代替),执行完毕后会发送ExecutorStateChanged消息给Master。

4、Master接收ExecutorStateChanged后,立即发送ExecutorUpdated消息通知Driver。

5、Driver中的AppClient接收到Master发过来的ExecutorAdded和ExecutorUpdated后进行相应的处理。

6、开启后的CoarseGrainedExecutorBackend会向Driver发送RegisterExecutor消息。

7、Driver中的SparkDeploySchedulerBackend(具体代码在CoarseGrainedSchedulerBackend里头)接收到RegisterExecutor消息,回复注册登记成功的消息RegisteredExecutor给ExecutorBackend,并且立马准备给它发送任务。

8、CoarseGrainedExecutorBackend接收到RegisteredExecutor消息后,示例化三个Executor等待任务的到来。

1、天然资源的运维

好,在他们讲完了整座注册登记Application的通信操作过程后,其中三个比较关键的地方是它的运维这块,它是怎么运维的?这也是我在前面为什么那么强调maxCores和executorMemoy的原因。

1、先运维Driver,再运维Application。

2、它的运维Application的方式是先进先出,所以就不要奇怪为什么你的App总得不到运维了,就像去北京的医院看病,去晚了号就没了,是三个道理。

3、Executor的分配方式有两种,一种是倾向于把任务分散在多个节点上,一种是在尽量少的节点上运转,由参数spark.deploy.spreadOut参数来决定的,默认是true,把任务分散到多个节点上。

遍历所有等待的Application,给它分配Executor运转的Worker,默认分配方式如下:

1、先从workers当中选出内存大于executorMemoy的worker,并且按照空闲cpu数从大到小的顺序来排序。

2、遍历worker,从可用的worker分配需要的cpu数,每个worker提供三个cpu核心理念,直到cpu数不足或者maxCores分配完毕。

3、给选出来的worker发送任务,让它们开启Executor,每个Executor占用的内存是他们设定的executorMemoy。

天然资源运维的操作过程大体是这样的,说到这里有些童鞋在有点儿疑惑了,那他们任务运维里头FIFO/FAIR运维是在哪里用的?任务运维器运维的不是Application,而是你的代码里头被解析出来的所有Task,这在上一节当中有提到。

基于那个原因,在共用SparkContext的情况下,比如Shark、JobServer什么的,任务运维器的作用才会明显。

2、Driver向Executor发布Task操作过程

上面他们讲一讲Driver向Executor发布Task操作过程,这在上一节是讲过的,现在把图给大家放出来了。

自动草稿

1、Driver流程的代码运转到action操作,触发了SparkContext的runJob方式。

2、SparkContext比较懒,转手就交给DAGScheduler。

3、DAGScheduler把Job划分stage,然后把stage转化为相应的Tasks,把Tasks交给TaskScheduler。

4、透过TaskScheduler把Tasks添加到任务队列当中,转手就交给SchedulerBackend了。

5、运维器给Task分配执行Executor,ExecutorBackend负责执行Task了。

补充:ExecutorBackend执行Task,是透过它外部的Executor来执行的,Executor外部有个线程池,new了三个TaskRunner交给线程池了。

3、Task状态更新

Task执行是透过TaskRunner来运转,它需要透过ExecutorBackend和Driver通信,通信消息是StatusUpdate:

1、Task运转之前,告诉Driver当前Task的状态为TaskState.RUNNING。

2、Task运转后,告诉Driver当前Task的状态为TaskState.FINISHED,并返回计算结果。

3、如果Task运转操作过程中发生错误,告诉Driver当前Task的状态为TaskState.FAILED,并返回错误原因。

4、如果Task在中途被Kill掉了,告诉Driver当前Task的状态为TaskState.FAILED。

上面讲的是运转成功的状态,具体操作过程以文字为主。

自动草稿

1、Task运转结束后,调用ExecutorBackend的statusUpdate方式,把结果返回。结果超过10M,就把结果保存在blockManager处,返回blockId,需要的这时候透过blockId到blockManager认领。

2、ExecutorBackend直接向Driver发送StatusUpdate返回Task的信息。

3、Driver(这里具体指的是SchedulerBackend)接收到StatusUpdate消息后,调用TaskScheduler的statusUpdate方式,然后准备给ExecutorBackend发送下一批Task。

4、TaskScheduler透过TaskId找到管理那个Task的TaskSetManager(负责管理一批Task的类),从TaskSetManager里头删掉那个Task,并把Task插入到TaskResultGetter(负责获取Task结果的类)的成功队列里。

5、TaskResultGetter获取到结果后,调用TaskScheduler的handleSuccessfulTask方式把结果返回。

6、TaskScheduler调用TaskSetManager的handleSuccessfulTask方式,处理成功的Task。

7、TaskSetManager调用DAGScheduler的taskEnded方式,告诉DAGScheduler那个Task运转结束了,如果那个这时候Task全部成功了,就会结束TaskSetManager。

8、DAGScheduler在taskEnded方式里触发CompletionEvent事件,CompletionEvent分ResultTask和ShuffleMapTask来处理。

1)ResultTask:

job的numFinished加1,如果numFinished等于它的分片数,则表示任务该Stage结束,标记那个Stage为结束,最后调用JobListener(具体同时实现在JobWaiter)的taskSucceeded方式,把结果交给resultHandler(经过包装的自己写的那个匿名函数)处理,如果完成的Task数量等于总任务数,任务退出。

2)ShuffleMapTask:

(1)调用Stage的addOutputLoc方式,把结果添加到Stage的outputLocs列表里。

(2)如果该Stage没有等待的Task了,就标记该Stage为结束。

(3)把Stage的outputLocs注册登记到MapOutputTracker里头,留个下三个Stage用。

(4)如果Stage的outputLocs为空,表示它的计算失败,重新提交Stage。

(5)找出下三个在等待并且没有父亲的Stage提交。

1.本站所有资源来源于用户上传和网络,如有侵权请邮件联系站长!
2.分享目的仅供大家学习和交流,您必须在下载后24小时内删除!
3.不得使用于非法商业用途,不得违反国家法律。否则后果自负!
4.本站提供的源码、模板、插件等其他资源,都不包含技术服务请大家谅解!
5.如有链接无法下载或失效,请联系管理员处理!
6.本站资源售价只是赞助,收取费用仅维持本站的日常运营所需!