首页 > Erlang快速入门 > 4.4 Erlang快速入门之分布式编程
2013
11-03

4.4 Erlang快速入门之分布式编程

BACK TOP文章索引

  1. Erlang分布式编程
  2. 共12条评论

Erlang分布式编程

现在我们来重写ping pong例子,其中ping和pong都在不同的计算机上。在我们做这件事情之前,这里有一些事情需要首先做到。分布式Erlang的实现提供了自有的安全机制来预防未经授权的Erlang系统访问。Erlang系统与别的机器进行交互时必须有同样的magic cookie(魔法甜饼)。最简单的实现方法就是建立一个.erlang.cookie文件在home目录,并且复制到其他所有打算运行Erlang系统的机器上(如果是用的是Windows系统,那么就是环境变量$HOME所指的目录,可能需要我们手动进行设定),在UNIX或者LINUX系统下可以安全的忽略上面的东西并且只需要简单的创建一个.erlang.cookie文件就可以了。该文件需要包含一行常量,例如在LINUX系统上,我们可以这样设定:

$ cd
$ cat > .erlang.cookie
this_is_very_secret
$ chmod 400 .erlang.cookie 

这个 chmod 命令让.erlang.cookie的文件访问许可只能限定于文件的所有者,这是必须的。
当我们启动一个Erlang系统并且试图与别的Erlang系统进行交互时,我们必须给定名称:
erl -sname my_name
我们稍后将看到更多的细节。如果你打算尝试分布式Erlang,但是只有一台计算机,你可以同时打开两个Erlang环境在同一台计算机上,然后赋予他们不同的名称就可以了(使用上面的操作系统shell下的命令)。每个运行在计算机上的Erlang系统都被称为一个节点(Node)。
(注意:erl -sname 命令假定所有节点都在同一个IP域内,如果我们需要在不同的域内使用,就用-name参数代替原有的参数,但是必须给出所有的IP地址)
这里是修改后分别运行在不同节点上的ping pong例子:

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

让我们假设我们有两台计算机分别叫做gollum和kosken。我们首先打开在计算机kosken上打开一个节点,称为ping,然后打开gollum,叫做pong。
在kosken上(在一台Linux系统上):

kosken> erl -sname ping
Erlang (BEAM) emulator version 5.2.3.7 [hipe] [threads:0]
Eshell V5.2.3.7  (abort with ^G)
(ping@kosken)1>    

在gollum上(在一台Windows系统上) :

gollum> erl -sname pong
Erlang (BEAM) emulator version 5.2.3.7 [hipe] [threads:0]
Eshell V5.2.3.7  (abort with ^G)
(pong@gollum)1>    
</pre?
现在我们在gollum上开始“pong”进程:
<pre lang="shell">
(pong@gollum)1> tut17:start_pong().
true    

然后再kosken上开始“ping”进程(从上面的代码中我们可以看到start_ping函数的一个参数是pong所运行的Erlang系统的名称):

(ping@kosken)1> tut17:start_ping(pong@gollum).
<0.37.0>
Ping received pong
Ping received pong 
Ping received pong
ping finished    

这里我们可以看到ping pong例子运行起来了,在“pong”一端,我们可以看到:

(pong@gollum)2>
Pong received ping                 
Pong received ping                 
Pong received ping                 
Pong finished                      
(pong@gollum)2>    

看看tut17中的代码,我们研究一下pong函数,发现并没有和前面的例子有什么改变:

{ping, Ping_PID} ->
    io:format("Pong received ping~n", []),
    Ping_PID ! pong,    

这里的工作与运行“ping”的节点完全无关。Erlang的pid包含了关于进程在何处执行的信息,所以如果你知道一个进程的pid,操作符“!”就可以被用来向这个进程传递消息,而不论该进程是否是在本机还是在远程。
一个不同点在于,如果是在另一个节点上的有名称的进程,我们对其发送消息:
{pong, Pong_Node} ! {ping, self()},
我们使用元组{regiestered_name,node_name}替换只是使用registered_name。
在之前的例子,我们开始“ping”和“pong”与不同的节点。spawn可以被用来启动其他节点上的进程。下面的例子还是ping pong程序,不过我们这次将“远程”启动进程:

-module(tut18).
-export([start/1,  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(Ping_Node) ->
    register(pong, spawn(tut18, pong, [])),
    spawn(Ping_Node, tut18, ping, [3, node()]).    

假定一个Erlang系统叫做“ping”(不是“ping”进程哈)已经在kosken上启动了,那么我们在gollum上操作:

(pong@gollum)1> tut18:start(ping@kosken).
<3934.39.0>
Pong received ping
Ping received pong
Pong received ping
Ping received pong
Pong received ping
Ping received pong
Pong finished
ping finished    

注意这里所有的输出都在gollum上。这是因为io系统会找寻进程创建的位置,并在该位置进行输出。


4.4 Erlang快速入门之分布式编程》有 12 条评论

  1. Angel+Baby 说:

    这个教程还不错啦,开通了社区,以后可以来这看看!

  2. 代码ldd 说:

    不错,对erlang 越来越感兴趣了,花几天时间把他给看完

  3. 网站不错很漂亮,欢迎互访!

  4. 漫画很棒 ~ = = ~ !!!!!! 要更新快啊

  5. 每次都成功的失败

  6. 每次都成功的失败

  7. 每次都成功的失败

  8. 每次都成功的失败

  9. 每次都成功的失败

  10. 每次都成功的失败

  11. 每次都成功的失败

留下一个回复

你的email不会被公开。