spark streaming源码分析3 调度及运行
来源:互联网 发布:会员消费数据分析 编辑:程序博客网 时间:2024/06/02 08:24
前面的两节内容介绍了StreamingContext的构造以及在此上的一系列操作。
通过调用start方法,真正开始调度执行。首先校验状态是否是INITIALIZED,然后调用JobScheduler的start方法,并将状态设置为ACTIVE。
看一下JobScheduler的start方法内部
1、首先构造一个事件类型为[JobSchedulerEvent]的循环器eventLoop(包含JobStarted,JobCompleted,ErrorReported三个事件),内部有一个线程实时获取队列中的事件,有则处理。实际调用如上的onReceive/onError方法。eventLoop.start后,内部线程真正运行起来,并等待事件的到来。2、构造ReceiverTracker
(1)从DStreamGraph中获取注册的ReceiverInputStreams
(2)获取所有ReceiverInputStreams的streamId
(3)构造一个ReceiverLauncher,它是一个接受器
(4)构造一个ReceivedBlockTracker,
用于维护所有的接收器(receiver)接收到的所有block信息,即ReceivedBlockInfo
3、调用receiverTracker的start方法。
如果receiverInputStreams不为空,则建立akka RPC服务,名称为ReceiverTracker,负责注册Receiver、AddBlock、ReportError(报告错误)、注销Receiver四个事件
调用receiverExecutor的start方法,最终调用了startReceivers方法。
1)获取所有的receiver(接收器)
2)将receivers建立tempRDD,并分区并行化,每个分区一个元素,元素为receiver
3)创建方法startReceiver,该方法以分区元素(receiver)的迭代器作为参数,之后将该方法参数传入runJob中,针对每个分区,依次将每个分区中的元素(receiver)应用到该方法上
4)runJob的startReceiver方法。每个分区只有一个receiver,因此在该方法内构造一个ReceiverSupervisorImpl,在它内部真正的接收数据并保存。发送RegisterReceiver消息给dirver驱动。
重点介绍一下supervisor.start方法内部的逻辑实现:主要分为以下两个方法
(1)onStart方法:
- 数据真正接收到是发生在SocketReceiver.receive函数中,将接收到的数据放入到BlockGenerator.currentBuffer
- 在BlockGenerator中有一个重复定时器,处理函数为updateCurrentBuffer, updateCurrentBuffer将当前buffer中的数据封装为一个新的Block,放入到blocksForPush队列中
- 同样是在BlockGenerator中有一个BlockPushingThread,其职责就是不停的将blocksForPushing队列中的成员通过pushArrayBuffer函数传递给blockmanager,让BlockManager将数据存储到MemoryStore中
- pushArrayBuffer还会将已经由BlockManager存储的Block的id号传递给ReceiverTracker,ReceiverTracker会将存储的blockId放到对应StreamId的队列中
(2)startReceiver方法:
1)receiver.onStart方法
建立socket连接,逐行读取数据,最终将数据插入BlockGenerator的currentBuffer中。一旦插入了数据,就触发了上面重复定时器。按设置的block生产间隔(默认200ms),生成block,将block插入blocksForPushing队列中。然后,blockPushingThread线程逐个取出传递给blockmanager保存起来,同时通过AddBlock消息通知ReceiverTracker已经将哪些block存储到了blockmanager中。
2)onReceiverStart方法
向receiverTracker(位于driver端)发送RegisterReceiver消息,报告自己(receiver)启动了,目的是可以在UI中反馈出来。ReceiverTracker将每一个stream接收到但还没有进行处理的block放入到receiverInfo,其为一Hashmap. 在后面的generateJobs中会从receiverInfo提取数据以生成相应的RDD。
4、调用jobGenerator的start方法。
(1)首先构建JobGeneratorEvent类型事件的EventLoop,包含GenerateJobs,ClearMetadata,DoCheckpoint,ClearCheckpointData四个事件。并运行起来。
(2)调用startFirstTime启动generator
timer.getStartTime计算出来下一个周期的到期时间,计算公式:(math.floor(clock.currentTime.toDouble / period) + 1).toLong * period,以当前的时间/除以间隔时间,再用math.floor求出它的上一个整数(即上一个周期的到期时间点),加上1,再乘以周期就等于下一个周期的到期时间。(3) 启动DStreamGraph,调用graph.start方法,启动时间比startTime早一个时间间隔,为什么呢?求告知!!!
(4) 调用timer.start方法,参数为startTime
这里的timer为:
内部包含一个定时器,每隔batchDuration的时间间隔就向eventLoop发送一个GenerateJobs消息,参数longTime为下一个间隔到来时的时间点
通过内部的thread.start方法,触发timer内部的定时器运行。从而按时间间隔产生job。
5、GenerateJobs/ClearMetadata 事件处理介绍
JobGeneratorEvent类型事件的EventLoop,包含GenerateJobs,ClearMetadata,DoCheckpoint,ClearCheckpointData四个事件
GenerateJobs:
(1)allocateBlocksToBatch:首先根据time的值获取之前receiver接收到的并且通过AddBlock消息传递给receiverTracker的block元数据信息。并且将time对应的blocks信息映射保存起来。
那么,这里的time是怎么和每200ms间隔产生blocks对应起来的呢?答案就是time时间到后,将所有接收到但还未分配的blocks都划为这个time间隔内的。
(2)generateJobs:根据一个outputStream生成一个job,最终每个outputStream都调用如下的方法,见下面代码注释
注:这里的generateJob实际调用的是根据outputStream重载的方法,比如print的方法是输出一些值:
这里需要解释一下ReceiverInputDStream的compute方法
1)首先根据time值将之前映射的blocks元数据信息获取出来
2) 获取这些blocks的blockId,blockId其实就是streamId+唯一值,这个唯一值可以保证在一个流里面产生的唯一的Id
3)将这个batchTime时间内的blocks元信息汇总起来,保存到inputInfoTracker中
4)将sparkContext和blockIds封装成BlockRDD返回
至此,Job已经产生了。如果Job产生成功,就走Case Success(Jobs) =>分支
主要是根据time,jobs,以及streamId和每个streamId的记录数的映射封装成JobSet,调用submitJobSet
可以看到,将jobSet保存到jobSets这样一个映射结构当中,然后将每个job通过JobHandler封装之后,通过一个线程调用运行起来。这个线程就是通过“spark.streaming.concurrentJobs”参数设置的一个线程池,默认是1。
接着看JobHandler被线程处理时的逻辑,见代码注释:
ClearMetadata:
当一个jobset完成后,就会处理ClearMetadata消息
1、根据time的时间,过滤出在time之前的rdd,如果设置了rememberDuration,则过滤出小于(time-rememberDuration)的rdd
2、将过滤出的rdd调用unpersist
3、删除在blockManager中的block
4、根据dependencies关系链依次删除,从outputStream开始,根据链路依次进行
5、删除其它内存纪录信息
至此,关于spark stream最重要的部分,调度及运行就分析结束了!
转载: http://blog.csdn.net/yueqian_zhu/article/details/49023383
- spark streaming源码分析3 调度及运行
- spark streaming源码分析3 调度及运行
- Spark Streaming源码分析
- spark-streaming源码分析
- spark 调度模块详解及源码分析
- spark 调度模块详解及源码分析
- spark streaming 运行原理图解分析
- Spark Streaming源码初探 (3)
- spark streaming源码分析1 StreamingContext
- spark streaming源码分析5 checkpoint
- spark streaming源码分析1 StreamingContext
- spark streaming 2.02 Receiver 运行executor的调度算法
- 5.Spark Streaming流计算框架的运行流程源码分析
- Spark资源调度机制源码分析--基于spreadOutApps及非spreadOutApps两种资源调度算法
- Spark源码系列(八)Spark Streaming实例分析
- Spark源码系列(八)Spark Streaming实例分析
- Spark源码分析(五)调度管理3
- Spark源码分析之二:Job的调度模型与运行反馈
- Spring Data JPA入门
- fb flux 实例分析
- OpenHEVC多线程解码流程
- nchar and nvarchar (Transact-SQL)(nchar 和nvarchar说明)
- NSURLSession(一)GET请求
- spark streaming源码分析3 调度及运行
- AsyncHttpClient执行流程简单总结
- SMO算法
- English Learn3
- NSURLSession(二)POST请求
- 从微信观看游戏制作观
- Linux stat 获取文件属性
- FZU 2173 Nostop(矩阵快速幂+floyd)
- ios 应用程序之间的跳转