檢視原始碼 分散式 Erlang
分散式 Erlang 系統
一個分散式 Erlang 系統由多個彼此通訊的 Erlang 執行時期系統組成。每個這樣的執行時期系統都稱為一個節點。當使用 PID 時,不同節點上的程序之間的訊息傳遞,以及連結和監視器都是透明的。然而,註冊名稱對於每個節點都是本地的。這表示在使用註冊名稱發送訊息等操作時,也必須指定節點。
分散機制是使用 TCP/IP socket 實作的。關於如何實作替代載體的描述,請參閱 ERTS 使用者指南。
警告
啟動分散式節點時,若未同時指定
-proto_dist inet_tls
,將會使節點暴露於攻擊之下,攻擊者可能完全存取該節點,並延伸至叢集。當使用不安全的分散式節點時,請確保網路已設定為防止潛在的攻擊者進入。有關如何設定安全分散式節點的詳細資訊,請參閱 使用 SSL 進行 Erlang 分散 使用者指南。
節點
一個節點是一個正在執行的 Erlang 執行時期系統,使用命令列旗標 -name
(長名稱)或 -sname
(短名稱)賦予名稱。
節點名稱的格式是一個原子 name@host
。name
是使用者給定的名稱。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 檔案)的分散式系統可以使用這種方式處理。
注意
透過此設定,
Node1
和Node2
同意要使用的 cookie:Node1
對Node2
使用其明確設定的DiffCookie
,而Node2
使用其預設 cookieDiffCookie
。如果您也在建立連線之前在
Node2
中呼叫erlang:set_cookie(Node1, DiffCookie)
,您也可以使用Node1
和Node2
都沒有作為其預設 cookie 的DiffCookie
。由於在選擇 cookie 之前會在連線設定期間交換節點名稱,因此連線設定的運作方式與哪個節點啟動它無關。
請注意,將
Node1
設定為與Node2
通訊時使用Node2
的預設 cookie,反之亦然會導致設定損壞(如果 cookie 不同),因為這兩個節點都會使用另一個節點的(不同的)cookie。
在兩個節點之間建立連線時,預設是立即連線所有其他可見節點。這樣,始終會有一個完全連線的網路。如果存在具有不同 cookie 的節點,則此方法可能不適用(因為可能無法為所有可能的節點設定不同的 cookie),並且必須設定命令列旗標 -connect_all false
,請參閱 ERTS 中的 erl 可執行檔。
可以使用呼叫 erlang:get_cookie()
來擷取本機節點的魔術 cookie。
分散式 BIF
以下是一些對分散式程式設計有用的 BIF
disconnect_node(Node)
- 強制斷開節點的連線。erlang:get_cookie/0
- 返回目前節點的魔法 Cookie。erlang:get_cookie(Node)
- 返回節點Node
的魔法 Cookie。is_alive/0
- 如果執行時期系統是節點並且可以連接到其他節點,則返回true
,否則返回false
。monitor_node(Node, Bool)
- 監控Node
的狀態。如果與它的連線遺失,將收到訊息{nodedown, Node}
。node/0
- 返回目前節點的名稱。允許在守護中使用。node(Arg)
- 返回Arg
(一個 pid、參考或 port)所在的節點。nodes/0
- 返回此節點連接的所有可見節點的列表。nodes(Arg)
- 根據Arg
,此函數可以返回不僅是可見節點的列表,還包括隱藏節點和先前已知的節點等等。erlang:set_cookie(Cookie)
- 設定當連接所有沒有使用erlang:set_cookie/2
明確設定 Cookie 的節點時要使用的魔法 CookieCookie
。erlang:set_cookie(Node, Cookie)
- 設定連接Node
時使用的魔法 Cookie。如果Node
是目前的節點,則當連接所有沒有使用此函數明確設定 Cookie 的節點時,將使用Cookie
。spawn_link(Node, Fun)
- 在遠端節點建立一個行程。spawn_opt(Node, Fun, Opts)
- 在遠端節點建立一個行程。spawn_link(Node, Module, Name, Args)
- 在遠端節點建立一個行程。spawn_opt(Node, Module, Name, Args, Opts)
- 在遠端節點建立一個行程。
表格:分佈式 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_kernel | Erlang 網路核心。 |
表格:Kernel 應用程式中對分佈式有用的模組。
在 STDLIB 應用程式中
模組 | 說明 |
---|---|
peer | 同層級節點的啟動和控制。 |
表格:STDLIB 應用程式中對分佈式有用的模組。