10 分鐘瞭解 Actor 模型

過去十幾年CPU一直遵循着摩爾定律發展,單核頻率越來越快,但是最近這幾年,摩爾定律已然失效,CPU的工藝製程和發熱穩定性之間難以取捨,取而代之的策略則是增加核心數量,目前家用電腦四核已經非常常見,服務器更是達到了32核64線程。爲了有效地利用多核CPU,我們在代碼層面就應該考慮到併發性。十幾年的痛苦開發經歷告訴我們,threads並不是獲取併發性的好方法,往往會帶來難以查找的bug,但是不用害怕,今天我們有很多其他方法來獲得易用的併發性,比如我們接下來介紹的Actor模型。

模型 Model

Actor模型是一個概念模型,用於處理併發計算。它定義了一系列系統組件應該如何動作和交互的通用規則,最著名的使用這套規則的編程語言是Erlang。這篇文章更關注模型本身而不是它在不同語言的實現。

Actors

一個Actor指的是一個最基本的計算單元。它能接收一個消息並且基於其執行計算。

這個理念很像面嚮對象語言,一個對象接收一條消息(方法調用),然後根據接收的消息做事(調用了哪個方法)。

Actors一大重要特徵在於actors之間相互隔離,它們並不互相共享內存。這點區別於上述的對象。也就是說,一個actor能維持一個私有的狀態,並且這個狀態不可能被另一個actor所改變。

聚沙成塔

One ant is no ant, one actor is no actor.
光有一個actor是不夠的,多個actors才能組成系統。在actor模型裏每個actor都有地址,所以它們才能夠相互發送消息。

Actors有郵箱

只得指明的一點是,儘管許多actors同時運行,但是一個actor只能順序地處理消息。也就是說其它actors發送了三條消息給一個actor,這個actor只能一次處理一條。所以如果你要並行處理3條消息,你需要把這條消息發給3個actors。

消息異步地傳送到actor,所以當actor正在處理消息時,新來的消息應該存儲到別的地方。Mailbox就是這些消息存儲的地方。

Actors通過異步消息溝通,在處理消息之前消息被存放在Mailbox中

Actors做什麼

當一個actor接收到消息後,它能做如下三件事中的一件:

  • Create more actors; 創建其他actors
  • Send messages to other actors; 向其他actors發送消息
  • Designates what to do with the next message. 指定下一條消息到來的行爲

前兩件事比較直觀,第三件卻很有意思。

我之前說過一個actor能維持一個私有狀態。「指定下一條消息來到做什麼」意味着可以定義下條消息來到時的狀態。更清楚地說,就是actors如何修改狀態。

設想有一個actor像計算器,它的初始狀態是數字0。當這個actor接收到add(1)消息時,它並不改變它原本的狀態,而是指定當它接收到下一個消息時,狀態會變爲1。

容錯 Fault tolerance

Erlang 引入了「隨它崩潰」的哲學理念,這部分關鍵代碼被監控着,監控者的唯一職責是知道代碼崩潰後幹什麼(如將這個單元代碼重置爲正常狀態),讓這種理念成爲可能的正是actor模型。

每段代碼都運行在process中,process是erlang稱呼actor的方式。這個process完全獨立,意味着它的狀態不會影響其他process。我們有個supervisor,實際上它只是另一個process(所有東西都是actor),當被監控的process掛了,supervisor這個process會被通知並對此進行處理。這就讓我們能創建「自愈」系統了。如果一個actor到達異常狀態並崩潰,無論如何,supervisor都可以做出反應並嘗試把它變成一致狀態,這裏有很多策略,最常見的是根據初始狀態重啓actor。

分佈式 Distribution

另一個關於actor模型的有趣方面是它並不在意消息發送到的actor是本地的或者是另外節點上的。

轉念一想,如果actor只是一些代碼,包含了一個mailbox和一個內部狀態,actor只對消息做出響應,誰會關注它運行在哪個機器上呢?只要我們能讓消息到達就行了。這允許我們基於許多計算機上構建系統,並且恢復其中任何一臺。

進一步瞭解

這裏是一個快速的概念模型回顧,其中的概念被運用到許多知名語言和庫中,比如Erlang和Elixir, Akka (for the JVM) 和 Celluloid (for Ruby)。

如果你想更深入瞭解actor及其背後的原理,你可以進一步閱讀下面書籍和文章:

這個視頻比較完整地討論了Actor的概念模型。
The Actor Model (everything you wanted to know)

Scala或Erlang的進程信箱都是一種Actor模型,也有Java的專門的Actor模型,這裏是幾種Actor模型比較明白了Actor模型原理,使用Disruptor這樣無鎖隊列也可以自己實現Actor模型,讓一個普通對象與外界的交互調用通過Disruptor消息隊列實現,比如LMAX架構就是這樣實現高頻交易,從2009年成功運行至今,被Martin Fowler推崇。

原文地址:https://www.jianshu.com/p/449850aa8e82
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章