使用Keepalived VIP通过Java客户端无法向RabbitMQ集群发消息
我之前在搭建类似的RabbitMQ高可用集群时,也碰到过一模一样的VIP登录认证拒绝问题,结合当时的排查经验和RabbitMQ的权限机制,给你梳理几个关键的排查方向和解决办法:
RabbitMQ默认会限制部分用户(比如默认的guest)只能从本地环回地址登录,当请求通过VIP过来时,RabbitMQ识别的是VIP的IP地址,如果你的用户没有被授权从这个IP访问,就会直接抛出认证拒绝。
- 登录到任意RabbitMQ节点,先查看目标用户的权限配置:
# 列出所有用户 rabbitmqctl list_users # 查看目标用户的权限详情 rabbitmqctl list_user_permissions your_login_username - 如果输出里没有包含VIP所在的IP段,或者用户被限制在
loopback范围,需要修改配置:
编辑RabbitMQ的配置文件(通常是/etc/rabbitmq/rabbitmq.conf),添加或调整:
改完后重启RabbitMQ服务:# 如果使用guest用户(生产环境不推荐),允许其从外部访问 loopback_users.guest = false # 或者指定允许从外部访问的用户列表 loopback_users.allowed = ["your_login_username"]systemctl restart rabbitmq-server
因为RabbitMQ的AMQP协议是基于TCP的,如果HAProxy用了HTTP模式转发,会导致请求被篡改,进而认证失败。
- 打开HAProxy的配置文件(
/etc/haproxy/haproxy.cfg),检查frontend和backend的配置:frontend rabbitmq_front bind YOUR_VIP:5672 mode tcp # 必须是tcp模式,不能是http default_backend rabbitmq_backend backend rabbitmq_backend mode tcp balance roundrobin # 负载均衡策略,按需调整 # 配置RabbitMQ节点的地址和端口 server rabbit_node1 192.168.1.10:5672 check inter 2000 rise 2 fall 3 server rabbit_node2 192.168.1.11:5672 check inter 2000 rise 2 fall 3 - 确认配置无误后,重启HAProxy:
systemctl restart haproxy
有时候Keepalived的VIP没有正确绑定到HAProxy节点,或者转发规则没有指向HAProxy的监听端口,导致请求根本没到达HAProxy,直接落到了RabbitMQ节点(但节点可能没配置VIP的访问权限)。
- 先检查VIP是否正确绑定:
确保VIP地址已经出现在HAProxy节点的网卡列表里。ip addr show - 查看Keepalived的配置文件(
/etc/keepalived/keepalived.conf),确认virtual_server的配置指向HAProxy的服务:
注意:如果你的架构是Keepalived+HAProxy+RabbitMQ,Keepalived应该接管HAProxy的高可用,而不是直接指向RabbitMQ节点。virtual_server YOUR_VIP 5672 { delay_loop 6 lb_algo rr lb_kind NAT persistence_timeout 50 protocol TCP real_server HAPROXY_NODE_IP 5672 { weight 1 TCP_CHECK { connect_port 5672 connect_timeout 3 } } # 如果有备用HAProxy节点,添加在这里 real_server BACKUP_HAPROXY_IP 5672 { weight 1 TCP_CHECK { connect_port 5672 connect_timeout 3 } } }
错误提示里明确说“For details see the broker logfile”,这是最直接的排查依据。
打开RabbitMQ的日志文件(通常在
/var/log/rabbitmq/rabbit@your_hostname.log),搜索ACCESS_REFUSED或PLAIN login refused,你会看到更详细的拒绝原因,比如:2024-05-20 14:30:00.000 [error] <0.1456.0> Error on AMQP connection <0.1456.0> (192.168.1.200:54321 -> 192.168.1.10:5672):
PLAIN login refused: user 'admin' can only connect from localhost这种日志就直接告诉你,用户
admin只能从本地登录,需要调整用户的IP权限。
在客户端机器上,先验证VIP的5672端口是否能正常访问:
# 用telnet测试 telnet YOUR_VIP 5672 # 或者用nc测试 nc -zv YOUR_VIP 5672
如果连接失败,说明防火墙(比如firewalld、iptables)阻止了VIP的5672端口流量,需要添加放行规则:
# firewalld示例 firewall-cmd --add-port=5672/tcp --permanent firewall-cmd --reload
内容的提问来源于stack exchange,提问作者MichaelLee1988

