Akka 使用系列之四: Future
這篇文章介紹 Akka 的同步機(jī)制,以及 Spark 和 Akka 的恩怨情仇。
1. Akka 中的 Future
Akka 中的 Actor 發(fā)送和接收消息默認(rèn)都是異步的。為了說(shuō)明異步性,我們實(shí)行下面的數(shù)學(xué)老師和歷史老師的 Actor:
- class MathTeacherActor extends Actor with ActorLogging {
- def receive = {
- case "1+1等于多少?" => {
- Thread.sleep(1)
- sender ! "1+1等于2"
- }
- }
- }
- class HistoryTeacherActor extends Actor with ActorLogging {
- def receive = {
- case "歷史上規(guī)模***的眾籌行動(dòng)是什么?" => {
- Thread.sleep(1)
- sender ! "歷史上規(guī)模***的眾籌行動(dòng)是 +1s"
- }
- }
- }
如果我們?cè)谠儐?wèn)歷史老師之后訪問(wèn)答案(如下面代碼所示),我們發(fā)現(xiàn)并不能獲取正確答案。原因就在于 Akka 是異步非阻塞的。
- val res = historyteacher ? "歷史上規(guī)模***的眾籌行動(dòng)是什么?"
- println(res)
實(shí)質(zhì)上, historyteacher ? "歷史上規(guī)模***的眾籌行動(dòng)是什么?" 返回的根本不是答案,而是一個(gè) Future。在Akka中, 一個(gè)Future是用來(lái)獲取某個(gè)并發(fā)操作的結(jié)果的數(shù)據(jù)結(jié)構(gòu)。有了 Future,我們可以以同步(阻塞)或異步(非阻塞)的方式訪問(wèn)結(jié)果。下面是簡(jiǎn)單地以同步(阻塞)方式訪問(wèn)結(jié)果的示例。
- class StudentActor(mathteacher:ActorRef,historyteacher:ActorRef)
- extends Actor with ActorLogging{
- def receive = {
- case res:String => {
- val future1 = historyteacher ? "歷史上規(guī)模***的眾籌行動(dòng)是什么?"
- val future2 = mathteacher ? "1+1等于多少?"
- val res1 = Await.result(future1,10 second)
- val res2 = Await.result(future2,10 second)
- println(res1)
- println(res2)
- }
- }
- }
2. Akka 和 Spark
Spark 一開(kāi)始使用 Akka 作為內(nèi)部通信部件。在 Spark 1.3 年代,為了解決大塊數(shù)據(jù)(如Shuffle)的傳輸問(wèn)題,Spark引入了Netty通信框架。到了 Spark 1.6, Spark 可以配置使用 Akka 或者 Netty 了,這意味著 Netty 可以完全替代 Akka 了。再到 Spark 2, Spark 已經(jīng)完全拋棄 Akka 了,全部使用 Netty 了。Sad。
為什么 Spark 無(wú)情地有步驟有預(yù)謀地拋棄 Akka 呢?Spark 官方倒是給了一個(gè)說(shuō)法:https://issues.apache.org/jira/browse/SPARK-5293。
A lot of Spark user applications are using (or want to use) Akka. Akka as a whole can contribute great architectural simplicity and uniformity. However, because Spark depends on Akka, it is not possible for users to rely on different versions, and we have received many requests in the past asking for help about this specific issue. For example, Spark Streaming might be used as the receiver of Akka messages - but our dependency on Akka requires the upstream Akka actors to also use the identical version of Akka.
Since our usage of Akka is limited (mainly for RPC and single-threaded event loop), we can replace it with alternative RPC implementations and a common event loop in Spark. |
大意就是很多 Spark 用戶希望同時(shí)使用 Spark 和 Akka ,但他們必須使用 Spark 依賴的那個(gè)版本的 Akka。Spark 主要用了 Akka 的 RPC 和 單線程 event-loop,因此 Spark 沒(méi)有必要依賴完全的 Akka。最終,對(duì) Akka 心心念念的 Spark 用 netty 實(shí)現(xiàn)下簡(jiǎn)易版本的 Akka。真愛(ài)啊。
3. 總結(jié)
到這里,Akka 使用系列就結(jié)束了。這個(gè)系列簡(jiǎn)單地過(guò)了一下 Akka 的基礎(chǔ)知識(shí),介紹其梗概。
【本文為51CTO專欄作者“李立”的原創(chuàng)稿件,轉(zhuǎn)載請(qǐng)通過(guò)51CTO獲取聯(lián)系和授權(quán)】