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

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章