Erlang节点互联失败原因分析以及解决方案

本文通过实际案例解析了Erlang环境下不同版本节点间的连接问题,详细介绍了问题排查及解决方案,强调了Erlang版本一致性的重要性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

转载自Erlang非业余研究

今天和项仲在部署新系统的时候发现节点间ping不成功的情况,类似

1> net_adm:ping('xx@ip1').      
pang

由于这个问题比较普遍,我就记录下一步步的排除步骤.

首先从原理上分析下!由于erlang节点间通讯是透过tcp来进行的,所以我们确保以下几点:    
1. 确保网络连接是通的,可以透过ping来查看。    
2. 确保网络连接上tcp是可以通的,可以透过netcat在二个节点所在的机器上分别开个服务器端和客户端进行验证。    
3. 确保端口是防火墙友好的。erlang的节点是登记在epmd服务上的,所以4369端口要能访问,其次节点的动态端口是可以访问的。

epmd -names      
epmd: up and running on port 4369 with data:      
name xx at port 46627      

同样可以用netcat来验证。    
4. erlang节点的cookie是一样的,可以透过setcookie来解决。

这几点确认无误后,就可以开始排查问题了。    
首先交代下环境,二台机器IP分别是10.1.150.12,10.232.31.89, 上面分别运行Erlang版本R16B和R14B04,cookie统一设置为456789。    
接着我们来演习下,首先我们10.1.150.12在节点A上起个节点’xx@10.1.150.12′,如下:

# erl -name xx@`hostname -i` -setcookie 456789

Erlang R16B (erts-5.10) 1 [64-bit] [smp:24:24] [async-threads:0] [hipe] [kernel-poll:false]

Eshell V5.10  (abort with ^G)

(xx@10.1.150.12)1>

=ERROR REPORT==== 28-Mar-2012::13:25:42 ===

** Connection attempt from disallowed node 'yy@10.232.31.89' **

同时我们在10.232.31.89上运行另外一个节点’yy@10.232.31.89′进行节点间连接,如下:

$erl -name yy@`hostname -i` -setcookie 456789

Erlang R14B04 (erts-5.8.5) 1 [64-bit] [smp:16:16] [rq:16] [async-threads:0] [hipe] [kernel-poll:false]

Eshell V5.8.5  (abort with ^G)

(yy@10.232.31.89)1>  net_adm:ping('xx@10.1.150.12').

pang

我们看到节点无法互通,出错的原因是”** Connection attempt from disallowed node ‘yy@10.232.31.89′ ** “.    
有提示消息就好办, 在otp源码目录下简单的运行:

# grep -rin "disallowed node" .

./lib/kernel/src/dist_util.erl:154:                   "disallowed node ~w ** ~n", [Node]),

./lib/kernel/src/dist_util.erl:603:                           "disallowed node ~w ** ~n", [NodeB]),

./lib/kernel/src/dist_util.erl:623:                           "disallowed node ~w ** ~n", [NodeB]),

./lib/kernel/src/net_kernel.erl:1149:                 "disallowed node ~w ** ~n", [Node]),

我们可以看到有4个函数有可能打印这个语句,分别是:    
1. is_allowed %% check if connecting node is allowed to connect with allow-node-scheme    
2 .recv_challenge_reply %% wait for challenge response after send_challenge    
3. recv_challenge_ack    
4. setup %% Set up connection to a new node.

其中和被动连接相关的俄只有1,2,3这几种情况.

情况1: 节点间allow相关的东西可以参考这篇文章:Erlang如何限制节点对集群的访问之net_kernel:allow    
我们来排除下allow导致问题的原因,把allow设成[],允许任意节点访问:

2> net_kernel:allow([]).      
ok      
(xx@10.1.150.12)2>      
=ERROR REPORT==== 28-Mar-2012::13:36:09 ===      
** Connection attempt from disallowed node ‘yy@10.232.31.89′ **

很清楚,这样并没有解决问题。

那就可以肯定是第2,3个原因了,回头来看下我们的版本号:    
R14B04 和 R16B, 差了二个大版本, 这个是核心原因。    
换成同样的版本的erlang问题应该解决!如下:

$erl -name yy@`hostname -i` -setcookie 456789

Erlang R16B (erts-5.10) 1 [64-bit] [smp:24:24] [async-threads:0] [hipe] [kernel-poll:false]

Eshell V5.10  (abort with ^G)

(yy@10.232.31.89)1>  net_adm:ping('xx@10.1.150.12').

pong

看来确实解决了!

小结: Erlang版本不混用,即使混用最好不超过2个版本。    
祝玩得开心!

转载于:https://my.oschina.net/szpengvictor/blog/51750

<think>我们正在解决Erlang节点间由于Cookie不匹配导致的认证失败问题。根据引用[1][2][3],我们知道: 1. Erlang节点间通信需要相同的Magic Cookie(引用[2]) 2. 实际案例中(如引用[3]的RabbitMQ问题)覆盖cookie文件并重启服务可解决 3. 引用[1]提到节点间ping不通可能是由于Cookie不一致 解决方案步骤: 1. **确认问题**:检查错误日志,通常会看到"**Mismatched cookie**"或"**Authentication failed**"等错误信息(引用[1][3]) 2. **统一Cookie值**:确保所有节点使用相同的Cookie - 方法1:手动复制主节点Cookie文件到其他节点 ```bash # 假设主节点Cookie文件在~/.erlang.cookie,目标节点node2 scp ~/.erlang.cookie user@node2:~/ ``` - 方法2:通过启动参数强制指定相同Cookie(适用于临时集群) ```bash erl -sname node1 -setcookie MyCookie erl -sname node2 -setcookie MyCookie ``` 3. **检查文件权限**:Cookie文件权限必须为600(引用[3]经验) ```bash chmod 600 ~/.erlang.cookie ``` 4. **重启节点**:修改Cookie后必须重启所有节点(引用[3]) 5. **验证连通性**:在节点1执行 ```erlang net_adm:ping(node2@hostname). ``` 返回`pong`表示成功,`pang`表示失败(引用[1][2]) **特殊场景处理**: - **RabbitMQ集群**:引用[3]表明需覆盖`/var/lib/rabbitmq/.erlang.cookie`并重启服务 - **多用户环境**:确保所有节点使用同一用户的Cookie文件(或不同用户但Cookie内容相同) **调试技巧**: - 开启Erlang分布式调试(临时设置环境变量): ```bash ERL_DIST_PORT=9000 erl -sname debug_node # 观察连接建立过程 ``` §§相关问题§§ 1. 如何动态修改运行中Erlang节点的Cookie值? 2. Erlang节点认证失败时如何获取详细错误日志? 3. RabbitMQ集群搭建时如何避免Cookie不一致问题? 4. Erlang分布式系统中有哪些除Cookie外的安全机制? 5. 如何通过防火墙配置增强Erlang节点间通信安全?</think>### 解决 Erlang 节点间 Cookie 不匹配导致的认证失败问题 以下是逐步解决方案,结合引用内容和实际经验整理: #### 🔍 步骤 1:确认 Cookie 不一致问题(引用[1][3]) ```erlang %% 在节点1执行 net_adm:ping('node2@hostname'). %% 返回 pang 表示认证失败 ``` ```bash # 检查日志中的关键错误(引用[3]) grep "cookie" /var/log/rabbitmq/rabbit@*.log # 典型错误:Mismatched cookie with node2@hostname ``` #### 🔧 步骤 2:统一所有节点的 Cookie 值(核心解决步骤) 1. **定位 Cookie 文件位置**(引用[2][3]): ```bash # 系统级(RPM安装常见) /var/lib/rabbitmq/.erlang.cookie # RabbitMQ默认路径[^3] # 用户级(源码安装常见) ~/.erlang.cookie ``` 2. **同步 Cookie**(必须所有节点相同): ```bash # 选择主节点cookie覆盖其他节点 scp /var/lib/rabbitmq/.erlang.cookie node2:/var/lib/rabbitmq/ scp /var/lib/rabbitmq/.erlang.cookie node3:/var/lib/rabbitmq/ ``` 3. **修正文件权限**(关键!引用[3]): ```bash chmod 600 /var/lib/rabbitmq/.erlang.cookie # 必须600权限 chown rabbitmq:rabbitmq /var/lib/rabbitmq/.erlang.cookie ``` #### ⚙ 步骤 3:重启服务并验证 1. **重启所有节点**(引用[3]经验): ```bash # RabbitMQ示例 systemctl restart rabbitmq-server # 普通Erlang节点需完全重启进程 ``` 2. **验证连通性**: ```erlang %% 节点1执行 net_adm:ping('node2@hostname'). %% 应返回 pong net_adm:ping('node3@hostname'). %% 应返回 pong ``` #### 🛠 特殊场景处理 1. **动态修改运行中节点**(临时方案): ```erlang %% 在需要连接的节点执行 erlang:set_cookie('node2@hostname', 'COOKIE_VALUE'). ``` > ⚠️ 仅限开发环境,生产环境需重启生效[^2] 2. **容器化环境**: ```dockerfile # Dockerfile示例 COPY .erlang.cookie /var/lib/rabbitmq/ RUN chmod 600 /var/lib/rabbitmq/.erlang.cookie ``` #### 📝 验证检查清单 | 检查项 | 命令 | 预期结果 | |--------|------|----------| | Cookie一致性 | `cat /var/lib/rabbitmq/.erlang.cookie` | 所有节点相同 | | 文件权限 | `ls -l /var/lib/rabbitmq/.erlang.cookie` | -rw------- | | 节点连通性 | `erl -name test@host -setcookie COOKIE -eval "net_adm:ping('target@host')"` | pong | | 防火墙状态 | `iptables -L -n` | 4369(epmd), 20000-30000端口开放 | ### 💡 根本原因分析 Erlang分布式系统通过Cookie实现节点认证(引用[2]): $$ \text{认证流程} = \begin{cases} \text{相同Cookie} & \rightarrow \text{建立连接} \\ \text{不同Cookie} & \rightarrow \text{拒绝连接} \end{cases} $$ 当节点A尝试连接节点B时,会交换并比对Cookie值,不匹配时触发`pang`响应[^1][^4]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值