Erlang 并发编程是在同一 Erlang 虚拟机上创建多个进程来实现的。而Erlang 的分布式编程可以通过在不同主机上的Erlang 虚拟机(可以运行在同一主机中或可以互相通过网络主机上)实现,其中运行Erlang 虚拟机的主机也称作Erlang 的节点。在Erlang 中,可以实现在一个Erlang 虚拟机上远程在另一个Erlang 虚拟机上创建新的工作的进程,然后利用其消息传递机制,将要计算的数据发送到另一虚拟机上的工作进程,在另一虚拟机中计算后,再使用消息传递机制将计算结果发送回来;也可以实现在一个Erlang虚拟机上以远程调用的方式在远程虚拟机上进行数据处理,并直接返回处理结果。
Erlang语言中与分布式编程有关的几个重要函数语法如下:
1.{pname,nodename}!Message
实现不同Erlang节点间的消息发送,其中pname是远程节点进程的注册名,nodename是远程节点名。
2.spawn(nodename,modulename,fun,[arg1,arg2..])
实现在远程节点上启动一个进程,与spawn/3相比只是多了个节点名……
3.rpc:call(nodename,modulename,fun,[arg1,arg2..])
实现远程调用的函数,它是Erlang标准库中的模块rpc中的函数,其参数与2中相同。
4.node()
返回本地节点名称
Erlang节点的启动方法:
1.在同一主机上启动多个Erlang节点命令行格式如下:
erl -sname nodename
使用短名称的形式启动一个名称为nodename的节点,其节点名称为启动后Erlang命令提示符所示,比如Erlang命令提示符为:
(ndb@USER-20170714FN)2>
则其节点名称为:ndb@USER-20170714FN。
2.在可以互相通信的主机上分别启动Erlang节点命令行格式如下:
erl -name nodename -setcookie abc
与1大致相同,区别是使用参数设置了节点的cookie,如果要实现节点间的通信,就需要多个节点的cookie的值完全相同。而1中在同一主机中,会自动设置为相同的cookie,所以没有进行显式的设置。
以下举一简单实例:
-module(nodetest).
-compile(export_all).
remotes() ->
receive
{From,Data} ->
From!"Remote recved:" ++ Data,
io:format("~s~n",[Data])
end,
remotes().
recv() ->
receive
Data -> io:format("~s~n",[Data])
end,
recv().
其中定义了一个remotes/0函数,可以将收到的消息输出后发回对方;recv/0函数只是简单的接收消息并输出。
上图即为在同一主机上不同节点的运行实例,在上一个窗口所示的节点ndb@USER-20170714FN中:
语句1在本地节点启动一个新进程运行函数recv/0,并注册名称为lrecv;
语句2在远程节点启动一个新进程运行函数remotes/0,返回远程进程的PID;
语句3向远程节点的进程发送一条消息,包括本地接收消息的进程名和本地节点名和一个字符串消息;
之后显示了三行内容:第一行为语句3返回值;第二行为远程进程收到的字符串消息并输出;第三行为本地进程lrecv收到的消息并输出。
在节点nda@USER-20170714FN窗口中似乎没有运行什么,你可以通过调用i()函数看到运行的函数remotes,如下图(部分截图):
其中有nodetest:remotes/0的运行提示。
如果在网络中不同主机上建立Erlang节点,则需要DNS支持,并且各节点使用-name参数和相同的cookie,同时防火墙应开启TCP和UDP的4396端口。这里仅在虚拟机和物理机的局域网中作相关测试如下图:
由于没有DNS支持,所以在启动节点时使用节点名@IP的形式,如“abc@192.168.1.213”,上面的窗口是WIN7下启动的Erlang节点,而下面的窗口是虚拟机中Fedora26中的Erlang节点,其中语句1在WIN7中的Erlang节点上远程启动了进程,以运行remotes/0函数,在cde节点上通过i()命令可以查看到正在运行的进程。
文章推送公众号: