Erlang入門(三)——分布式編程
明天要回家一個星期了,好好休息下。今天找到別人翻譯的Erlang編程手冊,值的好好讀一遍。所謂分布式的Erlang應用是運行在一係列Erlang節點組成的網絡之上。這樣的係統的性質與單一節點上的Erlang係統並沒有什麼不同。分布式這是個“大詞”,Erlang從語言原生角度支持分布式編程,相比於java簡單不少。
一、分布式機製
下列的BIFs是用於分布式編程:
spawn(Node, Mod, Func, Args)
啟動遠程節點的一個進程
spawn_link(Node, Mod, Func, Args)
啟動遠程節點的一個進程並創建連接到該進程
monitor_node(Node, Flag)
如果Flag是true,這個函數將使調用(該函數)的進程可以監控節點Node。如果節點已經舍棄或者並不存在,調用的進程將收到一個{nodedown,Node}的消息。如果Flag是false,監控將被關閉
node()
返回我們自己的進程name
nodes()
返回其他已知的節點name列表
node(Item)
返回原來Item的節點名稱,Item可以是Pid,引用(reference)或者端口(port)
disconnect_node(Nodename)
從節點Nodename斷開。
節點是分布式Erlang的核心概念。在一個分布式Erlang應用中,術語(term)節點(node)意味著一個可以加入分布式transactions的運行係統。通過一個稱為net kernal的特殊進程,一個獨立的Erlang係統可以成為一個分布式Erlang係統的一部分。當net kernal進程啟動的時候,我們稱係統是alive的。
與遠程節點上的進程進行通信,與同一節點內的進程通信隻有一點不同:
{Name, Node} ! Mess.
顯然,需要接收方增加一個參數Node用於指定接受進程所在的節點。節點的name一般是用@隔開的atom類型,比如pong@dennis,表示計算機名為dennis上的pong節點。通過執行:
erl -sname pong
將在執行的計算機中創建一個節點pong。為了運行下麵的例子,你可能需要兩台計算機,如果隻有一台,隻要同時開兩個Erlang係統並以不同的節點名稱運行也可以。二、一些例子。
這個例子完全來自上麵提到的翻譯的連接,關於分布式編程的章節。我增加了截圖和說明。
首先是代碼:
-module(tut17).
-export([start_ping/1, start_pong/0, ping/2, pong/0]).
ping(0, Pong_Node) ->
{pong, Pong_Node} ! finished,
io:format("ping finished~n", []);
ping(N, Pong_Node) ->
{pong, Pong_Node} ! {ping, self()},
receive
pong ->
io:format("Ping received pong~n", [])
end,
ping(N - 1, Pong_Node).
pong() ->
receive
finished ->
io:format("Pong finished~n", []);
{ping, Ping_PID} ->
io:format("Pong received ping~n", []),
Ping_PID ! pong,
pong()
end.
start_pong() ->
register(pong, spawn(tut17, pong, [])).
start_ping(Pong_Node) ->
spawn(tut17, ping, [3, Pong_Node]).
-export([start_ping/1, start_pong/0, ping/2, pong/0]).
ping(0, Pong_Node) ->
{pong, Pong_Node} ! finished,
io:format("ping finished~n", []);
ping(N, Pong_Node) ->
{pong, Pong_Node} ! {ping, self()},
receive
pong ->
io:format("Ping received pong~n", [])
end,
ping(N - 1, Pong_Node).
pong() ->
receive
finished ->
io:format("Pong finished~n", []);
{ping, Ping_PID} ->
io:format("Pong received ping~n", []),
Ping_PID ! pong,
pong()
end.
start_pong() ->
register(pong, spawn(tut17, pong, [])).
start_ping(Pong_Node) ->
spawn(tut17, ping, [3, Pong_Node]).
代碼是創建兩個相互通信的進程,相互發送消息並通過io顯示在屏幕上,本來是一個單一係統的例子,現在我們讓兩個進程運行在不同的兩個節點上。注意start_ping方法,創建的進程調用ping方法,ping方法有兩個參數,一個是發送消息的次數,一個就是遠程節點的name了,也就是我們將要創建的進程pong的所在節點。start_pong創建一個調用函數pong的進程,並注冊為名字pong(因此在ping方法中可以直接發送消息給pong)。
我是在windows機器上測試,首先打開兩個cmd窗口,並cd到Erlang的安裝目錄下的bin目錄,比如C:\Program Files\erl5.5.3\bin,將上麵的程序存為tut17.erl,並拷貝到同一個目錄下。我們將創建兩個節點,一個叫ping@dennis,一個叫pong@dennis,其中dennis是我的機器名。見下圖:

采用同樣的命令
erl -sname ping
創建ping節點。然後在pong節點下執行start_pong():
OK,這樣就在節點pong上啟動了pong進程,然後在ping節點調用start_ping,傳入參數就是pong@dennis
tut17:start_ping(pong@dennis).
執行結果如下圖:
同樣在pong節點上也可以看到:

結果如我們預期的那樣,不同節點上的兩個進程相互通信如此簡單。我們給模塊tut17增加一個方法,用於啟動遠程進程,也就是調用spawn(Node,Module,Func,Args)方法:
start(Ping_Node) ->
register(pong, spawn(tut17, pong, [])),
spawn(Ping_Node, tut17, ping, [3, node()]).
register(pong, spawn(tut17, pong, [])),
spawn(Ping_Node, tut17, ping, [3, node()]).
pong進程啟動Ping_Node節點上的進程ping。具體結果不再給出。
文章轉自莊周夢蝶 ,原文發布時間5.17
最後更新:2017-05-17 14:02:03
上一篇:
Kubernetes是Docker的終結者?我不認同!
下一篇:
當當網架構師:從碼農到大牛,技術與心境的雙重提升
學生專享:雲翼計劃(雲主機118元/年) –這是大學生成長計劃,為了更好的明天,讓自己脫穎而出!
ASP.NET MVC中的ActionFilter是如何執行的?
作為Python學習者你應該知道的Python常用技巧
表格存儲(TableStore)新功能Stream應用場景介紹
Linux網絡設置2——虛擬機中的Linux和Windows網絡互通設置
阿裏2018校招啟動—找對味,搏出way!
Oracle 12.2新特性掌上手冊 - 第三卷 Sharding 的增強
服務器管理助手Linux版(寶塔)新版安裝,支持一鍵SSL配置
《深入解析IPv6(第3版)》——11.5 參考資料
Android 中文件類型與MIME的匹配表