Elixir 分散式平臺

wang_yb發表於2018-05-15

概述

分散式平臺的核心在於併發,容錯。 而 Elixir 的優勢正是在於對於併發和容錯的處理。

分散式模型

  1. CSP(Communicating Sequential Process) 模型 :: 多個程式通過管道(channel)進行互動
  2. Actor 模型 :: 每個程式管理自己的內部狀態,通過訊息和外界互動

對於 CSP 來說,重點在與 channel,通過 channel 管理併發的任務,並不關心執行任務的執行者。 Actor 模型關心的是任務的執行者(也就是 Actor),每個 Actor 都是可以通過訊息和外界互動,根據訊息完成任務。

Elixir 採用的是 Actor 模型,golang 的併發是 CSP 模型。

併發

並行(concurrency)經常會和並行(parallelize)的概率混淆,併發是指同時發生,並行是指同時執行, 比如,在一個 4core 的機器上,併發的量可能上萬,但是並行可能只有 4。

Elixir 的併發是由 BEAM VM 來管理的,理論上,一個 BEAM VM 上可以建立 268,000,000 個程式,基本就可以當做是無限制。 一般來說,BEAM VM 都是通過少量的排程程式來管理大量的 processes Elixir 的併發程式之間不會共享任何東西(包括記憶體在內)。

容錯

對錯誤的處理方式,最普遍的就是 try/catch,這種方式對於單機的系統來說可以適用,但是對於分散式系統來說,存在不足之處:

  • 分散式系統涉及多個系統間的互動,try/catch 只能在單點上捕獲異常
  • 分散式系統中可能發生的錯誤往往很難重現,也無法預測,即使捕獲到異常,也很難預置處理方式,也就是很多異常會導致系統無法恢復
  • try/catch 機制一般都是捕獲錯誤,然後自己處理或者直接往上層拋異常,隨著系統的複雜,異常的層級也會越來越多

Elixir 中也有類似 try/catch 的機制,但是它的容錯性不是依靠這種機制來保證的。 Elixir 不是致力於去減少錯誤的發生,而是致力於提供一種機制去減少錯誤的影響,並使得系統能夠自己從錯誤中恢復。

Elixir 中通過程式樹來確保整個應用的可用性,少數幾個程式作為 supervisor,用來監管其他完成實際業務的程式。 如果程式出現問題,由 supervisor 程式負責重啟或者銷燬。

除了程式樹,對於分散式系統的容錯,Erlang 的理念是 let it crash 原因也就是因為在分散式系統中,很多的錯誤和環境相關,難於重現,並且很多時候在錯誤的基礎上恢復系統相當困難, 遠遠沒有直接重啟來的簡單有效。

當然,let it crash 不是 let everything crash,以下情況還是要處理:

-   對於關鍵性的程式,是絕對不能讓它 crash 的,比如有些主幹上的 supervisor
-   可以預期的錯誤,就要有對應的錯誤處理,不能什麼都靠重啟來解決
-   let it crash 是指把那些無法預期的錯誤交給 supervisor 來處理

OTP 平臺

OTP 平臺的分散式系統核心是 processmessage Elixir 本身也可以實現非常健壯的分散式系統,但是藉助 OTP 平臺上已經成熟的元件,可以更快的建立一個分散式應用

下面是 OTP 平臺上提供的成熟元件:(各個元件的示例參考:http://www.cnblogs.com/wang_yb/p/5589257.html)

  1. agent
  2. GenServer
  3. GenEvent
  4. task
  5. supervisor

相關文章