Akka手冊譯(一)——消息傳遞的可靠性

Akka幫助您構(gòu)建可靠的應(yīng)用程序在一臺機器上使用多個處理器核心(“擴大”)或分布在計算機網(wǎng)絡(luò)(“擴張”)。關(guān)鍵的抽象使所有交互者在代碼單元——Actor——發(fā)生在消息傳遞過程中,這就是為什么在參與者之間傳遞消息時以精確的詞義得到它們的內(nèi)容。

以下的討論涉及到考慮到應(yīng)用拆分到多個網(wǎng)絡(luò)主機上。不論發(fā)送到在本地JVM的Actor或遠(yuǎn)程的Actor基本的通信機制是一致的,當(dāng)然可以觀察到交付信息的延遲不同(可能取決于網(wǎng)絡(luò)鏈路的帶寬和消息大?。?和可靠性。對于遠(yuǎn)程消息發(fā)送顯然有更多的步驟,這意味著更多的出錯可能性。另一個方面是,本地傳遞只會在同一個JVM中通過引用信息,沒有任何限制底層對象發(fā)送,而遠(yuǎn)程運輸將受消息大小限制。

編寫Actor時采用悲觀策略以使每個交互者遠(yuǎn)程是安全的。這只有依靠屬性來保證,并在下面詳細(xì)討論這些內(nèi)容。有一些開銷發(fā)生在Actor實現(xiàn)時。如果樂意放棄的透明傳輸比如用一組緊密的Actor做樣例,把它們在同一個JVM只使消息傳遞完全可靠。下面將進(jìn)一步權(quán)衡這方面細(xì)節(jié)。

作為一種補充部分,我們將涉及到一些頂級內(nèi)置部分建立更高可靠性。這章結(jié)尾將討論一下“死信機制”。

一般的規(guī)則

這些是消息發(fā)送的規(guī)則(即tell或!方法,也構(gòu)成詢問模式):

  • 至多一次交付,例如非擔(dān)保的交付;
  • 發(fā)送者-接收者每個消息有序化成對;
    第一條規(guī)則通常發(fā)現(xiàn)在其它Actor實現(xiàn),當(dāng)?shù)诙lAkka特定于它們。

討論:至多一次交付是含義

描述交付機制的語義有三類:

  • 至多一次交付指每個消息的機制是1次或0次交付,更直白的說消息可能會丟失。
  • 至少一次交付指每個消息的機制是嘗試多次交付,并有一次成功。更直白的說消息會重復(fù)但不會丟失。
  • 只一次交付指每個消息只會交付給接收者一次,消息可能即不會被復(fù)制也不重復(fù)。
    第一個代價最低——高性能,低開銷——因為它實現(xiàn)即發(fā)即棄的方式不在發(fā)送端或傳輸狀態(tài)上保持狀態(tài)。第二個需要累計傳輸失敗量,這意味著發(fā)送端保持狀態(tài)以及接收端實現(xiàn)確認(rèn)機制。第三個代價最高,之所以性能最差,因為要保持接收端的狀態(tài)還要過慮掉重復(fù)數(shù)據(jù)。

討論:為什么用非擔(dān)保交付

以上這個問題的核心是擔(dān)保表示:

  1. 網(wǎng)絡(luò)上的消息發(fā)送出去嗎?
    2.消息在其他主機接收嗎?
  2. 消息放到目標(biāo)Actor的郵箱了嗎?
  3. 目標(biāo)Actor開始處理消息了嗎?
  4. 目標(biāo)Actor的消息處理成功了嗎?
    這些的每一個都有各自的挑戰(zhàn)和開銷,很明顯在消息處理庫中有條件的將無法完成??紤]例子的配置郵箱類型以及一個郵箱的邊界如何與第三點相互,甚至決定以上五個點的“成功”是什么。

沿這幾點的推理得到“Nobody Needs Reliable Messaging.”發(fā)送方知道的接收業(yè)務(wù)級別的確認(rèn)消息成功的唯一意義在于,Akka不是可以自己組成的。(這不是一個想怎么做就能怎么做的框架)。

Akka依賴分布式并使用不可靠的通信傳遞消息,因此它不保存可以想像成漏水一樣。這個模型已經(jīng)在Erlang中的取得了巨大的成功,用戶圍繞它來設(shè)計他們的應(yīng)用程序。可以閱讀更多關(guān)于這種方法在Erlang文檔(10.9和10.10節(jié)),Akka密切關(guān)注它。

另一個角度看這個問題,它只提供基本保障的用例不需要更強的可靠性不支付的成本實施;它總是可以添加更強的可靠性的基本內(nèi)容上,但這是不可能的倒行逆施的刪除為了獲得更多的性能可靠性。

討論:消息排序

更具體的說,對于給定的兩個Actor,消息收到時不會無序。這強調(diào)了只能保證應(yīng)用在發(fā)送時明確發(fā)送源和目標(biāo)時,而不是使用介質(zhì)或其他信息傳遞特性(除非另有說明)。
如下例這樣保障:

Actor A1發(fā)送消息 M1,M2,M3 到 A2
Actor A3發(fā)送消息 M4,M5,M6 到A2
這意味著:

  1. M1必須在M2和M3之前交付;
  2. M2必須在M3之前交付;
  3. M4必須在M5和M6之前交付;
  4. M5必須在M6之前交付;
  5. A2能從A1和A3交叉看到消息;
  6. 由于不是保證交付,任何消息都可能拋下,即沒有到達(dá)A2

注意
Akka保證適用于消息隊列的順序進(jìn)入收件人的郵箱。如果郵箱遵循FIFO實現(xiàn)順序(例如PriorityMailbox),然后處理順序的Actor將偏離入隊秩序。

注意這些規(guī)則是不可達(dá)的

Actor A發(fā)送消息M1 到Actor C
Actor A 然后發(fā)送消息M2 到Actor B
Actor B轉(zhuǎn)遞消息M2到Actor C
Actor C可能以任何順序收到M1和M2

由于可達(dá)順序是M2在M1在Acotr C收到后再收到(盡管其中任何一個可能丟失)。這個順充可能不確定因不同消息延遲,在A,B,C在不同的網(wǎng)絡(luò)主機上。請參閱下文。

注意
Actor創(chuàng)建被視為一個消息從父級發(fā)送到子級,如同上面所討論的。在發(fā)送消息到Actor時能重新在初始化時重新排序就意味著消息沒有到達(dá)因為Actor還沒生成。舉個例子發(fā)送一個消息從R2引用發(fā)送過來時,消息可能太早到而不能創(chuàng)建遠(yuǎn)程布署的Actor R1時。更好的定義順序是創(chuàng)建Actor后立即發(fā)送一個消息給它。

通訊失敗

請注意以上兩個Actor間保證順序的討論僅限于用戶消息。Actor的子級通信是特別的系統(tǒng)消息,與用戶消息的順序無關(guān)。特別是:

子Actor C發(fā)送消息M到它的父級P
子Actor F處理失敗
父Actor P可能收到兩個事件順序M,F(xiàn)或F,M

原因是內(nèi)部系統(tǒng)消息有自己的郵箱調(diào)用用戶排隊的順序和系統(tǒng)的消息不能保證出列的訂購時間。

JVM內(nèi)(本地)消息發(fā)送規(guī)則

留意正下這節(jié)所要做的

在這一節(jié)中依賴較強的可適應(yīng)性是不可取的,從應(yīng)用程序綁定到本地布署上。應(yīng)用程序被設(shè)計的不同(不僅僅是一些消息交換模式和一些Actor)以適應(yīng)一個集群上運行的機器。我們的信條是一次設(shè)計,任意布署。而要實現(xiàn)這一點,人應(yīng)該只依賴于一般規(guī)則。

本地發(fā)送的可靠性

Akka測試套件的依賴在本地的上下文中沒有丟失的消息(及遠(yuǎn)程開發(fā)沒有錯誤測試),這意味著我們努力保持測試穩(wěn)定。本地tell操作可能因為一些原因的錯誤就如同通常在JVM中調(diào)用的方法。

  • StackOverflowError
  • OutOfMemoryError
  • other VirtualMachineError
    此外,本地發(fā)送有特定的Akka方法使發(fā)送時出錯:
  • 比如郵箱沒有接收到消息(如,BoundedMaibox滿了)
  • 接收的actor處理失敗或已經(jīng)終止
    當(dāng)排除每一個錯誤的配置引起第二個時,第二個消息得不到反饋在處理異常。通知會被它的主客代替。這是一般不區(qū)分外部觀察者的失去了消息

本地消息發(fā)送順序

上述警告的不及物的消息假定在嚴(yán)格的FIFO郵箱中在特定條件下被消除。會注意到,這些很細(xì)微甚至涉及到未來優(yōu)化整個段落。這可能是下列不完整的幾點:

  • 在收到頂級的Actor回復(fù)前,有一個內(nèi)部鎖保護(hù)內(nèi)部監(jiān)時隊列,這把鎖不是直接的。這意味著排隊請求期間從不同的發(fā)送者到acotr的結(jié)構(gòu)(比如,細(xì)節(jié)更復(fù)雜)可能被重新排序根據(jù)底層線程調(diào)度。由于不存在完全公平鎖在JVM上,這是認(rèn)識上的誤區(qū)。
  • 使用相同的機制在建設(shè)一個路由器,更精確地ActorRef路由,因此Actor與路由器部署存在同樣的問題。
  • 如前所述,發(fā)生任何鎖的問題是涉及在入隊,這可能也適用于自定義郵箱。
    這個列表已經(jīng)仔細(xì)編制,但其他問題場景可能逃脫了我們的分析。

本地排除和網(wǎng)絡(luò)排序如何實施

對于一個給定的規(guī)則對Actor、消息發(fā)送直接從第一個到第二個不會收到無序適用于通過網(wǎng)絡(luò)發(fā)送的消息與基于TCP的Akka遠(yuǎn)程傳輸協(xié)議。
在前一節(jié)中解釋當(dāng)?shù)叵l(fā)送服從傳遞因果順序在特定條件下。這個命令可以違反了由于不同的消息傳遞延遲。例如:

node-1上Actor A發(fā)送消息M1到node-3上的actor C
然后node-1的Actor A上發(fā)送消息M2到node-2的Actor B
node-2上ActorB轉(zhuǎn)發(fā)消息M2到node-3的 Actor C
Actor C 可能以任何順序收到M1 和 M2

M1可能花很長時間旅行到node-3 比M2旅行經(jīng)過node-3經(jīng)過node-2

高級抽象

Akka提供強大的、更高層次的抽象基于一個微小而持續(xù)的Akka核心工具集。

消息傳遞模式

正如上面所討論的可靠傳遞的要求是一個顯式的ACK-RETRY協(xié)議。在其最簡單的形式要求

  • 一種識別個人信息和確認(rèn)相關(guān)信息
  • 重試機制,如果不確認(rèn)將重新發(fā)送消息
  • 為接收器檢測和丟棄重復(fù)
    第三種成為必要借助確認(rèn)不必要到達(dá)。ACK-RETRY協(xié)議與業(yè)務(wù)級別的確認(rèn)支持“至少一次”的Akka持久模塊交付。副本可以檢測到跟蹤消息的標(biāo)識符通過“至少一次”交付。另一種實現(xiàn)第三部分將使處理消息冪等層面的業(yè)務(wù)邏輯。

實現(xiàn)這三個需求的另一個例子是在可靠的代理模式(這是現(xiàn)在取代“至少一次”交付)。

事件源

事件源(和共享)用于制造大型網(wǎng)站規(guī)模數(shù)十億的用戶,這個想法非常簡單:當(dāng)一個組件(Actor)過程命令將生成一個事件列表代表命令的效果。這些事件存儲除了應(yīng)用于組件的狀態(tài)。這個方案的優(yōu)點是,事件只添加到存儲,沒有什么是永遠(yuǎn)的突變;這使得完美的復(fù)制和擴展消費者的事件流(即其他組件可以使用事件流來復(fù)制組件的狀態(tài)在一個不同的容器或反應(yīng)的變化)。如果組件的狀態(tài)因為機器故障或被排擠出緩存它可以很容易地重建重演了事件流(通常采用快照來加快這一進(jìn)程)。事件源支持Akka持久性。

郵箱的明確確認(rèn)

通過實現(xiàn)一個自定義郵箱類型可以重試的消息處理接收Actor的一端為處理臨時失敗。此模式主要是有用的本地通信上下文交付擔(dān)保否則足以滿足應(yīng)用程序的需求。

請注意,規(guī)則的警告在jvm(本地)消息發(fā)送申請。

實現(xiàn)這種模式的一個例子是顯示在郵箱與明確的確認(rèn)。

死信

消息不能交付(這可以確定)將交付給一個叫做 /deadLetters合成的Actor。這交付發(fā)生在力所能及;它可能會失敗甚至在本地JVM(例如在Actor終止)。通過發(fā)送的消息不可靠的網(wǎng)絡(luò)傳輸將丟失沒有出現(xiàn)死亡的信件。

死信用于哪些方面

這個設(shè)備的主要用途是為調(diào)試,特別是如果一個Actor發(fā)送與到達(dá)不一致(通常檢查死者字母會告訴你,發(fā)送方或接收方設(shè)置錯了沿途某處)。為了有效使用它盡可能避免發(fā)送deadLetters,即運行您的應(yīng)用程序與一個合適的死信記錄器(參見下面的更多)不時和清理日志輸出。這種需要明智的應(yīng)用常識:很可能是避免發(fā)送Actor終止,使發(fā)送方的代碼更清晰。

死信服務(wù)遵循相同的規(guī)則對交付擔(dān)保和其他消息發(fā)送,因此它不能用于實現(xiàn)保證交付。

如何接收死信

Actor可以訂閱akka.actor.DeadLetter在事件流,Event Stream顯示如何使用它。訂閱的Actor將會收到所有死信件發(fā)表在這一點的本地系統(tǒng)。死信不是通過網(wǎng)絡(luò)傳播,如果想收集在一個地方要訂閱一個Actor/手動網(wǎng)絡(luò)節(jié)點和轉(zhuǎn)發(fā)。死信在這個節(jié)點生成可以確定發(fā)送操作失敗,可以本地系統(tǒng)為遠(yuǎn)程發(fā)送(如果沒有可以建立網(wǎng)絡(luò)連接)或遠(yuǎn)程(如果你發(fā)送的Actor不存在在這個時間點)。

死信不需要擔(dān)心

每一次Actor不會由自已決定停止,因為有一可能它自已發(fā)送丟失。一些復(fù)雜的自動關(guān)閉場景是良性的:看到akka.dispatch.Terminate。終止消息意味著兩個終止請求,當(dāng)然只有一個能成功。同樣,你可能會看到akka.actor.Terminated。但父級看孩子時終止消息Actor的層次結(jié)構(gòu)在死信從孩子開始。

上一篇
下一篇

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 230,501評論 6 544
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 99,673評論 3 429
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事?!?“怎么了?”我有些...
    開封第一講書人閱讀 178,610評論 0 383
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經(jīng)常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,939評論 1 318
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 72,668評論 6 412
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 56,004評論 1 329
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 44,001評論 3 449
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 43,173評論 0 290
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 49,705評論 1 336
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 41,426評論 3 359
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,656評論 1 374
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 39,139評論 5 364
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 44,833評論 3 350
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 35,247評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,580評論 1 295
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 52,371評論 3 400
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 48,621評論 2 380

推薦閱讀更多精彩內(nèi)容