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

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

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

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

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

一般的規(guī)則

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

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

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

描述交付機(jī)制的語義有三類:

  • 至多一次交付指每個(gè)消息的機(jī)制是1次或0次交付兆解,更直白的說消息可能會丟失。
  • 至少一次交付指每個(gè)消息的機(jī)制是嘗試多次交付跑揉,并有一次成功痪宰。更直白的說消息會重復(fù)但不會丟失。
  • 只一次交付指每個(gè)消息只會交付給接收者一次畔裕,消息可能即不會被復(fù)制也不重復(fù)衣撬。
    第一個(gè)代價(jià)最低——高性能,低開銷——因?yàn)樗鼘?shí)現(xiàn)即發(fā)即棄的方式不在發(fā)送端或傳輸狀態(tài)上保持狀態(tài)扮饶。第二個(gè)需要累計(jì)傳輸失敗量具练,這意味著發(fā)送端保持狀態(tài)以及接收端實(shí)現(xiàn)確認(rèn)機(jī)制。第三個(gè)代價(jià)最高甜无,之所以性能最差扛点,因?yàn)橐3纸邮斩说臓顟B(tài)還要過慮掉重復(fù)數(shù)據(jù)。

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

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

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

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

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

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

討論:消息排序

更具體的說屯断,對于給定的兩個(gè)Actor,消息收到時(shí)不會無序侣诺。這強(qiáng)調(diào)了只能保證應(yīng)用在發(fā)送時(shí)明確發(fā)送源和目標(biāo)時(shí)殖演,而不是使用介質(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保證適用于消息隊(duì)列的順序進(jìn)入收件人的郵箱座硕。如果郵箱遵循FIFO實(shí)現(xiàn)順序(例如PriorityMailbox),然后處理順序的Actor將偏離入隊(duì)秩序。

注意這些規(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收到后再收到(盡管其中任何一個(gè)可能丟失)涕蜂。這個(gè)順充可能不確定因不同消息延遲华匾,在A,B机隙,C在不同的網(wǎng)絡(luò)主機(jī)上蜘拉。請參閱下文。

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

通訊失敗

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

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

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

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

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

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

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

Akka測試套件的依賴在本地的上下文中沒有丟失的消息(及遠(yuǎn)程開發(fā)沒有錯(cuò)誤測試)悴了,這意味著我們努力保持測試穩(wěn)定。本地tell操作可能因?yàn)橐恍┰虻腻e(cuò)誤就如同通常在JVM中調(diào)用的方法违寿。

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

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

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

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

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

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

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可能花很長時(shí)間旅行到node-3 比M2旅行經(jīng)過node-3經(jīng)過node-2

高級抽象

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

消息傳遞模式

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

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

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

事件源

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

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

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

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

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

死信

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

死信用于哪些方面

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

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

如何接收死信

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

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

每一次Actor不會由自已決定停止陷揪,因?yàn)橛幸豢赡芩砸寻l(fā)送丟失惋鸥。一些復(fù)雜的自動關(guān)閉場景是良性的:看到akka.dispatch.Terminate。終止消息意味著兩個(gè)終止請求,當(dāng)然只有一個(gè)能成功悍缠。同樣,你可能會看到akka.actor.Terminated卦绣。但父級看孩子時(shí)終止消息Actor的層次結(jié)構(gòu)在死信從孩子開始。

上一篇
下一篇

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末飞蚓,一起剝皮案震驚了整個(gè)濱河市滤港,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌玷坠,老刑警劉巖蜗搔,帶你破解...
    沈念sama閱讀 211,561評論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件劲藐,死亡現(xiàn)場離奇詭異八堡,居然都是意外死亡樟凄,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,218評論 3 385
  • 文/潘曉璐 我一進(jìn)店門兄渺,熙熙樓的掌柜王于貴愁眉苦臉地迎上來缝龄,“玉大人,你說我怎么就攤上這事挂谍∈迦溃” “怎么了?”我有些...
    開封第一講書人閱讀 157,162評論 0 348
  • 文/不壞的土叔 我叫張陵口叙,是天一觀的道長炼绘。 經(jīng)常有香客問我,道長妄田,這世上最難降的妖魔是什么俺亮? 我笑而不...
    開封第一講書人閱讀 56,470評論 1 283
  • 正文 為了忘掉前任,我火速辦了婚禮疟呐,結(jié)果婚禮上脚曾,老公的妹妹穿的比我還像新娘。我一直安慰自己启具,他們只是感情好本讥,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,550評論 6 385
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著鲁冯,像睡著了一般拷沸。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上薯演,一...
    開封第一講書人閱讀 49,806評論 1 290
  • 那天撞芍,我揣著相機(jī)與錄音,去河邊找鬼涣仿。 笑死勤庐,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的好港。 我是一名探鬼主播愉镰,決...
    沈念sama閱讀 38,951評論 3 407
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼钧汹!你這毒婦竟也來了丈探?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,712評論 0 266
  • 序言:老撾萬榮一對情侶失蹤拔莱,失蹤者是張志新(化名)和其女友劉穎碗降,沒想到半個(gè)月后隘竭,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,166評論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡讼渊,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,510評論 2 327
  • 正文 我和宋清朗相戀三年动看,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片爪幻。...
    茶點(diǎn)故事閱讀 38,643評論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡菱皆,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出挨稿,到底是詐尸還是另有隱情仇轻,我是刑警寧澤,帶...
    沈念sama閱讀 34,306評論 4 330
  • 正文 年R本政府宣布奶甘,位于F島的核電站篷店,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏臭家。R本人自食惡果不足惜疲陕,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,930評論 3 313
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望侣监。 院中可真熱鬧鸭轮,春花似錦、人聲如沸橄霉。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,745評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽姓蜂。三九已至按厘,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間钱慢,已是汗流浹背逮京。 一陣腳步聲響...
    開封第一講書人閱讀 31,983評論 1 266
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留束莫,地道東北人懒棉。 一個(gè)月前我還...
    沈念sama閱讀 46,351評論 2 360
  • 正文 我出身青樓,卻偏偏與公主長得像览绿,于是被迫代替她去往敵國和親策严。 傳聞我的和親對象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,509評論 2 348

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

  • 本章描述了Actor如何被識別和定位在于一個(gè)分布式Actor系統(tǒng)。這與固有的主管層次一樣是Actor系統(tǒng)的核心內(nèi)容...
    兒哥欠三百首閱讀 1,808評論 0 0
  • Actor系統(tǒng)的實(shí)體 在Actor系統(tǒng)中,actor之間具有樹形的監(jiān)管結(jié)構(gòu)倔韭,并且actor可以跨多個(gè)網(wǎng)絡(luò)節(jié)點(diǎn)進(jìn)行透...
    JasonDing閱讀 3,334評論 2 6
  • 本章概述了監(jiān)督的原語語義和背后的概念术浪。而如何轉(zhuǎn)化為實(shí)際代碼,請參閱相應(yīng)的章節(jié)Scala和Java api寿酌。 主管的...
    兒哥欠三百首閱讀 956評論 0 0
  • 前一節(jié)解釋了Actor系統(tǒng)中Actor的層級以及構(gòu)建應(yīng)用程序的最小單元胰苏。這一節(jié)則看單個(gè)Actor,解釋它的概念并去...
    兒哥欠三百首閱讀 1,284評論 0 0
  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理份名,服務(wù)發(fā)現(xiàn)碟联,斷路器妓美,智...
    卡卡羅2017閱讀 134,633評論 18 139