1、Spark的部署图:
在基于standalone的Spark集群,Cluster Manger就是Master。
Master负责分配资源,在集群启动时,Driver向Master申请资源,Worker负责监控自己节点的内存和CPU等状况,并向Master汇报。
从资源方面,可以分为两个层面:
1)资源的管理和分配
资源的管理和分配,由Master和Worker来完成。Master给Worker分配资源,
Master时刻知道Worker的资源状况。
客户端向服务器提交作业,实际是提交给Master。
2)资源的使用
资源的使用,由Driver和Executor。程序运行时候,向Master请求资源。
2、Spark运行示意图:
一个Worker默认情况下分配一个Executor,配置时根据需要也可以配置多个Executor。一个节点,如果配置了多个Executor,那么就会涉及到性能调优。
Driver、Master、Worker、Executor,其实它就是JVM进程。
图上Worker区域用◇形状表示的是:Worker上有Executor的句柄,也就是说Worker能开对Executor进行控制,必要时可以Kill掉该进程。
从图中可以看到Driver和Executor之间画了一根线条,表明:Driver 程序运行时是直接与Executor进行交互的。
我们对图2.1进行修改,增加Spark事件流,得到下图2.2:
在Driver中,RDD首先交给DAGSchedule进行Stage的划分。
然后底层的调度器TaskScheduler就与Executor进行交互。
Driver和上图中4个Worker节点的Executor发指令,让它们在各自的线程池中运行Job。
运行时Driver能获得Executor的具体运行资源,这样Driver与Executor之间进行通信,通过网络的方式,Driver把划分好的Task传送给Executor,Task就是我们的Spark程序的业务逻辑代码。
Executor接收任务,进行反序列化,得到数据的输入和输出,在分布式集群的相同数据分片上,数据的业务逻辑一样,只是数据不一样罢了,然后由Executor的线程池负责执行。
编程的Spark程序,打包提交到Driver端,这样就构成了一个Driver,
Driver内部的调度流程,根据算子逻辑的依赖关系,DAGScheduler来划分成不同的Stage,每个Stage中的计算逻辑是一样的,只是数据分片不一样。TaskScheduler向Executor发送任务,Executor反序列化数据之后,也就得到数据的输入和输出,也就是任务的业务逻辑,Executor运行的就是我们的业务逻辑代码。
我们整个Spark应用程序,可以分成:Driver和Executor两部分。
Driver由框架直接生成;
Executor执行的才是我们的业务逻辑代码。
执行的时候,框架控制我们代码的执行。Executor需要执行的结果汇报给框架也就是Driver。
3、数据的管理
在Spark应用具体执行过程中,会涉及到数据的读取和存储。
在Executor中关于数据的管理正是Spark的精髓之一。
默认情况下,数据要写到磁盘上。
DAGScheduler划分了多个Stage,下一个Stage 会向Driver请求上一个Stage的运行结果。这就是Shuffle的过程,依赖于上一个Stage全部的结果。前面Stage的输出是后面Stage的输入。
每个数据分片都要去全部节点上找属于它的数据分片的一部分。
比如:上一个Stage有1万个数据分片,现在这个Stage有100个数据分片,那么拉取数据的过程中,整个任务就需要寻找100万次数据。
4、总结:
本课从Driver和Worker的角度,也就是资源管理和分配的角度,来讲解Master、Worker、Driver、Executor工作流程。
程序运行的时候,Driver向Master申请资源;
Master让Worker给程序分配具体的Executor。
下面就是Driver具体的调用过程:
通过DAGScheduler划分阶段,形成一系列的TaskSet,然后传给TaskScheduler,把具体的Task交给Worker节点上的Executor的线程池处理。线程池中的线程工作,通过BlockManager来读写数据。
这就是4大组件:Worker、Master、Executor、Driver之间的协同工作。