Erlang仅仅能在具有相同的magic cookie系统之间的直接对话。如果想要在几台机器之间运行相互通信的Erlang程序,最简单的方法就是放置一个名叫".erlang.cookie"的文件在每个机器的$HOME目录里,并且把该文件的权限设置为400,该文件的内容即cookie名字。400权限意味着该文件仅能被此文件的owner访问。
$ cat .erlang.cookie
this is very secret
$ chmod 400 .erlang.cookie
Erlang支持分布式通信的两大基石
1. 进程间通过拷贝通信(Process communication by copying)
2. 透明的位置信息(Location transparency)
Erlang自己会保证进程标识符在运行网络上的唯一,即便是跨机器(Erlang guarantees that process identifiers are unique on the network, even across machines.)也一样。
每一个Erlang VM都叫作一个节点(Node),当两个或者多个Node都知道了对方之后,这些节点就形成了集群(Cluster)。Erlang集群默认情况下是完全连接(fully connected)的,即Erlang集群中的每一个节点都知道每一个其他的节点,并且相互之间能够直接通信。正因为如此,在实际中Erlang通常只有几十个节点,一般不会有几百个或者更多的节点,因为在完全连接的网络中,节点越多,保持节点之间的通信开销越大。
但是可以通过某个特殊的节点,将多个cluster连接成一个更大的cluster,这样的cluster不是完全连接的,cluster直接是通过这个特殊的节点连接的。
在Erlang集群中,节点不会主动去寻找其他节点,除非他寻找其他节点有事要做;在找到其他节点之后,他们会相互追踪对方,并且交换彼此所知道的其他节点信息,以便于形成一个完全连接的网络。
每个节点都有自己的名字(Name),其他节点就是通过这个名字来查找到该节点,并且与之交互。通过内建函数node()可以取得当前节点的名字,节点的名字格式为: nodename@hostname。如果一个节点运行在非分布式模式下,则该节点的名字默认是nonode@nohost。在单台机器上允许同时运行多个节点。
如何启动一个节点?
启动一个节点可以使用命令
-name选项用在有DNS正常工作的普通网络中,即可以正常使用完全限定名(fully qualified name)的网络环境中。
或者
当完全限定名(fully qualified name)不起作用的时候,使用-sname选项。这种情况经常发生在局域网的生产环境中。比如在局域网中不能通过域名访问其他机器时,你只能使用短名称(sname)访问。
只要所有节点都在同一个子网中,短名称就起作用。
使用短名称和长名称的节点会使用不同的通信模式工作。在同一个Erlang集群中,所有节点必须使用统一的通信模式,或者使用长名称,或者都是用短名称,不可混用。
当Erlang VM作为一个节点运行时,他的节点名称会显示在命令行提示符中,比如我启动了一个名叫guibin的短名称节点:
Erlang R14B01 (erts-5.8.2) [source] [smp:2:2] [rq:2] [async-threads:0] [hipe] [kernel-poll:false]
Eshell V5.8.2 (abort with ^G)
(guibin@localhost)1>
Erlang nodes是如何找到对方并通信?
负责Erlang节点间通信的是一个叫作epmd(Erlang Port Mapper Daemon)的后台线程。如下:
305 ?? S 0:00.02 /opt/local/lib/erlang/erts-5.8.2/bin/epmd -daemon
513 s003 U+ 0:00.00 grep epmd
当启动一个node时,node会检查本机是否有epmd在运行,如果没有则启动epmd。epmd启动之后会跟踪记录所有本机运行的node和这些node被分配的端口号。
当一个在本机的node想和远程的node通信时,本地的epmd首先会和远程的epmd通信(默认在4369端口上使用TCP/IP),询问是否有相应的node在那里运行。如果有,则远程的epmd会响应请求,并直接和本地的epmd通信。
但是epmd不会自动去寻找其他的epmd,这些通信和寻找过程必须被node的查找操作触发。
注意:Erlang默认的分布模型是基于所有集群中的机器都运行在一个被信任和可靠的网络中。如果实际运行的网络环境并非如此信任和可靠,而是通过广域网连接,则集群中的机器间通信应该直接使用TCP(或者UDP,或者SCTP)。或者也可以基于SSL、SSH或者IPsec建立隧道通信。
Erlang基于cookie的安全系统
如果在一台机器上至少启动过一次node之后,就会生成cookie文件。初次启动node,node会自动生成由随机字符串组成的cookie。默认情况下,一个node认为其他的能和他通信的node都具有相同的cookie。
推荐只有owner才对cookie文件具有读的权限,即400。
Erlang分布式控制常用命令选项
命令erl用来启动Erlang的运行时系统(Erlang runtime system)。
这个选项使得启动的Erlang的运行时系统处于分布式模式下,节点名称为NodeName@FullyQualifiedName。
这个选项使得启动的Erlang的运行时系统也处于分布式模式下,节点名称为NodeName@ShortName。
该选项设置当前节点的Magic Cookie为Cookie,而不使用默认的~/.erlang.cookie中的内容作为Cookie。
这个选项设置该启动节点和其他Erlang节点的连接模式为非完全连接,即该节点仅仅保存和他直接通信的节点状态,非直接连接的节点状态不理会。