本博文的主要内容如下:

  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. iOS pop使用通知传值

    iOS pop回父级页面,使用通知传值 输入所要发送的信息 ,同时将label的值通过button方法调用传递, - (IBAction)buttonClick:(id)sender { //添加 字 ...

  2. 集成支付宝报一堆warning: (arm64) /Users/scmbuild/workspace/standard-pay/.....警告问题解决办法亲测可行!

  3. angularJS广播

    控制器之间共享数据(向父级/子级控制器传递event,data),类似于service在不同的控制器中通信 html: <div ng-controller="ParentCtrl&q ...

  4. 关于Java的一道内存的题目

    import java.util.Arrays; import java.util.EmptyStackException; public class MyStack<T> { priva ...

  5. .NET开源工程推荐(Accord,AForge,Emgu CV)

         本人用C#开发了一些项目,下面的开源工程给了我很大的帮助——详细的源代码介绍加丰富的实例运用,是非常不错的学习资源,分享给大家,同时附上我的相关开发项目.    Accord.NET The ...

  6. QT UI 使一个QWidget里面的元素自动填充满本QWidget

    使一个QWidget里面的元素自动填充满本QWidget: 对象查看器,右键点击本QWidget,选择"布局",为此QWidget增加一个布局. 如果该QWidget只有一个对象, ...

  7. Memcached认知[分布式]

    Memcached是一个高性能的分布式内存对象缓存系统,用于动态Web应用以减轻数据库负载. Memcached的服务器客户端通信使用简单的基于文本行的协议. Memcached基于一个存储键/值对的 ...

  8. header("Location:login.php")

    header("Location:login.php")应该注意的几个问题  header("Location:")作为php的转向语句.其实在使用中,他有几点 ...

  9. Apache 支持PHP

    ①加载PHP模块到Apache中: LoadModule php5_module "d:\php5\php5apache2_2.dll"   ②加入识别扩展名为.php文件(也可以 ...

  10. DELPHI TMS Advanced Charts 3.8.0.3 Full Source D6-XE6 控件分享

    仅供大家学习使用,请大家支持正版!! TMS Advanced Charts 3.8.0.3 Full Source D6-XE6 该控件用来画图标,压缩包里还有FOR INTRAWEB的版本 链接: ...