Erlang 分布式:节点间通信
Erlang 最初就是为了电信级的高可用性分布式系统设计的。其内置的分布式机制允许运行在不同机器(或同一台机器的不同端口)上的 Erlang 虚拟机像处理本地进程一样处理远程进程。本文将指导你一步步搭建两个 Erlang 节点,并实现它们之间的基础通信。
一、 基础准备与环境检查
Erlang 节点之间的通信依赖于一个共享的“魔法 Cookie”,只有持有相同 Cookie 的节点才能互相通信。默认情况下,Erlang 会读取用户主目录下的 .erlang.cookie 文件。为了演示方便,我们将通过命令行参数手动指定 Cookie,以确保两个节点一致。
- 打开终端(Terminal 或 Command Prompt)。
- 输入以下命令检查 Erlang 是否已安装:
erl -version如果输出了版本号,则环境已就绪。
二、 启动第一个节点(Node A)
我们需要启动一个具有特定名称的 Erlang 节点。节点名称分为长名称(使用全限定域名)和短名称(使用主机名)。为了在本地测试方便,这里使用短名称模式。
-
运行以下命令启动节点 A,并设置 Cookie 为
secret_cookie:erl -sname s1 -setcookie secret_cookie-sname s1:将节点命名为s1。-setcookie secret_cookie:设置安全口令。
-
观察命令行提示符。进入 Erlang Shell 后,提示符通常会显示
(s1@your-hostname)1>,表示当前位于节点s1上。
三、 启动第二个节点(Node B)
保持节点 A 的终端窗口运行,打开一个新的终端窗口。
-
运行以下命令启动节点 B,Cookie 必须与节点 A 完全一致:
erl -sname s2 -setcookie secret_cookie -
确认提示符显示为
(s2@your-hostname)1>。
此时,系统中已经存在两个独立的 Erlang 节点,但它们尚未建立连接。
四、 建立节点连接
在 Erlang 中,节点之间的连接是透明的,通常在第一次尝试通信时自动建立。我们也可以通过 net_adm:ping 手动检测并建立连接。
-
切换到节点 B(
s2)的终端窗口。 -
输入以下命令尝试连接节点 A:
net_adm:ping(s1@your-hostname).注意:请将
your-hostname替换为你实际的计算机名,或者直接使用localhost(如果在某些系统配置下可行,通常短名称对应实际主机名)。如果在同一台机器上,通常是s1@加上你的主机名。如果
net_adm:ping返回pong,说明连接成功;如果返回pang,说明连接失败(通常是 Cookie 不匹配或节点名错误)。 -
验证连接状态。在节点 B 上输入:
nodes().该命令会返回一个列表,包含当前已连接的所有远程节点。如果列表中包含
s1@your-hostname,说明连接已建立。
为了更直观地理解这一过程,以下是节点握手与通信的流程:
五、 跨节点消息传递
连接建立后,我们可以像发送本地消息一样向远程进程发送消息。
-
切换到节点 A(
s1)的终端窗口。 -
注册一个全局进程。为了简单起见,我们注册一个名为
test_server的模块:register(test_server, spawn(fun() -> loop() end)).这里假设我们定义了一个简单的
loop/0函数用于接收消息。为了快速测试,先直接在 Shell 定义该函数:loop() -> receive {hello, From} -> io:format("Received hello from ~p~n", [From]), loop(); stop -> ok end.然后执行第 2 步的
register命令。 -
切换回节点 B(
s2)的终端窗口。 -
发送消息给节点 A 上的
test_server进程:{test_server, s1@your-hostname} ! {hello, self()}. -
观察节点 A(
s1)的终端窗口。你应该会看到输出打印:Received hello from <0.85.0>(
<0.85.0>是节点 B 上发送消息的进程标识符)。
六、 远程过程调用 (RPC)
除了发送原始消息,Erlang 提供了强大的 RPC(Remote Procedure Call)机制,允许你像调用本地函数一样执行远程节点上的代码。
-
在节点 B(
s2)上,使用rpc:call调用节点 A 上的erlang:time/0函数:rpc:call(s1@your-hostname, erlang, time, []). -
查看返回结果。你应该会得到节点 A 所在机器的当前时间,例如
{18, 30, 45}。
七、 进阶:分布式监控机制
Erlang 的分布式特性允许一个节点监控另一个节点的存活性。如果被监控的节点断开连接,监控节点会收到通知。
-
在节点 B(
s2)上,监控节点 A:erlang:monitor_node(s1@your-hostname, true).如果返回
true,说明监控已生效。 -
模拟节点 A 崩溃。切换到节点 A 的终端,按下
Ctrl + C,然后输入a并回车,强制停止节点。 -
观察节点 B 的终端。你会立即收到一条消息:
{nodedown, s1@your-hostname}这正是构建高可用系统(如自动故障转移)的基础信号。

暂无评论,快来抢沙发吧!