emqx集群部署和使用问题

使用两台主机,部署了双节点高可用集群,启动正常,客户端注册和消费正常,web页面访问正常,但是集群高可用有点问题

1、使用集群查询命令发现节点并没有注册成功
2、down掉某一台机器,emqx组件不可用,客户端注册、订阅都不正常了
请问下是那块儿没做对,按理来说双节点任意节点down机,应该都不影响的



图看出来,集群已经加入成功:两个 Dashboard 都能看到 emqx@node1.emqx.ioemqx@node2.emqx.io 为 Running。
第一张图是 emqx_ctl 无法连接本机 Erlang 节点,而且容器状态已经是 unhealthy
这和客户端故障转移是两个问题。

先在两台宿主机分别执行下面这些命令,把输出贴出来:

docker exec emqx sh -c 'hostname -f; env | grep -E "EMQX_(NAME|HOST|NODE__NAME|NODE__COOKIE)|WITH_EPMD"; emqx_ctl status; emqx_ctl cluster status'
docker inspect --format '{{json .State.Health}}' emqx
docker logs --tail 200 emqx

重点检查:

  • 两个节点名必须唯一,两个节点的 node.cookie 必须完全一致;
  • node1.emqx.ionode2.emqx.io 在两个容器内都要解析到对端地址;
  • 默认 ekka 模式下,两台主机之间的 TCP 43705370 要双向可达;只有启用了 WITH_EPMD=1 才额外检查 4369node.dist_listen_min/maxping 通只说明 ICMP 正常,不能证明 Erlang/RPC 端口可用。

另外,还要说明一下的是:EMQX 集群不会把已经建立在故障节点上的 TCP 连接无缝搬到另一节点。节点宕机后,这些连接一定会断,客户端必须自动重连,并通过 TCP 负载均衡/VIP 连接到仍健康的节点;如果客户端一直直连某一台机器的 IP,那台机器停掉后自然就无法注册和订阅。可以先确认客户端接入地址是不是单节点 IP,以及前面有没有带健康检查的 LB。

你好,这是命令返回内容


shan上层是用了VIP+NG做了高可用负载的
image
客户端有重连,不过健康检查确实没有,nginx只是做了负载

现在可以定位了:unhealthy 的直接原因是容器节点名配置不一致,不是 Dashboard 里的集群没有加入。

截图里 hostname -f 返回容器 ID 3f32...,但 EMQX_HOST=node1.emqx.io;健康检查同时报 Node emqx@node1.emqx.io not responding to pings。EMQX 容器的健康检查就是执行 emqx_ctl status,节点名在容器内不能正确解析时就会出现这个结果。

先备份两台机器挂载的 /opt/emqx/data 和配置,再把每台容器的 hostname 与 EMQX_HOST 对齐。例如 node1:

hostname: node1.emqx.io
environment:
  EMQX_HOST: node1.emqx.io
  EMQX_NODE__COOKIE: "同一个非默认值"

node2 对应改成 node2.emqx.io。还要保证两个容器内都能把这两个名字解析到对端实际可达的地址;用 Docker network alias、DNS 或 extra_hosts 都可以。不要直接清空 data,EMQX 4.4 的数据目录包含节点名,改节点名之前必须备份。

重建后两边都验证:

docker exec emqx sh -c 'hostname -f; getent hosts node1.emqx.io node2.emqx.io; emqx_ctl status; emqx_ctl cluster status'

NGINX 这层也要补故障摘除。开源版 NGINX stream 没有主动 MQTT 健康检查,max_fails/fail_timeout 只是连接失败后的被动摘除,可以先显式配置:

upstream mqtt_servers {
    server 192.168.112.92:1883 max_fails=1 fail_timeout=10s;
    server 192.168.112.93:1883 max_fails=1 fail_timeout=10s;
}

server {
    listen 1883;
    proxy_pass mqtt_servers;
    proxy_connect_timeout 3s;
    proxy_next_upstream on;
    proxy_next_upstream_tries 2;
}

先执行 nginx -t,确认当前 NGINX 版本支持这些指令再 reload。节点宕机时,原来落在该节点上的 MQTT TCP 连接仍会断,客户端必须重连;被动摘除只能保证后续连接尽快落到另一节点。最后确认 VIP 后面确实有两台 NGINX,否则单台 NGINX 仍然是单点。

好的,谢谢,感谢支持,祝好