本博文的主要内容如下:

  1、通过案例观察Spark架构

  2、手动绘制Spark内部架构

  3、Spark Job的逻辑视图解析

  4、Spark Job的物理视图解析 

 1、通过案例观察Spark架构

  spark-shell中,默认情况下,没有任何的Job。

 

  从Master角度讲:

    1、管理CPU、MEM等资源(也考虑网络)

   2、接收Driver端提交作业的请求,并为其分配资源(APPid等)

    注:spark默认是粗粒度,即spark作业提交的时候就会为我们作业分配资源,后续运行的过程中一般使用已分配的资源,除非资源发生异常需要重新分配。

 从Worker角度讲:

     Worker进程负责当前worker节点上的资源的使用。从分布式的节点架构讲Spark是Master/Slave分布式的,从作业的运行架构来讲主要分为Driver和众多的Worker,而从集群静态部署来讲分为Master和Worker。

              

                      图1 Spark逻辑执行

  

运行作业

  在spark的安装目录下的bin下,  执行 ./spark-shell --master spark://Master:7077

  此时web控制台http://Master:8080,多了一个Running Applications ,该Application有Master分配的ApplicationId和由Master的分配的资源(MEM、CPU的Cores等),而分配的Cores的个数和MEM在spark.env.sh中做了配置,Spark-shell中默认情况下没有任何的job,但是在Standalone模式中默认为粗粒度的资源分配模式,提交应用程序后,Master已经进行了粗粒度的资源分配。

                    图2 作业运行job视图

  从图2看出在作业运行的端口中可以看出Cores是32,Mem是4G是在Spark-env.sh中配置的,standalone模式spark-shell只是提交了一个程序,没有做任何事。默认情况下每个Worker上启动一个ExecutorBackend进程,一共有5个Executor。driver驱动整个应用程序的运行,一个Worker上可以配置多个ExecutorBackend进程,例如在只有一个Executor的时候,CPU利用率不高的情况,只有应用程序关闭Executor线程池才会stop。

应用程序在提交的时候会进行注册并由Master分配id和计算资源,无论一个应用程序中有多少的Action导致的作业在运行,也不会产生资源冲突的情况,因为作业运行的资源实际上是在粗粒度的方式下在程序注册的时候分配好的,多个job可以采取资源复用和排队执行的方式运行完应用程序。

默认的资源分配方式在每个Worker上启动一个ExecutorBackend进程,且默认情况下会最大的占用CPU和MEM,若不加限制,集群上除了Spark还有其他程序的话,Spark运行就会占用最大的资源,给人一种Spark很占内存的感觉,若有多套计算框架,就需要资源管理器yarn或者mesos。

  1. root@Worker1:~#jps
  2. 3920 Worker
  3. 3244 DataNode
  4. 2565 jps
  5. 6455 CoarseGrainedExecutorBacken

  

  采用Client的方式提交应用程序,让driver运行在Client的机器上,也可以采用Cluster的方式提交到集群中,使用spark-shell运行程序会在Worker上多了进程CoarseGrainedExecutorBackend进程,默认情况下Worker节点为程序分配一个Executor,而CoarseGrainedExecutorBackend进程里有Executor,Executor会通过并发线程池并发执行的方式执行Task。

  1. scala> sc.TextFile("/library/wordCount/input/Data").flatMap(_.split("")).map(word => (word,1)).reduceByKey(_+_,1).map(pair => (pair._2 , pair._1)).sortByKey(false).map(pair = > (pair._2,pair._1)).collect

  运行程序,广告点击排名,在ReduceByKey(_+_,1)进行了全局单词的排序,然后在ReduceByKey中指定并行度为1,因为只有一个作业collect,DAG如下:

                      

                      图3 DAG视图

  

  从上面运行的job可以看出一个job产生了3个stage(数据在Stage内部是pipeline流过去的,依次是HadoopRDD、MapPartitionRDD、MapPartitionRDD、ShuffledRDD...),两个shuffledRDD,因为shuffledRDD是宽依赖(每个父RDD都被子RDD使用),因为遇到宽依赖就断开,遇到窄依赖就把当前的RDD加入该Stage中,所以形成三个stage。

             

                                                    图4

  从Stage中可以看出,一共有88个Task,因为这里有88个文件且每个文件大小小于HDFS默认的文件块BLOCK大小128MB,每个文件就是一个Partition,共有88个Partitions,而默认情况下一个Task对应执行一个Partition,所以就有88个Task,而每个Task都运行在Executor中,并发复用执行。每个Worker运行多少个Task,主要由于数据本地行,数据在哪尽量在哪儿排队并发运行,以此减少网络传输IO,减少通信频率。

                                图5

  可以从图5看出一共有4个Executor,每个Worker上一个Executor进程,因为默认情况下每个Worker上启动一个Executor进程(一个CoarseGrainedExecutorBackend进程一一对应一个Executor进程,而CoarseGrainedExecutorBackend是进程级别的,Executor是计算资源级别的,因为其内部有线程池),并最大化利用当前Worker上的内存和CPU,这点前面已经提到,并且每个Executor运行不同个数的Task。

需要注意的是:一次性最多在Executor中能运行多少个并发的任务task取决于当前节点Executor中Cores数量,在实际运行的时候哪个task执行完成,就会将资源回收到线程池中进行覆用,对于一次没法全部运行的任务,就会形成task排队的情况,为了应对这种情况,优化的方法(避免oom),指定多个Executor线程池,增加分片数量,每个分片中的数据就小,所以减少OOM情况,获取更多的MEM和资源,但前提是我们的Spark运行在拥有其他大数据框架的集群中。

下面运行有Cache的情况(Cache后不同有算子,Cache后Storage中):

  1. scala>val cached = sc.TextFile("/library/wordCount/input/Data").flatMap(_.split("")).map(word => (word,1)).reduceByKey(_+_,1).map(pair => (pair._2 , pair._1)).cache

运行完成后产生一个新的job

                                图 6 Storage视图

  从图6看出,由于进行了Cache操作,所以讲ShuffledRDD Cache到了内存中,且只有一个副本,因为数据不足128MB,所以只有一个Partition,对应一个Task,这里Executor在Worker2上,那么作业运行在Worker2上,充分说明了运行任务的时候基于数据本地性。

下面测试在ReduceByKey的时候,不传入第二个参数,即不指定作业运行的并行度,分别运行:

  1. scala>val cached = sc.TextFile("/library/wordCount/input/Data").flatMap(_.split("")).map(word => (word,1)).reduceByKey(_+_).map(pair => (pair._2 , pair._1)).cache
  2. scala>cached.map(pair = > (pair._2,pair._1)).collect

             

                            图7 作业运行DAG视图

  从图7 反应的Stage的DAG可以看出Stage8已经kipped了,是Application内部进行的优化,查看job得知本次作业运行产生了88个并行度,即88个Partition,因为不指定并行度的话,作业会继承并行度。

注:如果我们的Spark集群只是作为唯一的计算框架,没有其他计算框架,为了应对oom,需要增加分片数量,每个分片运行的数据减小。

任务在运行前具体分配给谁主要取决于数据本地性(有些机器分配的多,也有些分配的少)!

  

 2、手动绘制Spark内部架构

    无

  3、Spark Job的逻辑视图解析

                                          图8 Spark执行逻辑图

  

(Worker NODE上是Worker进程,其中有Executor Process句柄,管理当前节点上的计算资源接受Master的管理)

从总体而言,spark在集群启动的时候,有个全局的资源管理器Master,负责整个集群资源的管理以及接受程序提交并为程序分配资源,而每个Worker节点上都一个Worker process来管理当前机器上的计算资源,当应用程序提交的时候,Master就会为我们提交的应用程序在每个节点上默认分配一个CorseGrainedExecutorBackend进程,该进程默认情况下载不对MEN和CPU进行限制,会最大化的应用当前机器的MEN和CPU,当Driver实例化没有问题的时候,Driver本身会进行作业的调度来驱动CorseGrainedExecutorBackend中的Executor中的线程,来具体并发执行task,这也是Spark并发执行的过程。

而从CorseGrainedExecutorBackend的角度来看是Worker Process来管理当前节点上的MEM 和CPU,但是真正管理资源的是Master,Worker Process只是走个形式,因为我们的CorseGrainedExecutorBackend进程是被Worker Process分配的,实质上是通过Master来管理Worker节点的资源。

每个Worker上包含一个或者多个ExecutorBackend进程,而每个ExecutorBackend中包含一个Executor对象,该对象拥有一个线程池,而每个线程又可以覆用多个Task任务。

从DAG逻辑角度来看数据在Stage内部是pipeline流过去的,因为有两次ShuffledRDD,所以job被划分成3个Stage。

从Hadoop的MapReduce角度看stage0上stage1的mapper;而stage1上stage0 的mapper;stage1上stage2 的mapper;而stage2上stage1 的mapper,我们可以将Spark看做一个MapReduce的更加具体的实现。

扩充:

a)Application中由于不同的Action产生若干job;

b)每个Job中都会至少有一个Stage;

c)每个Stage内部的TaskSet一定是在Executor中执行的。

 

 4、Spark Job的物理视图解析 

      无

感谢下面的博主:

http://bbs.pinggu.org/thread-4631944-1-1.html  

DT大数据梦工厂联系方式:
新浪微博:www.weibo.com/ilovepains/
微信公众号:DT_Spark
博客:http://.blog.sina.com.cn/ilovepains
TEL:18610086859
Email:18610086859@vip.126.com

从spark架构中透视job的更多相关文章

  1. Spark 概念学习系列之从spark架构中透视job(十六)

    本博文的主要内容如下:  1.通过案例观察Spark架构 2.手动绘制Spark内部架构 3.Spark Job的逻辑视图解析 4.Spark Job的物理视图解析 1.通过案例观察Spark架构 s ...

  2. [Spark]Spark章1 Spark架构浅析

    Spark架构 Spark架构采用了分布式计算中的Master-Slave模型.集群中运行Master进程的节点称为Master,同样,集群中含有Worker进程的节点为Slave.Master负责控 ...

  3. 把传统的基于sql的企业信息中心迁移到spark 架构应该考虑的几点思考...[修改中]

    把传统的基于sql的企业信息中心迁移到spark 架构应该考虑的几点 * 理由: 赶时髦,  这还不够大条么? > 数据都设计为NO-SQL模式, 只有需要search的才建立2级索引. 就可以 ...

  4. Spark核心技术原理透视一(Spark运行原理)

    在大数据领域,只有深挖数据科学领域,走在学术前沿,才能在底层算法和模型方面走在前面,从而占据领先地位. Spark的这种学术基因,使得它从一开始就在大数据领域建立了一定优势.无论是性能,还是方案的统一 ...

  5. Spark 架构

    本文转之Pivotal的一个工程师的博客.觉得极好.   作者本人经常在StackOverflow上回答一个关系Spark架构的问题,发现整个互联网都没有一篇文章能对Spark总体架构进行很好的描述, ...

  6. [Spark性能调优] 第四章 : Spark Shuffle 中 JVM 内存使用及配置内幕详情

    本课主题 JVM 內存使用架构剖析 Spark 1.6.x 和 Spark 2.x 的 JVM 剖析 Spark 1.6.x 以前 on Yarn 计算内存使用案例 Spark Unified Mem ...

  7. GC调优在Spark应用中的实践(转载)

    Spark是时下非常热门的大数据计算框架,以其卓越的性能优势.独特的架构.易用的用户接口和丰富的分析计算库,正在工业界获得越来越广泛的应用.与Hadoop.HBase生态圈的众多项目一样,Spark的 ...

  8. 大数据 Spark 架构

    一.Spark的产生背景起源 1.spark特点 1.1轻量级快速处理 Saprk允许传统的hadoop集群中的应用程序在内存中已100倍的速度运行即使在磁盘上也比传统的hadoop快10倍,Spar ...

  9. Spark架构

    Spark架构    为了更好地理解调度,我们先来鸟瞰一下集群模式下的Spark程序运行架构图. 1. Driver Program        用户编写的Spark程序称为Driver Progr ...

随机推荐

  1. 常见 PL.SQL 数据库操作

    Oracle PL/SQL 1, Alt +E 2, 默认大写功能, 解析SQL原则,Comment,UnComment. 3, 触发Trig,使用Test Window. 4, Compile In ...

  2. cocos2d-x Android 环境搭建问题汇总

    初次接触Cocos2d-x,准备搭建一个hello world的Android环境,问题遇到很多.在此记录,为自己,也为大家,避免重走弯路! 具体的环境搭建,可以参考官方的文档.在Windows7平台 ...

  3. Win32 GDI 非矩形区域剪裁,双缓冲技术

    传统的Win32通过GDI提供图形显示的功能,包括了基本的绘图功能,如画线.方块.椭圆等等,高级功能包括了多边形和Bezier的绘制.这样app就不用关心那些图形学的细节了,有点类似于UNIX上的X- ...

  4. Win32中GDI+应用(四)--- 位图的打开与显示

    显示位图,你应该使用GDI+里面的Bitmap类或者Image类,这两个类都提供了方法从硬盘上的一个文件打开文件,创建相应的内存中的位图对象的工作.然后你可以使用Graphics类的DrawImage ...

  5. ThinkPHP调试模式与日志记录

    1.可以在config.php中进行设置,默认为关闭状态. 'APP_DEBUG'   =>  true 打开\ThinkPHP\Common\debug.php文件可以查看debug的默认设置 ...

  6. Apache 支持.htaccess

    ******************************************************************************* Apache 服务器 ********* ...

  7. windows“画图”工具用法

    图片编辑工具不少,photoshop功能强大,但是并不是那么容易掌握.而且,倘若一个简单的图片处理问题就使用这么强大的工具,有点“杀鸡焉用牛刀”的意思,要知道只打开photoshop就需要一段等待时间 ...

  8. 学习Swift -- 可选链

    可空链式调用 可空链式调用是一种可以请求和调用属性.方法及下标的过程,它的可空性体现于请求或调用的目标当前可能为空(nil).如果可空的目标有值,那么调用就会成功:如果选择的目标为空(nil),那么这 ...

  9. Xcode7之后常见问题整理-b

    一.Xcode7,iOS9之后传出来的什么Xcode有鬼,被植入代码片段什么的,可以看看,了解一下http://drops.wooyun.org/news/8864 二.bitcode问题--未正确设 ...

  10. struts文件上传拦截器中参数的配置(maximumSize,allowedTypes ,allowedExtensions)问题

    <interceptor-ref name="fileUpload"> <param name="allowedTypes">image ...