一行Spark代码的诞生记(深度剖析Spark架构)

大家好,我是一行Spark代码,我叫小小小蕉,不知道为毛,我爸爸大蕉和我妈妈大大蕉把我生的又瘦又长。长这样。

valsssjiao =newSparkContext(newSparkConf().setAppName("sssjiao").setMaster("yarn-cluster")).parallelize(Array(""));

我真的,不知道怎么说,好长好长啊。。总有小伙伴对着我说:

问君何不乘风起     扶摇直上九万里。

说出来不怕吓着你,其实我一个字都看不懂。

作为一行普通的代码,我也开始思考码生的三大问题,我是谁,我从哪里来,要到哪里去。

我从我从哪里来,开始讲我的故事吧。

我从哪里来?

这有什么好说的,出自我爸爸大大蕉之手,就酱。

本文终。

当当当,你以为就这样结束了吗?不可能的。我长得这么细这么长,其实我是由三个部分组成的。分别是SparkConf,SparkContext,RDD[String],从代码层面来说,就是定义了一个SparkConf的配置,来生成一个SparkContext上下文,然后用这个SparkContext来对数组进行序列化,我就被产生出来啦。

但是我今天不仅仅是想介绍这么浅层的来源,毕竟爸比妈咪生得我那么辛苦是吧?

(要开始Spark on yarn的深度剖析了)

大大蕉:yarn兄,我要生一个儿子,oh不我要产生一个Spark任务了,能帮忙拨                   点行政资源不?

yarn    :啥玩意,你想干啥?要尊贵的cluster模式还是平民的client模式?

大大蕉:这两个有啥差别?我头胎。

yarn    :client就你用你自己粗糙的Driver,cluster模式就我给你分配一个高配置又漂亮的Driver。

大大蕉:那行,给我来个尊贵的cluster吧。

yarn    :等着。

yarn    :歪,ResourceManager吗(管资源的,下面简称RM)?你那边不是在管资源吗?咱这有货吗?赶紧给我空运一个高配的机器,嗯对,用来跑Driver和ApplicationMaster的,嗯对对对,我们这边有人快生了。对,急急急,这辈子就这要一次最急。

RM    :知道了(一脸嫌弃懒洋洋)。

过了0.00001ms,对于CPU来说过了好久了

RM    :NodeManage(每台机器的管家,下面简称NM),歪,根据记录你那里的配置恰好够用,你那里的Container1容器我征用了,就这样。

NM    :我R。。。

RM    :yarn老哥,给你那个名字为container-1的容器吧,他的地址和配置信息(CPU,内存)在这,你收好了。

yarn的最小分配单位为Container

yarn    :好的,非常感谢,后面有事情还麻烦你。

yarn    :大大蕉吗?Container拿到了,就是Container1,自己去看看怎么生吧。

大大蕉:好的。掰。

大大蕉:(自言自语)根据说明书,先启动一个ApplicationMaster,名字叫做sssjiao,用来管理这个Job和Container。再先启动一个Driver,来管理DAGScheduler(有向无环图管理)和TaskScheduler(任务调度管理),BlockManagerMaster(数据块管理的Master)。咦,那我去哪跑任务呢?还差一些Worker工作站啊。

Spark将一个大的任务拆成一个有向无环图,来表示依赖关系。

大大蕉:歪。yarn吗?嗯是我。我这好像还差点东西啊。。我还需要一些Container来做我的Worker啊,不然我儿子生完往哪放啊?

yarn    :知道了知道了,不会一次说完吗?真讨厌。

大大蕉:我。。。我™也不知道需要这个啊。

yarn    :歪。RM吗?嗯又是我。我需要一批Container。嗯对高配那种。对,急急急,这辈子就这一次最急。

RM      :知道了。(不耐烦)

RM      :NM-A,NM-B,NM-C,NM-D,你们几个的资源我都征用了。

NM界一脸懵逼,都感觉自己被抢劫了。。

RM      :歪,yarn老哥吗?资源都ok了。ContainerA,ContainerB,ContainerC,ContainerD。

yarn    :好嘞。

yarn    :大大蕉。资源拿到了,信息我装在信封里了,你拿好吧。

大大蕉:嗯,我还想问一下,后面的(电话那头传来嘟嘟嘟挂断的声音)。步、骤、要、怎、么、走。算了还是自己看说明书吧。

首先在Container里面启动一个或者多个Executor,然后启动一些jvm和BlockManager。好了现在Driver、Master和Worker都有了,完事具备,只欠东西南北风了。

到这里,SparkContext算是初始化完了。

大大蕉抓着头发,一脸茫然地看着面前这堆玩意,要怎么玩。。。

诶,再看看说明书吧,看看有没有说怎么玩。(大蕉自言自语道)

突然空气中响起了旁白:切分、分配、切分、分配。

对!这个job可以先用DAGScheduler进行stage切分。

切分完然后用TaskScheduler进行任务调度分配。所以一个Job就被切分成很多个stage,封装成很多个TaskSet,然后每次Executor来请求任务的时候,就给他们分配一个,所有的Executor执行完成后又向TaskScheduler报告进度。

Task失败了?报告TaskScheduler。从头开始重新跑。

Task太慢了?TaskSchduler找多一个Executor并行跑,谁先跑完就用谁(好残忍)

Stage挂了?TaskScheduler报告DAGScheduler重新进行Stage拆分,看看是从当前开始重跑还是要用从父stage重跑。

好了到现在,小小小蕉我,还没有被产生出来。。

然后SparkContext就我的前辈Array("")进行序列化,然后根据key,也就是每个字符串进行分区,分区完之后把分区信息和对应的Executor保存起来。然后呢根据分区信息把数据发送到Executor那边去。所以我的本体RDD是在Driver的,但是我被分成很多份很小份很小份放在Exector里面的。

我是谁?

我是一个RDD。全名RDD(Reilient Distributed DataSets)弹性分布式数据集。RDD的具体描述在这里边。

小飞象小飞象飞吖飞No.6

我要到哪里去?

我后面的任务就是进行具体程序的执行,一个job一个job,一个stage一个stage。

这里再深入,就是从编译完的.class文件,用JVM的ClassLoader类加载器,加载完变成一个真正的类,然后再又JVM编译成机器码,在堆里开辟一点内存初始化一个String对象,在栈里开辟一点内存初始化一个指针。

然而跑完之后呢,我又将何去何从呢?

然后10M以下的就直接放在结果返回给TaskScheduler啦。

如果在10M以上的,就放到某个BlockManage,只返回BlockId了。

通知TaskScheduler说跑完啦。

然后TaskScheduler就通知DAGScheduler说跑完啦。

然后DAGScheduler就通知SparkContext说跑完啦。

然后SparkContext就通知Driver跑完啦。

然后SparkContext就准备要stop了。

大大蕉    :歪,yarn吗?我儿子生完了,资源都还给你把。

yarn        :好。

yarn        :歪。RM吗?刚刚申请的资源用完了,你把它们标记为可用把。

虚拟机    :这行又瘦又长的叫sssjiao的代码是谁啊。。好像被人丢在这了,诶当垃圾回收了吧,然后就给小小小蕉脸上盖上了一个待回收的印子♻️。

过了不久,小小小蕉就被GC(Garbage Collection)回收了,但是它脸上洋溢着笑容,它,是快乐的。

这就是小小小蕉快快乐乐的一生。

附上之前的好几篇Spark文章哈。

小飞象小飞象飞吖飞No.6

Spark你一定学得会(一)No.7

Spark你一定学得会(二)No.8

Spark你一定学得会(三)No.10

如果觉得还不错呢,就帮忙点赞评论分享一下啦,是对我最大的支持,感谢各位读者小伙伴,哇咔咔(づ ̄3 ̄)づ╭❤~。


微信公众号:一名叫大蕉的程序员

你可能感兴趣的:(一行Spark代码的诞生记(深度剖析Spark架构))