3.4 Spark通信機制
前面介紹過,Spark的部署模式可以分為local、standalone、Mesos、YARN等。
本節(jié)以Spark部署在standalone模式下為例,介紹Spark的通信機制(其他模式類似)。
3.4.1 分布式通信方式
先介紹分布式通信的幾種基本方式。
1. RPC
遠程過程調(diào)用協(xié)議(Remote Procedure Call Protocol, RPC)是一種通過網(wǎng)絡(luò)從遠程計算機程序上請求服務(wù),而不需要了解底層網(wǎng)絡(luò)技術(shù)的協(xié)議。RPC假定某些傳輸協(xié)議的存在,如TCP或UDP,為通信程序之間攜帶信息數(shù)據(jù)。在OSI網(wǎng)絡(luò)通信模型中,RPC跨越了傳輸層和應(yīng)用層。RPC使得開發(fā)分布式應(yīng)用更加容易。RPC采用C/S架構(gòu)。請求程序就是一個Client,而服務(wù)提供程序就是一個Server。首先,Client調(diào)用進程發(fā)送一個有進程參數(shù)的調(diào)用信息到Service進程,然后等待應(yīng)答信息。在Server端,進程保持睡眠狀態(tài)直到調(diào)用信息到達為止。當(dāng)一個調(diào)用信息到達時,Server獲得進程參數(shù),計算結(jié)果,發(fā)送答復(fù)信息,然后等待下一個調(diào)用信息,最后,Client調(diào)用進程接收答復(fù)信息,獲得進程結(jié)果,然后調(diào)用執(zhí)行繼續(xù)進行。
2. RMI
遠程方法調(diào)用(Remote Method Invocation, RMI)是Java的一組擁護開發(fā)分布式應(yīng)用程序的API。RMI使用Java語言接口定義了遠程對象,它集合了Java序列化和Java遠程方法協(xié)議(Java Remote Method Protocol)。簡單地說,這樣使原先的程序在同一操作系統(tǒng)的方法調(diào)用,變成了不同操作系統(tǒng)之間程序的方法調(diào)用。由于J2EE是分布式程序平臺,它以RMI機制實現(xiàn)程序組件在不同操作系統(tǒng)之間的通信。比如,一個EJB可以通過RMI調(diào)用Web上另一臺機器上的EJB遠程方法。RMI可以被看作是RPC的Java版本,但是傳統(tǒng)RPC并不能很好地應(yīng)用于分布式對象系統(tǒng)。Java RMI則支持存儲于不同地址空間的程序級對象之間彼此進行通信,實現(xiàn)遠程對象之間的無縫遠程調(diào)用。
3. JMS
Java消息服務(wù)(Java Message Service, JMS)是一個與具體平臺無關(guān)的API,用來訪問消息收發(fā)。JMS使用戶能夠通過消息收發(fā)服務(wù)(有時稱為消息中介程序或路由器)從一個JMS客戶機向另一個JMS客戶機發(fā)送消息。消息是JMS中的一種類型對象,由兩部分組成:報頭和消息主體。報頭由路由信息以及有關(guān)該消息的元數(shù)據(jù)組成。消息主體則攜帶著應(yīng)用程序的數(shù)據(jù)或有效負載。JMS定義了5種消息正文格式,以及調(diào)用的消息類型,允許發(fā)送并接收以一些不同形式的數(shù)據(jù),提供現(xiàn)有消息格式的一些級別的兼容性。
? StreamMessage:Java原始值的數(shù)據(jù)流。
? MapMessage:一套名稱-值對。
? TextMessage:一個字符串對象。
? ObjectMessage:一個序列化的Java對象。
? BytesMessage:一個未解釋字節(jié)的數(shù)據(jù)流。
4. EJB
JavaEE服務(wù)器端組件模型(Enterprise JavaBean, EJB)的設(shè)計目標(biāo)是部署分布式應(yīng)用程序。簡單來說就是把已經(jīng)編寫好的程序打包放在服務(wù)器上執(zhí)行。EJB定義了一個用于開發(fā)基于組件的企業(yè)多重應(yīng)用程序的標(biāo)準(zhǔn)。EJB的核心是會話Bean(Session Bean)、實體Bean(Entity Bean)和消息驅(qū)動Bean(Message Driven Bean)。
5. Web Service
Web Service是一個平臺獨立的、低耦合的、自包含的、基于可編程的Web應(yīng)用程序。可以使用開放的XML(標(biāo)準(zhǔn)通用標(biāo)記語言下的一個子集)標(biāo)準(zhǔn)來描述、發(fā)布、發(fā)現(xiàn)、協(xié)調(diào)和配置這些應(yīng)用程序,用于開發(fā)分布式的應(yīng)用程序。Web Service技術(shù)能使得運行在不同機器上的不同應(yīng)用無須借助第三方軟硬件,就可相互交換數(shù)據(jù)或集成。Web Service減少了應(yīng)用接口的花費。Web Service為整個企業(yè)甚至多個組織之間的業(yè)務(wù)流程的集成提供了一個通用機制。
3.4.2 通信框架AKKA
AKKA是一個用Scala語言編寫的庫,用于簡化編寫容錯的、高可伸縮性的Java和Scala的Actor模型應(yīng)用。它分為開發(fā)庫和運行環(huán)境,可以用于構(gòu)建高并發(fā)、分布式、可容錯、事件驅(qū)動的基于JVM的應(yīng)用。AKKA使構(gòu)建高并發(fā)的分布式應(yīng)用變得更加容易。Akka已經(jīng)被成功運用在眾多行業(yè)的眾多大企業(yè),從投資業(yè)到商業(yè)銀行、從零售業(yè)到社會媒體、仿真、游戲和賭博、汽車和交通系統(tǒng)、數(shù)據(jù)分析等。任何需要高吞吐率和低延遲的系統(tǒng)都是使用AKKA的候選,因此Spark選擇AKKA通信框架來支持模塊間的通信。
Actor模型常見于并發(fā)編程,它由Carl Hewitt于20世紀(jì)70年代早期提出,目的是解決分布式編程中的一系列問題。其特點如下:
1)系統(tǒng)中的所有事物都可以扮演一個Actor。
2)Actor之間完全獨立。
3)在收到消息時Actor采取的所有動作都是并行的。
4)Actor有標(biāo)識和對當(dāng)前行為的描述。
Actor可以看作是一個個獨立的實體,它們之間是毫無關(guān)聯(lián)的。但是,它們可以通過消息來通信。當(dāng)一個Actor收到其他Actor的信息后,它可以根據(jù)需要做出各種響應(yīng)。消息的類型和內(nèi)容都可以是任意的。這點與Web Service類似,只提供接口服務(wù),不必了解內(nèi)部實現(xiàn)。一個Actor在處理多個Actor的請求時,通常先建立一個消息隊列,每次收到消息后,就放入隊列。Actor每次也可以從隊列中取出消息體來處理,而且這個過程是可循環(huán)的,這個特點讓Actor可以時刻處理發(fā)送來的消息。
AKKA的優(yōu)勢如下:
1)易于構(gòu)建并行與分布式應(yīng)用(simple concurrency & distribution):AKKA采用異步通信與分布式架構(gòu),并對上層進行抽象,如Actors、Futures、STM等。
2)可靠性(resilient by design):系統(tǒng)具備自愈能力,在本地/遠程都有監(jiān)護。
3)高性能(high performance):在單機中每秒可發(fā)送5000萬個消息。內(nèi)存占用小,1GB內(nèi)存中可保存250萬個actors。
4)彈性,無中心(elastic — decentralized):自適應(yīng)的負責(zé)均衡、路由、分區(qū)、配置。
5)可擴展性(extensible):可以使用Akka擴展包進行擴展。
3.4.3 Client、Master和Worker之間的通信
Client、Master與Worker之間的交互代碼實現(xiàn)位于如下路徑:
? ? ? ? (spark-root)/core/src/main/scala/org/apache/spark/deploy
主要涉及的類包括Client.scala、Master.scala和Worker.scala。這三大模塊之間的通信框架如圖3-9所示:
[插圖]
圖3-9 Client、Master和Worker之間的通信
以Standalone部署模式為例,三大模塊分工如下:
1)Client:提交作業(yè)給Master。
2)Master:接收Client提交的作業(yè),管理Worker,并命令Worker啟動Driver和Executor。
3)Worker:負責(zé)管理本節(jié)點的資源,定期向Master匯報心跳信息,接收Master的命令,如啟動Driver和Executor。
下面列出Client、Master與Worker的實現(xiàn)代碼,讀者可以從中看到三個模塊間的通信交互。
1. Client端通信
2. Master端通信
3. Worker端通信邏輯