集群里到底哪些东西是所有节点共享的,哪些只在一个节点?队列放在哪个节点由谁决定?节点永久下线要做什么?少数派的节点能做什么、不能做什么?这篇起了一个真实的三节点集群一项项验证。
n1@localhost 上看到 exchange ['x.meta']、队列 ['q.meta@n1@localhost']
n2@localhost 上看到 exchange ['x.meta']、队列 ['q.meta@n1@localhost']
n3@localhost 上看到 exchange ['x.meta']、队列 ['q.meta@n1@localhost']
feature flag khepri_db 的状态: [('khepri_db', 'enabled')]用户、vhost、exchange、队列定义和绑定在每个节点上都有,4.3.6 的元数据存储是基于 Raft 的 Khepri。队列里的消息则只在队列所在的节点(经典队列)或副本节点(quorum / stream)。
连到队列所在的 n1: p50 0.086 ms,p99 0.158 ms 连到 n2: p50 0.122 ms,p99 0.219 ms 连到 n3: p50 0.122 ms,p99 0.218 ms
客户端可以连任意节点操作任意队列,不在队列所在节点时消息被转发,本机上 p50 从 0.086 ms 增加到 0.122 ms。
默认(client-local),每个节点上的客户端各声明 3 个,leader 的分布: {'n1@localhost': 3, 'n2@localhost': 3, 'n3@localhost': 3}
其中 loc.1.* 是 n1 上的客户端声明的: n1@localhost, n1@localhost, n1@localhost
全部从 n1 的客户端声明 9 个队列:policy queue-leader-locator=balanced → {'n1@localhost': 3, 'n3@localhost': 3, 'n2@localhost': 3};不设 policy(client-local)→ {'n1@localhost': 9}默认 queue-leader-locator=client-local:放在声明它的客户端所连的节点;balanced 按节点现有队列数放置。队列都从同一个节点创建的应用要设成 balanced。
停掉 n3 之后:Disk Nodes ['n1@localhost', 'n2@localhost', 'n3@localhost'];Running Nodes ['n1@localhost', 'n2@localhost']
$ rabbitmqctl forget_cluster_node n3@localhost
Removing node n3@localhost from the cluster
forget 之后:Disk Nodes ['n1@localhost', 'n2@localhost'];Running Nodes ['n1@localhost', 'n2@localhost']停掉的节点仍是集群成员(Disk Nodes 里还在),永久下线要 rabbitmqctl forget_cluster_node。
$ rabbitmqctl -n q18x@localhost join_cluster n1@localhost
Clustering node q18x@localhost with n1@localhost
13:09:53.619 [error] Feature flags: error while running:
Feature flags: rabbit_ff_controller:running_nodes[]
Feature flags: on node `n1@localhost`:
Feature flags: exception error: {erpc,noconnection}
Error:
{:aborted_feature_flags_compat_check, {:error, {:erpc, :noconnection}}}节点靠相同的 Erlang cookie 互相认证。cookie 不一致时 join_cluster 只报 noconnection,看不出是 cookie 的问题。
往已有的 exchange / 队列发布一条(带 confirm): 成功(1 ms) 声明新队列 q.new: 20 秒内没有返回(用时 20.0 s)
元数据变更需要多数派。三个节点只剩一个时,已有队列的发布照常,新建队列等不到返回。