Broker 配置
Artemis 允许通过管理 API 修改运行中 broker 的 address settings、security settings 和 divert,并且这些修改在重启后仍然保留。这很有用,也是一个陷阱:broker 里没有任何记录说明这次修改发生过,于是运行中的 broker 和下一次部署所依据的 broker.xml 会悄悄地不一致。
本页讲的就是填补这个缺口的功能。每个集群拥有一份声明——它应当运行什么——Studio 用它衡量每个活动节点,在你要求时应用它,并在某个节点漂移时用文字告诉你。

声明是什么
四个区段,每个集群一份文档,每次保存生成一个版本:
| 区段 | 应用时会做什么 |
|---|---|
| Address 与队列 | 创建缺失的。从不删除。已存在但配置不同的队列只会被报告,不会被修改——请在 Queues 视图中编辑。 |
| Address settings | 按 match:上限、策略、死信与过期 address、重投递。应用时会替换 broker 中该 match 的整个条目。 |
| Security settings | 按 match:哪些角色可以发送、消费、创建和管理。 |
| Divert | 缺失则创建;被修改的 divert 是一次删除加一次创建。 |
broker.xml 的其余部分——global-max-size、<ha-policy>、acceptor 等——在任何 Artemis 版本上都无法通过管理 API 应用。导入含有这些元素的文件时,每一个都会被列为未应用;不会为它们存储任何东西,也不会假装可以。
两种应用方式
模式在声明头部按集群设置,两个动作始终可见:
- 由 Studio 管理。 预览并应用 通过管理 API 把声明写到每个活动节点。修改在重启后持久,下一次漂移评估会显示节点已同步。
- 在 Studio 之外管理。 复制 broker.xml 片段 把声明渲染为
<core>元素的四个区段,供你自己的配置管理使用。应用被禁用并说明原因。漂移仍然会被评估,所以你能知道部署是否一致。
Studio 从不写入 broker.xml,也从不调用 reloadConfigurationFile——重载会从 broker 磁盘重新读取整个文件,包括 Studio 从未见过的编辑,这正是无法预览的那类操作。
得到第一份声明
有活动节点却还没有声明的集群,打开时会看到一个提议:把这个集群正在运行的内容采纳为第 1 版,其中按区段列出会声明多少条目,以及节点之间的任何分歧——这些在你打开任何东西之前就已写明。它只是一次读取(与漂移评估相同的批量读取),不保存任何东西。按下 审阅并采纳为第 1 版 会打开常规的采纳预览,那里会在确认旁边再次给出这些数量。
Studio 从不自作主张地采纳。采纳意味着声明"brokers 此刻碰巧在运行的一切"就是有意为之——包括某人一小时前手改、尚未想清楚的那个设置。只有操作员能这样说,这也是漂移在有人这样说之前始终只是建议的原因(ADR-0067 D8),以及为什么这只是一个提议而不是默认动作。
从 Configuration 视图有三个入口:
从集群采纳 读取每个活动节点,用它们正在运行的内容构建声明。每个 address-setting match 都以 broker 报告的完整条目填充,因此第一次应用什么也不会改变。节点之间不一致时,两个值都会列出,由你选择。
导入 XML:粘贴一份
broker.xml或片段——裸的<address-setting>和<security-setting>元素也可以。预览列出识别到的内容(按区段:新增 / 变更 / 未变)、未应用 的元素,以及指明元素的错误——未解析的${…}占位符是错误,不是值。默认情况下,粘贴的内容会合并进已声明的内容:粘贴的条目新增或更新其对应项,对 address setting 而言粘贴的键生效、其余已声明的键保留。替换 则让粘贴的内容成为整个声明。集群设置页和设置页上的能力账本走的是同一扇门。当某个"需要设置"的片段是 address 或 security setting——慢消费者检测、通知权限、管理消息大小上限——该行会说明这一点并提供 在配置中声明,直接在该片段上打开导入预览。片段中的静态部分(
<broker-plugins>块)会被列为未应用,仍需修改broker.xml。在任一区段添加条目。编辑器根据 broker 接受的每个 address-setting 键的目录进行校验:未知键会被拒绝,而不是在 broker 上变成静默的无操作。每个键旁边都有一个信息控件,说明它管什么并给出示例值;其他键 后面的长尾有查找框。
有一件事 broker 无法告诉 Studio:security setting 的 view 和 edit 权限类型通过管理 API 会被接受,却从不回报(在 2.44 上测得)。它们会被发送,但不参与计划、验证和漂移检查,编辑器会说明这一点——这两项请在 broker 自身的配置里确认。
每次保存都是一个新版本。两个操作员同时编辑不会互相覆盖:保存时会声明它基于哪个版本,若版本已变动则被拒绝。
关闭能力缺口
能力账本报告为缺失的内容,有一部分根本不是静态配置:它们是管理 API 在运行时就接受的 address setting 或 security setting。推荐 标签页把这些变成一份你可以应用的声明,而不是一段需要你去粘贴的片段(ADR-0068)。

今天有三项可以应用——把完整消息体返回给 Studio(management-message-attribute-size-limit)、慢消费者检测,以及 activemq.notifications 权限。每一项都以节点当前运行的完整条目呈现,并在其上改动推荐的键,因为运行时写入会替换整个条目而不是合并进去:屏幕上列出的,正是写入之后该节点将持有的内容。security setting 的推荐角色从 broker 读取,声明之前可以修改;不指名任何角色的块会被拒绝,因为它能干净地应用却不授予任何人任何权限。
其余的——通知插件、acceptor、管理 security setting——背后没有任何管理操作,将来也不会有。它们会连同各自的 broker.xml 与原因一起写明,而不是被省略。
声明会保存为一个来源为 RECOMMENDED 的普通版本,因此审计轨迹说得清它从何而来,并把你带到计划页。在你像对待任何一次应用那样确认之前,没有任何内容到达 broker。一旦探针能读回某项推荐的效果,它就会消失——这也是只提供上述三项的原因:Studio 无法观测到"已完成"的推荐将永远不会消失。
注册集群时,连接检查通过后会预览同一个面板,并在集群建立后把你带到那里。
预览并应用
应用流程是 计划 → 确认 → 结果,其设计目标是不可能一次拖垮整个集群。
计划。 一次试运行读取每个目标节点——每个节点最多两次批量请求,绝不按条目逐个请求——并按节点计算观测状态与声明不同的有序步骤。读回已经一致的步骤标记为已如声明,不发出写操作。节点内顺序:address → 队列 → address settings → security settings → divert,删除在新增之后。
每个步骤读起来就是一份差异:每个键一行,before → after,发生变化的键在前,这次写入同样会带上的键(因为管理写入会替换整个条目)留在下面并以淡色显示。替换语义因此是看得见的,而不是靠推断;你没有声明却会被改变的键是一个名为非预期键变更的高危害。你滚动查看步骤时,顶部会固定一条摘要:多少次写入、多少个节点、哪个节点先走、还有多少项尚未确认。大集群上按节点分组可以折叠;金丝雀节点和任何失败的节点始终展开。筹码式过滤器按区段或键筛选视图——数量和步骤编号仍是计划本身的。

危害在任何写操作之前分类。高危害必须在计划上逐个按 id 确认:
| 危害 | 何时出现 |
|---|---|
| 非预期键变更 | 替换语义重置了声明未设置的键 |
| 消息丢失策略 | 在有已观测 address 的 match 上,address-full-policy 变为 DROP 或 FAIL |
| 阻塞策略 | address-full-policy 变为 BLOCK |
| 上限低于用量 | 新上限低于该 match 下某个 address 已持有的量 |
| 管理访问 | security setting 覆盖了管理 address,或 match 为 # / * |
| 宽泛匹配 | match 为 # 或 *——broker 上的每个 address |
| 移除未声明项 | 你选择移除 Studio 未曾应用的东西 |
中、低危害(divert 被替换、DLQ 被移动、启用自动删除、移除自有项)会被说明,无需确认。
确认。 影响范围被重述——多少次写入、哪些节点、金丝雀优先——然后你输入集群名称。确认危害不等于确认操作;两者都需要。这里刻意没有"替你填入名称"的按钮:一次点击就把名称填好,会把输入式确认重新变成第二次点击。
返回计划再回来,你的危害确认会被保留。继续进入确认时会先重新计算计划并比较哈希:如果期间某个节点变了,你会看到集群已变化——这是一份新的计划,差异就在屏幕上,之前的确认被清除,而不是在你已经输入完名称之后才收到一个 409。
结果。 第一个活动节点(金丝雀;可在计划中另选)接收所有步骤,并在触碰任何其他节点之前被读回。这个过程你看得见:应用运行期间,每个节点都会报告它到了哪一步——正在应用、第 n 步(共 m 步)、正在读回验证、完成或已停止——因此金丝雀上的一次停止会立刻显现,而不是看起来像一次缓慢的成功。报告结果的仍然是那次响应;时间线只是提示。随后逐节点继续,并在第一次失败处停止:该节点剩余步骤和所有剩余节点都为未尝试。不会回滚,结果用一句话说明:
Halted at broker-1 step 3: AMQ229001 … broker-2 not attempted. Nothing was rolled back. Re-running converges.
重新运行同一版本会收敛:一致的步骤已如声明;失败和未尝试的步骤会再次尝试。
每次应用(包括试运行)都是一条审计事件,附带 节点 × 步骤 的结果。步骤上限(config.apply-step-cap,默认 100)会拒绝更大的计划,除非显式覆盖,覆盖会被记录。
应用永远不会做的事
- 销毁队列或 address。 从声明中移除只是让 Studio 不再检查它。删除是队列自己的流程,带有批量上限。
- 移除它未曾应用的东西。 Studio 记录自己应用了什么。节点上存在而声明未提及的 setting 或 divert 报告为未声明;移除它是每次计划单独的选择,带有自己的高危害,因为如果
broker.xml也有它,移除会在下次重启时回退,而 Studio 无从得知。 - 按定时器运行。 漂移评估是定时的;应用永远不是。规则可以对漂移告警(
CONFIG_DRIFT);没有任何东西会替你行动。
漂移
每个活动节点按计划(config.drift-interval,默认五分钟)、每次应用之后以及按需,被与当前版本比较。每个节点一次批量、限速的读取;评估从不改变任何东西。
Drift 标签页以一句话给出结论——All 3 live nodes match revision 7——随后是这次测量发生在多久之前,以及测量的节奏:Last evaluated 2m ago · evaluated about every 5m。单看一个时长无法区分"刚刚评估过"和"调度器停了",所以两者始终一起出现;绝对时刻就在标签上,可用键盘访问,每个节点也各自带有自己的状态标记和时长。评估与应用完成时,标签页会自行更新,无需刷新。
当有差异时,按类型分组列出,声明值与观测值在同一行上,每一行都标明节点:

| 发现 | 含义 |
|---|---|
| 缺失 | 已声明,节点上没有 |
| 不同 | 节点上存在但值不同 |
| 未声明 | 节点上存在,声明中没有(仅当集群开启了该报告) |
| 队列不同 | 已声明的队列存在但配置不同——在 Queues 视图中编辑 |
| 无法验证 | broker 不会回报的键 |
| 不可达——未评估 | 节点未应答;缺席不会被当作事实报告 |
备份节点不参与评估:它们在成为活动节点之前不显示运行时设置,并通过复制接收 address settings、security settings 和 divert。提升后的备份一旦活动就会被评估。
Config diff 比较两个节点之间的差异;漂移比较每个节点与声明的差异。两者互相链接。
权限
| 权限 | 授予 |
|---|---|
cluster:read | 查看声明、漂移、历史;立即评估 |
config:write | 保存版本、导入、采纳、更改模式 |
config:apply | 预览并应用 |
config:apply 是创建与更新的权限:它从不意味着删除队列或 address。内置管理员角色拥有全部权限;把两个 config:* 权限授予操作员角色,方式与 queue:create 或 divert:write 相同。
通过 MCP
broker_config 读取声明、漂移、XML 片段或应用历史。broker_config_change 声明(来自文档或 XML)或应用:试运行——默认——返回计划、危害和确切的 acknowledge id;真实运行需要 confirm 等于集群名称、expectedPlanHash 等于预览时的哈希,并且与 UI 完全一样地停止。见 MCP 服务器。
决策依据
ADR-0067 记录了本页背后的十二个决定以及被否决的替代方案——自由格式 XML 编辑器、reloadConfigurationFile、全量扇出、自动调和器。