閱讀292 返回首頁    go 阿裏雲 go 技術社區[雲棲]


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]).

    代碼是創建兩個相互通信的進程,相互發送消息並通過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()]).

pong進程啟動Ping_Node節點上的進程ping。具體結果不再給出。

文章轉自莊周夢蝶  ,原文發布時間5.17

最後更新:2017-05-17 14:02:03

  上一篇:go  Kubernetes是Docker的終結者?我不認同!
  下一篇:go  當當網架構師:從碼農到大牛,技術與心境的雙重提升