檢視原始碼 分散式 Erlang

分散式 Erlang 系統

一個分散式 Erlang 系統由多個彼此通訊的 Erlang 執行時期系統組成。每個這樣的執行時期系統都稱為一個節點。當使用 PID 時,不同節點上的程序之間的訊息傳遞,以及連結和監視器都是透明的。然而,註冊名稱對於每個節點都是本地的。這表示在使用註冊名稱發送訊息等操作時,也必須指定節點。

分散機制是使用 TCP/IP socket 實作的。關於如何實作替代載體的描述,請參閱 ERTS 使用者指南

警告

啟動分散式節點時,若未同時指定 -proto_dist inet_tls,將會使節點暴露於攻擊之下,攻擊者可能完全存取該節點,並延伸至叢集。當使用不安全的分散式節點時,請確保網路已設定為防止潛在的攻擊者進入。有關如何設定安全分散式節點的詳細資訊,請參閱 使用 SSL 進行 Erlang 分散 使用者指南。

節點

一個節點是一個正在執行的 Erlang 執行時期系統,使用命令列旗標 -name(長名稱)或 -sname(短名稱)賦予名稱。

節點名稱的格式是一個原子 name@hostname 是使用者給定的名稱。host 如果使用長名稱,則是完整主機名稱;如果使用短名稱,則是主機名稱的第一部分。函式 node() 會傳回節點的名稱。

範例

% erl -name dilbert
(dilbert@uab.ericsson.se)1> node().
'dilbert@uab.ericsson.se'

% erl -sname dilbert
(dilbert@uab)1> node().
dilbert@uab

節點名稱也可以在執行時期透過呼叫 net_kernel:start/1 來給定。

範例

% erl
1> node().
nonode@nohost
2> net_kernel:start([dilbert,shortnames]).
{ok,<0.102.0>}
(dilbert@uab)3> node().
dilbert@uab

注意

具有長節點名稱的節點無法與具有短節點名稱的節點進行通訊。

節點連線

分散式 Erlang 系統中的節點是鬆散連接的。第一次使用另一個節點的名稱時,例如,如果呼叫 spawn(Node, M, F, A)net_adm:ping(Node),則會嘗試連線至該節點。

連線預設是可傳遞的。如果節點 A 連線到節點 B,而節點 B 與節點 C 有連線,則節點 A 也會嘗試連線到節點 C。可以使用命令列旗標 -connect_all false 來關閉此功能,請參閱 ERTS 中的 erl

如果節點關閉,則所有與該節點的連線都會被移除。呼叫 erlang:disconnect_node(Node) 會強制斷開節點的連線。

目前已連線的(可見)節點清單由 nodes/0 傳回。

epmd

Erlang Port Mapper Daemon epmd 會在啟動 Erlang 節點的每個主機上自動啟動。它負責將符號節點名稱映射到機器位址。請參閱 ERTS 中的 epmd

隱藏節點

在分散式 Erlang 系統中,有時在不連線到所有其他節點的情況下連線到節點會很有用。一個例子是用來檢查系統狀態的某種操作和維護功能,而不會干擾它。為此,可以使用隱藏節點

隱藏節點是以命令列旗標 -hidden 啟動的節點。隱藏節點和其他節點之間的連線不可傳遞,必須明確設定。此外,隱藏節點不會顯示在 nodes/0 傳回的節點清單中。而是必須使用 nodes(hidden)nodes(connected)。這表示,例如,隱藏節點不會被新增至 global 所追蹤的節點集合中。

動態節點名稱

如果節點名稱設定為undefined,則該節點將以特殊模式啟動,作為另一個節點的臨時客戶端。然後,該節點會從其連線的第一個節點請求動態節點名稱。此外,還會設定這些分散設定

-dist_listen false -hidden -kernel dist_auto_connect never

由於 -dist_auto_connect 設定為 never,因此必須呼叫 net_kernel:connect_node/1 才能設定連線。如果第一個建立的連線(為節點提供動態名稱)關閉,則任何其他連線也會關閉,並且節點將失去其動態節點名稱。可以再次呼叫 net_kernel:connect_node/1 來取得新的動態節點名稱。如果分散機制被捨棄然後重新設定,則節點名稱可能會變更。

變更

從 Erlang/OTP 23 開始支援動態節點名稱功能。臨時客戶端節點和第一個連接的對等節點(提供動態節點名稱)都必須至少是 Erlang/OTP 23 才能運作。

C 節點

C 節點是一個 C 程式,編寫為在分散式 Erlang 系統中充當隱藏節點。程式庫 Erl_Interface 包含用於此目的的函式。有關 C 節點的詳細資訊,請參閱 Erl_Interface 應用程式和 互通性教學

安全性

注意

此處的「安全性」並是指密碼學上的安全,而是指防止意外誤用的安全性,例如防止節點連線到不應與之通訊的叢集。

此外,節點之間的通訊預設為明文。如果您需要強大的安全性,請參閱 SSL 應用程式使用者指南中的 使用 TLS 進行 Erlang 分散

此外,以下文字中提到的預設隨機 cookie 並不是很難以預測。可以使用 crypto 模組中的基本元素產生更好的 cookie,儘管這仍然無法使初始交握在密碼學上安全。並且節點間的通訊仍然是明文。

身分驗證決定哪些節點可以彼此通訊。在不同的 Erlang 節點的網路中,它是以盡可能低的層級建構到系統中的。所有節點在連接另一個節點時都使用一個魔術 cookie,這是一個 Erlang 原子。

在連線設定期間,交換節點名稱後,會比較節點彼此呈現的魔術 cookie。如果它們不匹配,則會拒絕連線。cookie 本身從不傳輸,而是使用雜湊的挑戰來進行比較,儘管不是以密碼學安全的方式進行。

在啟動時,節點會被指派一個隨機原子作為其預設魔術 cookie,並且假設其他節點的 cookie 為 nocookie。然後,Erlang 網路驗證伺服器(auth)的第一個動作是在 使用者主目錄 中,然後在 filename:basedir(user_config, "erlang") 中搜尋名為 .erlang.cookie 的檔案。如果這些檔案都不存在,則會在使用者主目錄中建立一個 .erlang.cookie 檔案。檔案的 UNIX 權限模式設定為八進制 400(使用者唯讀),其內容為隨機字串。會從檔案內容建立一個原子 Cookie,並使用 erlang:set_cookie(Cookie) 將本機節點的 cookie 設定為此原子。這會設定本機節點將用於所有其他節點的預設 cookie。

因此,具有相同 cookie 檔案的使用者群組會擁有可以自由通訊的 Erlang 節點,因為它們使用相同的魔術 cookie。想要執行節點但 cookie 檔案位於不同檔案系統上的使用者必須確保其 cookie 檔案相同。

對於使用魔術 cookie Cookie 的節點 Node1 能夠連接到,並接受來自使用不同 cookie DiffCookie 的另一個節點 Node2 的連線,必須先在 Node1 上呼叫函式 erlang:set_cookie(Node2, DiffCookie)。具有多個主目錄(不同的 cookie 檔案)的分散式系統可以使用這種方式處理。

注意

透過此設定,Node1Node2 同意要使用的 cookie:Node1Node2 使用其明確設定的 DiffCookie,而 Node2 使用其預設 cookie DiffCookie

如果您也在建立連線之前在 Node2 中呼叫 erlang:set_cookie(Node1, DiffCookie),您也可以使用 Node1Node2 都沒有作為其預設 cookie 的 DiffCookie

由於在選擇 cookie 之前會在連線設定期間交換節點名稱,因此連線設定的運作方式與哪個節點啟動它無關。

請注意,將 Node1 設定為與 Node2 通訊時使用 Node2 的預設 cookie,反之亦然會導致設定損壞(如果 cookie 不同),因為這兩個節點都會使用另一個節點的(不同的)cookie。

在兩個節點之間建立連線時,預設是立即連線所有其他可見節點。這樣,始終會有一個完全連線的網路。如果存在具有不同 cookie 的節點,則此方法可能不適用(因為可能無法為所有可能的節點設定不同的 cookie),並且必須設定命令列旗標 -connect_all false,請參閱 ERTS 中的 erl 可執行檔。

可以使用呼叫 erlang:get_cookie() 來擷取本機節點的魔術 cookie。

分散式 BIF

以下是一些對分散式程式設計有用的 BIF

表格:分佈式 BIF

分佈式命令列標誌

用於分散式程式設計的命令列標誌範例(如需更多資訊,請參閱 ERTS 中的 erl 可執行檔)

命令列標誌說明
-connect_all false僅使用明確的連線設定。
-hidden將節點設為隱藏節點。
-name Name使用長節點名稱將執行時期系統設為節點。
-setcookie Cookie與呼叫 erlang:set_cookie(Cookie) 相同。
-setcookie Node Cookie與呼叫 erlang:set_cookie(Node, Cookie) 相同。
-sname Name使用短節點名稱將執行時期系統設為節點。

表格:分佈式命令列標誌

分佈式模組

在 Kernel 應用程式中對於分散式程式設計有用的模組範例

模組說明
global全域名稱註冊機制。
global_group將節點分組為全域名稱註冊群組。
net_adm各種 Erlang 網路管理常式。
net_kernelErlang 網路核心。

表格:Kernel 應用程式中對分佈式有用的模組。

在 STDLIB 應用程式中

模組說明
peer同層級節點的啟動和控制。

表格:STDLIB 應用程式中對分佈式有用的模組。