本节课通过二个部分阐述SparkStreaming的理解:
二、瞬间理解SparkStreaming本质
Spark源码定制,自己动手改进Spark源码,通常在电信、金融、教育、医疗、互联网等领域都有自己不同的业务,如果Sprak官方版本没有你需要的业务功能,你自己可以定制、扩展Spark的功能,满足公司的业务需要。
选择SparkStreaming框架源码研究、二次开发的原因
1、Spark起初只有Spark Core基础框架没有其他的子框架(Spark SQL、Spark Streaming、Spark ML、Spark Graphx、Spark R等),在其后加入了各种子框架来满足不同的需求。而分析这些子框架发现,选择Spark Streaming框架来研究,是最明智的选择,通过研究Spark Core上的Spark Streaming子框架,是迈向精通Spark力量源泉和解决所有问题之道。
2、Spark有很多子框架,我们选择Spark Streaming而为什么不用其他框架?
Spark SQL涉及了很多SQL语法细节的解析和优化,当然分析其解析、优化从而集中精力去研究Spark而言是一件重要的事情,但不是最重要的事情,所以Spark SQL不太适合作为具体的子框架值得我们去研究。
目前Spark R现在不成熟,支撑功能有限。
图计算,从各版本演进而言Graphx几乎没有改进,这种趋势,Graphx是不是已经发展基本到尽头了;另外图计算而言有很多数学级别的算法,而要把Spark做到极致,数学对我们来说重要,但对于研究而言不是最重要的。
Mechine Learning在封装了Vector向量、Metrics构建了众多的算法库,从而涉及了太多的数学知识,所有选择ML其实也不是太好的选择。
最后筛选出SparkStreaming子框架才是最佳的研究切入黄金点。
Spark Streaming是流式计算框架,一切数据如果和流处理不相关的话都是无效的数据。流式处理才是我们真正对大数据的初步印象,数据流进来它立即会给我们一个反馈,而不是数据挖掘、图计算。Spark强悍地方是使用流处理可以完美的结合使用机器学习的成果、图计算的成果、Spark sql或者说spark R的成果。这得益于Spark的一体化、多元化的技术架构的设计,也就是说通过一个技术堆栈可以调用技术堆栈中所有的东西,根本不需要任何的设置,这是Spark无可匹敌之处也是SparkStreaming一统天下的根源。这个时代的流处理单打独斗是不行了,SparkStreaming和多个兄弟框架联合起来,无可匹敌。如果你精通SparkStreaming的话,恭喜你,因为SparkStreaming以及背后的几个兄弟框架正好展示了Spark大数据无穷的魅力。
整个Spark的所有应用程序,哪些程序容易出问题?肯定是SparkStreaming程序是最容易出问题的,因为数据是不断流入的,ss要动态的控制数据的流入、作业的切分、数据的处理,所以最容易出问题,但最容易出问题的地方同时也是最受关注的地方也是展示大数据最神奇魅力的地方。这些特色结合的话,也是最需要技术人才的地方。关注SparkStreaming在Spark的发展,你会很清晰知道,ss跟其他自框架不同之处,ss很象SparkCore上的一个应用程序。
正如世界万物发展一样,任何技术都有其关键点或转折点,SparkStreaming运行在SparkCore上,所以很多性能调优都是建立在SparkCore上的;Spark是大数据的龙脉,SparkStreaming是龙脉的穴位。
接下来感受一下龙脉和穴位
研究SparkStreaming时,有困惑你的东西,SparkStreaming数据不断流进来,根据batchInterval时间片不断生成Job,并将Job提交集群处理,如果能清晰的看到数据的流入和数据的处理,你心里会很很踏实。
如何能清晰的看到数据的处理过程呢?只需要一个小技巧:就是把SparkStreaming中的batchInterval放的足够大,例如说从30秒调整为1分钟一次batch,或者5分钟一次batch,你会很清晰的看到整个流程序的运行过程。
以广告点击在线黑名单的过滤为例
调整时间维度:
我们把时间从30秒调至300秒:
读取SparkStreaming Socket端口的数据:
打包程序发布至集群部署环境:
检查集群进程:
通过webui检查HDFS启动情况:
启动history-server监控进程及其对应的webui监控界面:
至此整个集群环境启动一切OK。
开始启动运行SparkStreaming应用程序
启动外部请求SparkStreaming服务端口的客户端:
输入待处理的数据流:
看结果如下:
看webui控制台:
点击链接进入后产生了0~4个Job:
有意思的是SparkStreaming应用程序启动实际执行的是一个Job,但真正执行的是5个Job,其分别是Receiver Job,Output Job,Output Job,Output Job,Start Job.
第 0 个Job是不是我们逻辑中的代码?不是的,不是reduceByKey的执行结果Job,如下图:
SparkStreaming在启动的过程中会自动启动一些Job,如start操作:
SparkStreaming最像一个应用程序,就算是算一次,也执行了好几个Job,就像spark应用程序一样,可以启动不同的Job完成不同的功能。
继续看Job1:
通过Job告诉你内幕:通过追踪Receiver发现其会产生makeRDD,实际上作为整个Job独立的一个stage,只在一台机器上执行,而且执行了1.5分钟,刚才启动SparkStreaming,没有任务执行1.5分钟的,如下图:
思考一下什么东西执行了1.5分钟,而整个Job只运行了2分钟?
答案就是ReceiverTracker接收器运行的,它需要接收流入的数据。这个Job就是Receiver,并且执行了1.5分钟,而启动的Receiver就是一个Job。
结论:
SparkStreaming启动Receiver的是一个Job,在具体的Cluster的Worker上的executor中,启动Receiver是通过Job启动的。通过作业的运行时间看出,整个SparkStreaming运行的时间是2分钟,其中有个Job运行了1.5分钟,这个Job就是Receiver,其实指的是Receiver启动运行的时间,Receiver是在executor中运行的,也就是说SparkStreaming框架在启动Recevier是通过Job启动的。而且Receiver(可以启动多个receiver接收数据)就是在一个executor中运行且通过一个Task去接收我们的数据:
从这个角度讲Receiver接收数据和普通job有什么区别?没有区别。转过来给我们启发:在一个Spark application中可以启动很多的job,这些job之间可以相互配合。例如:SparkStreaming框架默认启动job给你接收数据,然后为后续的处理做准备,为你写复杂的应用程序奠定了一个良好的基础。这就是你写非常复杂的Spark应用程序的黄金切入点,复杂的程序一般都是有多个job构成的。
上图的Process_local即内存节点,SparkStreaming在默认情况下接收数据是memory_and_disk_ser_2的方式,也就是说接收的数据量比较少内存能存下的话默认情况下是不会存储磁盘的,在这里直接使用内存中。
看下第0个job:
在4个worker上启动4个executor,是在最大化的使用计算资源,通过第1个job 不断接收数据。
这里处理数据有shuffle read,shuffle write,通过socketTextStream即rdd,这里叫blockRdd,而且blockrdd来自于socketTextStream的方法:
其实是inputStream帮我们在固定时间间隔内会产生固定的rdd,接收数据是在一个executor的task中接收的,但现在处理数据是transform操作发生在executor里面的发生在4个executor,这个结果告诉我们在一台机器上接收数据,但实际上是在四台机器上处理数据的。最大化利用集群资源处理数据。SparkStreaming程序执行时就是一个batch级别的Job,里面做了很多事情。整个处理,其实只有一个Job真正在执行,但产生很多Job相互协调来完成复杂的业务处理,这个情况告诉我们SparkStreaming并不是网络、博客、书籍、官网上讲的那么简单。
SparkStreaming本身是随着流进来的数据按照时间为单位生成job,然后触发job在Cluster上执行的流式处理的引擎,它本身是加上以时间为维度的批处理,实例中以300秒为会产生一批数据,基于这一批数据会生成rdd,基于rdd会触发job,rdd的生成、job的触发,都是SparkStreaming框架去做的。SparkStreaming中有个至关只要的东西叫DStream,我们每隔一定时间都会生成rdd,产生rdd的依赖或触发job具体的执行。每隔时间,所以弄了一个DStream,DStream代表时空的概念,时间为维度,随着时间的推进不断产生rdd,实际上DStream就是rdd的集合,只不过是有时间的先后顺序;空间维度实际上是DStream的处理层面,我们对DStream进行处理实际上是对DStream里面的每个rdd的处理。整个时空是一个很大的概念,时间固定的话,可以锁定对空间的操作,操作其实就是transform,对DStream的操作会构建DStream Graph。
总结:
随着时间为维度有个DStream Graph,同时在时间维度下有个空间维度,空间维度就是操作,空间维度确定的情况下时间不断推进的时候他就不断把空间维度的DStream Graph实例化成rdd的graph,然后触发具体的job进行执行。