Spark通信架構分析及總結


Spark作為分布式計算框架,多個節點的設計與相互通信模式是其重要的組成部分。

Spark一開始使用 Akka 作為內部通信部件。在Spark 1.3年代,為了解決大塊數據(如Shuffle)的傳輸問題,Spark引入了Netty通信框架。到了 Spark 1.6, Spark可以配置使用 Akka 或者 Netty 了,這意味着 Netty 可以完全替代 Akka了。再到 Spark 2, Spark 已經完全拋棄 Akka了,全部使用Netty了。

為什么呢?官方的解釋是:

1)     很多Spark用戶也使用Akka,但是由於Akka不同版本之間無法互相通信,這就要求用戶必須使用跟Spark完全一樣的Akka版本,導致用戶無法升級Akka。

2)     Spark的Akka配置是針對Spark自身來調優的,可能跟用戶自己代碼中的Akka配置沖突。

3)     Spark用的Akka特性很少,這部分特性很容易自己實現。同時,這部分代碼量相比Akka來說少很多,debug比較容易。如果遇到什么bug,也可以自己馬上fix,不需要等Akka上游發布新版本。而且,Spark升級Akka本身又因為第一點會強制要求用戶升級他們使用的Akka,對於某些用戶來說是不現實的。

1.1  通信組件概覽

對源碼分析,對於設計思路理解如下:

 

 

1)     RpcEndpoint:RPC端點 ,Spark針對於每個節點(Client/Master/Worker)都稱之一個Rpc端點 ,且都實現RpcEndpoint接口,內部根據不同端點的需求,設計不同的消息和不同的業務處理,如果需要發送(詢問)則調用Dispatcher

2)     RpcEnv:RPC上下文環境,每個Rpc端點運行時依賴的上下文環境稱之為RpcEnv

3)     Dispatcher:消息分發器,針對於RPC端點需要發送消息或者從遠程RPC接收到的消息,分發至對應的指令收件箱/發件箱。如果指令接收方是自己存入收件箱,如果指令接收方為非自身端點,則放入發件箱

4)     Inbox:指令消息收件箱,一個本地端點對應一個收件箱,Dispatcher在每次向Inbox存入消息時,都將對應EndpointData加入內部待Receiver Queue中,另外Dispatcher創建時會啟動一個單獨線程進行輪詢Receiver Queue,進行收件箱消息消費

5)     OutBox:指令消息發件箱,一個遠程端點對應一個發件箱,當消息放入Outbox后,緊接着將消息通過TransportClient發送出去。消息放入發件箱以及發送過程是在同一個線程中進行,這樣做的主要原因是遠程消息分為RpcOutboxMessage, OneWayOutboxMessage兩種消息,而針對於需要應答的消息直接發送且需要得到結果進行處理

6)     TransportClient:Netty通信客戶端,根據OutBox消息的receiver信息,請求對應遠程TransportServer

7)     TransportServer:Netty通信服務端,一個RPC端點一個TransportServer,接受遠程消息后調用Dispatcher分發消息至對應收發件箱

注意:

TransportClient與TransportServer通信虛線表示兩個RpcEnv之間的通信,圖示沒有單獨表達式

一個Outbox一個TransportClient,圖示沒有單獨表達式

一個RpcEnv中存在兩個RpcEndpoint,一個代表本身啟動的RPC端點,另外一個為 RpcEndpointVerifier

1.2  Endpoint啟動過程

     啟動的流程如下:

 

Endpoint啟動后,默認會向Inbox中添加OnStart消息,不同的端點(Master/Worker/Client)消費OnStart指令時,進行相關端點的啟動額外處理

Endpoint啟動時,會默認啟動TransportServer,且啟動結束后會進行一次同步測試rpc可用性(askSync-BoundPortsRequest)

Dispatcher作為一個分發器,內部存放了Inbox,Outbox的等相關句柄和存放了相關處理狀態數據,結構大致如下

 

 

 

1.3  Endpoint Send&Ask流程

     Endpoint的消息發送與請求流程,如下:

 

Endpoint根據業務需要存入兩個維度的消息組合:send/ask某個消息,receiver是自身與非自身

1)     OneWayMessage: send + 自身, 直接存入收件箱

2)     OneWayOutboxMessage:send + 非自身,存入發件箱並直接發送

3)     RpcMessage: ask + 自身, 直接存入收件箱,另外還需要存入LocalNettyRpcCallContext,需要回調后再返回

4)     RpcOutboxMessage: ask + 非自身,存入發件箱並直接發送,,需要回調后再返回

1.4  Endpoint receive流程

Endpoint的消息的接收,流程如下:

 

 

上圖 ServerBootstrap為Netty啟動服務,SocketChanel為Netty數據通道

上述包含TransportSever啟動與消息接受兩個流程 

1.5  Endpoint Inbox處理流程

Spark在Endpoint的設計上核心設計即為Inbox與Outbox,其中Inbox核心要點為:

1)     內部的處理流程拆分為多個消息指令(InboxMessage)存放入Inbox

2)     當Dispatcher啟動最后,會啟動一個名為【dispatcher-event-loop】的線程掃描Inbox待處理InboxMessage,並調用Endpoint根據InboxMessage類型做相應處理

3)     當Dispatcher啟動最后,默認會向Inbox存入OnStart類型的InboxMessage,Endpoint在根據OnStart指令做相關的額外啟動工作,三端啟動后所有的工作都是對OnStart指令處理衍生出來的,因此可以說OnStart指令是相互通信的源頭

 

 

消息指令類型大致如下三類

1)     OnStart/OnStop

2)     RpcMessage/OneWayMessage

3)     RemoteProcessDisconnected/RemoteProcessConnected/RemoteProcessConnectionError

 

1.6  Endpoint畫像

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM