从spark架构中透视job
本博文的主要内容如下:
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。
- root@Worker1:~#jps
- 3920 Worker
- 3244 DataNode
- 2565 jps
- 6455 CoarseGrainedExecutorBacken
采用Client的方式提交应用程序,让driver运行在Client的机器上,也可以采用Cluster的方式提交到集群中,使用spark-shell运行程序会在Worker上多了进程CoarseGrainedExecutorBackend进程,默认情况下Worker节点为程序分配一个Executor,而CoarseGrainedExecutorBackend进程里有Executor,Executor会通过并发线程池并发执行的方式执行Task。
- 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中):
- 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的时候,不传入第二个参数,即不指定作业运行的并行度,分别运行:
- scala>val cached = sc.TextFile("/library/wordCount/input/Data").flatMap(_.split("")).map(word => (word,1)).reduceByKey(_+_).map(pair => (pair._2 , pair._1)).cache
- 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的更多相关文章
- Spark 概念学习系列之从spark架构中透视job(十六)
本博文的主要内容如下: 1.通过案例观察Spark架构 2.手动绘制Spark内部架构 3.Spark Job的逻辑视图解析 4.Spark Job的物理视图解析 1.通过案例观察Spark架构 s ...
- [Spark]Spark章1 Spark架构浅析
Spark架构 Spark架构采用了分布式计算中的Master-Slave模型.集群中运行Master进程的节点称为Master,同样,集群中含有Worker进程的节点为Slave.Master负责控 ...
- 把传统的基于sql的企业信息中心迁移到spark 架构应该考虑的几点思考...[修改中]
把传统的基于sql的企业信息中心迁移到spark 架构应该考虑的几点 * 理由: 赶时髦, 这还不够大条么? > 数据都设计为NO-SQL模式, 只有需要search的才建立2级索引. 就可以 ...
- Spark核心技术原理透视一(Spark运行原理)
在大数据领域,只有深挖数据科学领域,走在学术前沿,才能在底层算法和模型方面走在前面,从而占据领先地位. Spark的这种学术基因,使得它从一开始就在大数据领域建立了一定优势.无论是性能,还是方案的统一 ...
- Spark 架构
本文转之Pivotal的一个工程师的博客.觉得极好. 作者本人经常在StackOverflow上回答一个关系Spark架构的问题,发现整个互联网都没有一篇文章能对Spark总体架构进行很好的描述, ...
- [Spark性能调优] 第四章 : Spark Shuffle 中 JVM 内存使用及配置内幕详情
本课主题 JVM 內存使用架构剖析 Spark 1.6.x 和 Spark 2.x 的 JVM 剖析 Spark 1.6.x 以前 on Yarn 计算内存使用案例 Spark Unified Mem ...
- GC调优在Spark应用中的实践(转载)
Spark是时下非常热门的大数据计算框架,以其卓越的性能优势.独特的架构.易用的用户接口和丰富的分析计算库,正在工业界获得越来越广泛的应用.与Hadoop.HBase生态圈的众多项目一样,Spark的 ...
- 大数据 Spark 架构
一.Spark的产生背景起源 1.spark特点 1.1轻量级快速处理 Saprk允许传统的hadoop集群中的应用程序在内存中已100倍的速度运行即使在磁盘上也比传统的hadoop快10倍,Spar ...
- Spark架构
Spark架构 为了更好地理解调度,我们先来鸟瞰一下集群模式下的Spark程序运行架构图. 1. Driver Program 用户编写的Spark程序称为Driver Progr ...
随机推荐
- C++专题 - Qt是什么
Qt是一个1991年由奇趣科技开发的跨平台C++图形用户界面应用程序开发框架.它既可以开发GUI程式,也可用于开发非GUI程式,比如控制台工具和服务器.Qt是面向对象的框架,使用特殊的代码生成扩展(称 ...
- Codeforces 551D GukiZ and Binary Operations(矩阵快速幂)
Problem D. GukiZ and Binary Operations Solution 一位一位考虑,就是求一个二进制序列有连续的1的种类数和没有连续的1的种类数. 没有连续的1的二进制序列的 ...
- Android Studio中JNI -- 1 -- 配置方法
1.配置NDK 1.1 下载NDK Android Studio 1.2 配 android-ndk-r10e,不同版本的Studio需要配置不同的ndk,下载完成后,随便解压放至某个文件目录下 1. ...
- android入门到熟练(二)----活动
1.活动创建对于每一个后端java类(继承至Activity或者ActionBarActivity)代码都有一个方法需要被重写[onCreate], 在此方法中可以加载界面资源文件或者绑定元素事件. ...
- jquery 左侧展开栏目
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...
- sass学习--什么是sass
1.预备知识--什么是 CSS 预处理器 CSS 预处理器定义了一种新的语言,其基本思想是,用一种专门的编程语言,为 CSS 增加了一些编程的特性,将 CSS 作为目标生成文件,然后开发者就只要使用这 ...
- 安装ImageMagick扩展出现configure: error: not found. Please provide a path to MagickWand-config or Wand- config program
安装ImageMagick扩展报错: checking ImageMagick MagickWand API configuration program... checking Testing /u ...
- ThinkPHP Uploadify 图片上载
从官方网站下载的Uploadify最新版本:http://www.uploadify.com/download/ jQuery库是1.7.1版本. 下载好的Uploadify目录下面的文件有: 用到的 ...
- 基于Lua的清除类游戏算法
最近在开发游戏,用Lua语言.习惯了其它的语言,然后对Lua的一些语法很不习惯. 比如table的元素个数的取值,比switch语句等等. 不过没有办法,还是要运用Lua来写游戏的.看来学C++还真的 ...
- crontab 基本用法
crontab格式:第1列分钟1-59第2列小时1-23(0表示子夜)第3列日1-31第4列月1-12第5列星期0-6(0表示星期天)第6列要运行的命令 还可以用一些特殊符号: *: 表示任何时刻 , ...