Spark Streaming之Receive分发

以Socket为例,SocketInputDStream对应的流数据接收器为SocketReceiver,在SocketInputDStream中通过getReceiver方法获取该流数据接收器:

在StreamingContext启动过程中,ReceiverTracker会把流数据接收器Receiver分发到Executor上,在每个Executor上,由ReceiverSupervisor启动对应Receiver;在Spark1.4及以前的版本中根据N个Receiver实例,在StreamingContext中创建一个作业,在该作业包含N个任务;

如下图:

1:先遍历ReceiveInputStream,通过其getReceiver获取需要启动的N个Receiver实例,然后把这些实例作为N份数据,在StreamingContext创建一个RDD实例,该RDD分为N个partition。每个

partition对应包含一个Receiver数据,即Receiver实例;

2:在这里我们把Receiver所进行的计算定义为func函数,该函数以Receiver实例为参数构造ReceiverSupervisorImpl实例supervisor,构造完毕后使用新线程启动该Supervisor并阻塞该线程;

3:把ReceiverTacker尽可能地按照Receiver的首选位置分发到集群中并启动,启动完毕后Receiver会处于阻塞状态,持续不断的接入流数据;

该Receiver分发方式在长时间的运行过程中,如果出现某个任务失败,则spark会重新发送该任务到其他Executor进行重跑,但由于该分发的过程属于随机分配,无法实现集群的负载均衡,有可能出现某Worker节点运行多个任务,而某些worker节点却是空闲的。而当该任务失败次数超过规定的上限spark.task.maxFailures(默认=4)。则会导致该Receiver无法启动;

针对以上出现的问题,在Spark1.5及以后的版本做优化;

在StreamingContext中会根据N个Receiver实例创建N个作业,各个作业中只包含一个任务,并加入了可插拔的Receiver分发策略;

在Spark Streaming中每个Receiver都有一个作业来分发(该作业只包含一个任务),而且对于仅有的一个任务只在第一次启动的时候,才尝试启动Receiver。如果该任务失败了,则不再尝试启动Receiver,对应的作业可以置为完成状态,此时ReceiverTacker会新生一个作业,在其他Executor尝试启动,直到成功为止,这样Receiver就不会受到任务失败上限而无法启动。通过这种方式,Spark Streaming总是保持活性,并不会随Executor的失败而终止;

Receiver分发策略

Receiver分发策略在ReceiverSchedulingPolicy类中定义,在Receiver分发之前会收集所有的InputDstream包含的所有Receiver实例和Executor,然后调用该类中的scheduleReceivers方法计算每个Receiver对应的Executor,在该方法中以轮询的调度方式进行分配,首先对存在首选位置的Receiver进行处理,尽可能地把Receiver运行在首选位置机器运行Receiver个数最少的Executor中,接着对于没有首选位置的Receiver,则优先分配到运行Receiver个数最少的Executor中,分配完成后返回调度好的Executor列表;

QQ交流群:519844688

猜你喜欢

转载自blog.csdn.net/wql_zero/article/details/86033333
今日推荐