文章目录

Erlang 分布式:节点间通信

发布于 2026-04-14 02:26:55 · 浏览 28 次 · 评论 0 条

Erlang 分布式:节点间通信

Erlang 最初就是为了电信级的高可用性分布式系统设计的。其内置的分布式机制允许运行在不同机器(或同一台机器的不同端口)上的 Erlang 虚拟机像处理本地进程一样处理远程进程。本文将指导你一步步搭建两个 Erlang 节点,并实现它们之间的基础通信。


一、 基础准备与环境检查

Erlang 节点之间的通信依赖于一个共享的“魔法 Cookie”,只有持有相同 Cookie 的节点才能互相通信。默认情况下,Erlang 会读取用户主目录下的 .erlang.cookie 文件。为了演示方便,我们将通过命令行参数手动指定 Cookie,以确保两个节点一致。

  1. 打开终端(Terminal 或 Command Prompt)。
  2. 输入以下命令检查 Erlang 是否已安装:
    erl -version

    如果输出了版本号,则环境已就绪。


二、 启动第一个节点(Node A)

我们需要启动一个具有特定名称的 Erlang 节点。节点名称分为长名称(使用全限定域名)和短名称(使用主机名)。为了在本地测试方便,这里使用短名称模式。

  1. 运行以下命令启动节点 A,并设置 Cookie 为 secret_cookie

    erl -sname s1 -setcookie secret_cookie
    • -sname s1:将节点命名为 s1
    • -setcookie secret_cookie:设置安全口令。
  2. 观察命令行提示符。进入 Erlang Shell 后,提示符通常会显示 (s1@your-hostname)1>,表示当前位于节点 s1 上。


三、 启动第二个节点(Node B)

保持节点 A 的终端窗口运行,打开一个新的终端窗口。

  1. 运行以下命令启动节点 B,Cookie 必须与节点 A 完全一致:

    erl -sname s2 -setcookie secret_cookie
  2. 确认提示符显示为 (s2@your-hostname)1>

此时,系统中已经存在两个独立的 Erlang 节点,但它们尚未建立连接。


四、 建立节点连接

在 Erlang 中,节点之间的连接是透明的,通常在第一次尝试通信时自动建立。我们也可以通过 net_adm:ping 手动检测并建立连接。

  1. 切换到节点 B(s2)的终端窗口。

  2. 输入以下命令尝试连接节点 A:

    net_adm:ping(s1@your-hostname).

    注意:请将 your-hostname 替换为你实际的计算机名,或者直接使用 localhost(如果在某些系统配置下可行,通常短名称对应实际主机名)。如果在同一台机器上,通常是 s1@ 加上你的主机名。

    如果 net_adm:ping 返回 pong,说明连接成功;如果返回 pang,说明连接失败(通常是 Cookie 不匹配或节点名错误)。

  3. 验证连接状态。在节点 B 上输入

    nodes().

    该命令会返回一个列表,包含当前已连接的所有远程节点。如果列表中包含 s1@your-hostname,说明连接已建立。

为了更直观地理解这一过程,以下是节点握手与通信的流程:

sequenceDiagram autonumber participant "Node B (s2)" as NB participant "Node A (s1)" as NA NB->>NA: "net_adm:ping(Pid)" NA-->>NB: "pong (Connection Established)" NB->>NB: "nodes() returns [s1@host]"

五、 跨节点消息传递

连接建立后,我们可以像发送本地消息一样向远程进程发送消息。

  1. 切换到节点 A(s1)的终端窗口。

  2. 注册一个全局进程。为了简单起见,我们注册一个名为 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 命令。

  3. 切换回节点 B(s2)的终端窗口。

  4. 发送消息给节点 A 上的 test_server 进程:

    {test_server, s1@your-hostname} ! {hello, self()}.
  5. 观察节点 A(s1)的终端窗口。你应该会看到输出打印:

    Received hello from <0.85.0>

    <0.85.0> 是节点 B 上发送消息的进程标识符)。


六、 远程过程调用 (RPC)

除了发送原始消息,Erlang 提供了强大的 RPC(Remote Procedure Call)机制,允许你像调用本地函数一样执行远程节点上的代码。

  1. 在节点 B(s2)上,使用 rpc:call 调用节点 A 上的 erlang:time/0 函数:

    rpc:call(s1@your-hostname, erlang, time, []).
  2. 查看返回结果。你应该会得到节点 A 所在机器的当前时间,例如 {18, 30, 45}


七、 进阶:分布式监控机制

Erlang 的分布式特性允许一个节点监控另一个节点的存活性。如果被监控的节点断开连接,监控节点会收到通知。

  1. 在节点 B(s2)上,监控节点 A:

    erlang:monitor_node(s1@your-hostname, true).

    如果返回 true,说明监控已生效。

  2. 模拟节点 A 崩溃。切换到节点 A 的终端,按下 Ctrl + C,然后输入 a 并回车,强制停止节点。

  3. 观察节点 B 的终端。你会立即收到一条消息:

    {nodedown, s1@your-hostname}

    这正是构建高可用系统(如自动故障转移)的基础信号。

评论 (0)

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

扫一扫,手机查看

扫描上方二维码,在手机上查看本文