
后端物联网消息队列通信【免费下载链接】emqxThe most scalable and reliable MQTT broker for AI, IoT, IIoT and connected vehicles项目地址https://gitcode.com/gh_mirrors/em/emqx点击查看免费下载导读本篇文章围绕 EMQX 仓库变更记录 changes/ee/fix-16434.en.md 展开讲解告警管理 HTTP 接口中强制解除告警force deactivate alarm能力的一次关键修复此前通过 HTTP API 强制解除告警只会作用于单个节点集群中其他节点上的同名告警依然存在修复后只要按告警名称执行一次清除即可在所有节点上同步清除。读完本文你将掌握该接口的请求/响应语义、集群级清除的 RPC 调用链以及如何用源码与测试用例验证这一行为。一、变更内容速览原变更记录全文如下Previously, using the HTTP API to force deactivate an alarm would not clear it from all nodes. Now, clearing an alarm name will clear it from all nodes.翻译过来即修复前通过 HTTP API 强制解除告警不会在所有节点上清除它修复后按告警名称清除即可在所有节点上清除。该变更由内部问题 fix-16434 驱动属于集群一致性缺陷修复核心改动位于告警管理 API 的实现与对应的 RPC 通道。二、为什么单个节点清除不够告警表的本地内容模型要理解这个修复的价值先要看清 EMQX 告警数据的存储方式。告警模块 apps/emqx/src/emqx_alarm.erl 在create_tables/0中创建了两张 Mnesia 表活动告警表?ACTIVATED_ALARM即emqx_activated_alarm宏定义见 apps/emqx/include/emqx.hrl已解除告警历史表?DEACTIVATED_ALARM即emqx_deactivated_alarm两张表都声明了以下关键属性{type, ordered_set}, {storage, disc_copies}, {local_content, true},其中local_content true是理解本修复的核心每张告警表在每个节点上都持有本地副本节点之间并不共享告警数据。因此在 EMQX 集群中同一个告警名称例如high_system_memory_usage可能在多个节点上各自处于活动状态。此时若只在发起请求的节点上解除该告警其他节点上的同名活动告警依然存在集群的告警视图便不一致——这正是本次修复要解决的缺陷。三、修复后的集群级清除POST /api/v5/alarms/force_deactivate3.1 接口定义告警管理 API 由 apps/emqx_management/src/emqx_mgmt_api_alarms.erl 实现paths/0注册了三个路径paths() - [ /alarms, /alarms/force_deactivate ].其中/alarms/force_deactivate的 schemaschema/1 的对应分支定义了方法POST请求体force_deactivate_alarm_request仅一个必填字段namebinary 类型示例为high_system_memory_usage响应204解除成功400参数非法或告警不存在/已被解除实际 API 基础路径为/api/v5见 apps/emqx_management/test/emqx_mgmt_api_test_util.erl 中的?BASE_PATH定义因此完整端点为POST /api/v5/alarms/force_deactivate3.2 请求示例curl -X POST http://127.0.0.1:18083/api/v5/alarms/force_deactivate \ -H accept: application/json \ -H Content-Type: application/json \ -d { name: high_system_memory_usage }成功返回HTTP 204 No Content表示该告警名称已在所有支持节点上清除。失败返回HTTP 400code为NOT_FOUNDmessage为Alarm not found or already deactivated所有节点上都不存在该活动告警。3.3 参数校验与分发逻辑force_deactivate_alarm/2处理器L159-L178完整逻辑如下force_deactivate_alarm(post, #{body : Body}) - Name maps:get(name, Body, undefined), case Name : undefined orelse Name : of true - {400, #{code INVALID_PARAMETER, message name is required}}; false - Nodes emqx_bpapi:nodes_supporting_bpapi_version(?BPAPI_NAME, 1), Timeout 15_000, Result emqx_mgmt_api_alarms_proto_v1:safe_deactivate(Nodes, Name, Timeout), AnyOk [ok || {ok, NRes} - Result, ok - NRes], case AnyOk of [ok | _] - {204}; [] - {400, #{ code NOT_FOUND, message Alarm not found or already deactivated }} end end.几个值得注意的实现细节名称必填校验name缺失或为空字符串时直接返回400 INVALID_PARAMETER提示name is required不会发起任何集群调用。集群节点发现通过emqx_bpapi:nodes_supporting_bpapi_version(?BPAPI_NAME, 1)获取支持该 bpapi 版本 1 的所有节点而不是只向node()本地节点发起解除。超时控制RPC 调用超时固定为 15 秒15_000ms。成功判定只要任意一个节点成功解除返回ok整体即返回204若所有节点都返回{error, not_found}则返回400 NOT_FOUND。四、集群级清除的底层 RPC 调用链4.1 从 HTTP 处理器到 erpc:multicall集群分发经由 bpapi 通道 apps/emqx_management/src/proto/emqx_mgmt_api_alarms_proto_v1.erl 完成introduced_in() - 6.1.0. safe_deactivate(Nodes, Name, Timeout) - erpc:multicall(Nodes, emqx_mgmt_api_alarms, safe_deactivate_v1, [Name], Timeout).erpc:multicall会对Nodes列表中每个节点并行发起远程调用目标函数为emqx_mgmt_api_alarms:safe_deactivate_v1/1。该 proto 的introduced_in标记为6.1.0说明这一集群级清除通道自该版本起引入emqx_bpapi在调用前按版本过滤节点天然兼容混合版本集群中暂不支持该通道的节点。4.2 节点侧执行safe_deactivate_v1每个被调用节点上执行safe_deactivate_v1/1emqx_mgmt_api_alarms.erl L184-L185safe_deactivate_v1(Name) - lists:map(fun emqx_alarm:safe_deactivate/1, convert_alarm_names(Name)).convert_alarm_names/1L197-L205会把请求中携带的 binary 名称同时转换成已存在的 atom 名称 原始 binary 名称两种形式转换失败则退回原始 binary以兼容历史上以 atom 注册的内部告警名称若请求本身传的就是 atom则原样保留。这意味着一个 HTTP 请求实际上可能触发两次解除尝试确保名称表示形式不同的同名告警也能被命中。4.3 节点本地存储操作emqx_alarm:safe_deactivate最终落到告警模块 apps/emqx/src/emqx_alarm.erlsafe_deactivate(Name) - safe_call({deactivate_alarm, Name, no_details, }).handle_call({deactivate_alarm, ...})L277-L284先mnesia:dirty_read(?ACTIVATED_ALARM, Name)查找本地活动告警查无此告警 → 返回{error, not_found}对应 HTTP 层的NOT_FOUND查到 → 调用deactivate_alarm/4L379-L417执行状态迁移把活动告警记录写入?DEACTIVATED_ALARM历史表、从?ACTIVATED_ALARM中删除并根据alarm.actions配置触发日志、$SYS主题发布与alarm.deactivated钩子。由于每个节点各自执行一次本地safe_deactivate_v1集群中所有节点上的同名活动告警都会被逐一清除这正是本次修复clear it from all nodes的实现机理。另外safe_call/1对 gen_server 调用做了超时与异常捕获避免个别节点无响应时拖垮整个请求。五、完整的告警生命周期与相关接口修复后的/alarms/force_deactivate与告警生命周期中的其他环节共同构成完整的管理闭环阶段动作说明触发告警模块内部activate/1,2,3写入活动告警表按alarm.actions执行动作查询GET /api/v5/alarms支持activatedtrue/false查询参数分页返回自动解除条件恢复、进程退出监控等写入历史表从活动表移除强制解除POST /api/v5/alarms/force_deactivate按名称跨节点清除本次修复清空历史DELETE /api/v5/alarms清除全部已解除告警其中DELETE /api/v5/alarms由emqx_mgmt_api_alarms.erl的alarms(delete, _Params)处理调用 apps/emqx_management/src/emqx_mgmt.erl 的delete_all_deactivated_alarms/0该函数遍历emqx:running_nodes()逐个节点 RPC 清空?DEACTIVATED_ALARM表同样是集群级操作。查询接口返回的告警字段见fields(alarm)包括node告警所在节点、name、message、details、duration持续时间毫秒、activate_at、deactivate_at均为 RFC3339 格式见emqx_alarm:format/2实现。六、关联的告警配置项告警模块的行为由 apps/emqx/src/emqx_schema.erl 的fields(alarm)配置L1857-L1886控制与本文主题直接相关的三项如下配置项类型/范围默认值作用alarm.actions[log, publish]数组[log, publish]告警触发/解除时的动作写日志、向$SYS/brokers//alarms/{activate,deactivate}发布消息并触发钩子alarm.size_limit整数1..30001000历史告警表最大条数超过时淘汰最旧记录见deactivate_alarm/4中的淘汰逻辑alarm.validity_period时长如24h24h已解除告警的保留期过期由定时器清理见handle_info(timeout, ...)理解这些配置有助于判断强制解除操作的影响面被解除的告警并非立即删除而是转为历史记录受size_limit与validity_period约束actions中若包含publish解除动作还会广播到$SYS主题并触发alarm.deactivated钩子。七、测试用例如何验证集群级清除apps/emqx_management/test/emqx_mgmt_api_alarms_SUITE.erl 提供了针对本次修复的直接验证t_force_deactivate_alarm_api/1L227-L261依次验证——对不存在的告警强制解除返回400 NOT_FOUND激活告警后强制解除返回成功且活动告警列表中不再出现该名称对已解除告警再次强制解除返回400 NOT_FOUNDatom 形式的告警名称可通过atom_to_binary转换后正常解除name缺失或为空串时返回400 INVALID_PARAMETER与name is required。t_cluster_force_deactivate/0L289-L313以集群模式[{matrix, true}]运行先在两个节点上分别激活同名告警some_alarm确认查询接口返回两条记录每个节点一条随后调用一次强制解除断言集群中该告警全部清除、查询结果为空且再次强制解除返回NOT_FOUND。该用例直接覆盖了本次修复的clear it from all nodes行为。此外t_alarms_api/1与t_delete_alarms_api/1覆盖了查询与清空历史接口的既有行为。八、使用建议与注意事项适用前提集群级清除依赖emqx_mgmt_api_alarms_proto_v1这一 bpapi 通道introduced_in为6.1.0请确保发起请求的节点能够通过emqx_bpapi:nodes_supporting_bpapi_version枚举到集群内各节点混合版本集群中不支持该通道的节点不会被调用。幂等语义接口以任意节点成功即成功判定重复对已清除的告警名发起请求会得到400 NOT_FOUND属预期行为可在自动化脚本中将其视为目标状态已达成。名称匹配请求体中的name需与告警名称一致内部告警同时支持 atom 与 binary 两种表示convert_alarm_names/1会尽量兼容两者。与DELETE /api/v5/alarms的区别force_deactivate只清除指定名称的活动告警转为历史记录DELETE则清空全部已解除历史二者用途不同可配合使用。监控视角若通过$SYS/brokers//alarms/deactivate主题或alarm.deactivated钩子消费解除事件集群级清除会在每个受影响节点各产生一次解除事件消费端需按节点维度归并。结语fix-16434 虽是一行简短变更记录背后却是一次典型的集群一致性问题修复告警数据以local_content模型存储在每节点本地而管理 API 通过 bpapi RPC 通道将按名解除广播到全部节点从而保证集群告警视图一致。本文结合 emqx_mgmt_api_alarms.erl、emqx_alarm.erl 与 emqx_mgmt_api_alarms_SUITE.erl 完整还原了从 HTTP 请求到节点本地存储操作的整条链路可作为告警运维与二次开发的参考。赞分享后端物联网消息队列通信【免费下载链接】emqxThe most scalable and reliable MQTT broker for AI, IoT, IIoT and connected vehicles项目地址https://gitcode.com/gh_mirrors/em/emqx点击查看免费下载相关推荐gh_mirrors/swi/swift-style-guide中的警告处理如何消除所有警告gh_mirrors/swi/swift style guide中的警告处理如何消除所有警告 你是否还在为Swift项目中的警告而烦恼是否想让代码更加整洁、教程EMQX 集群最大 TPS 许可证告警机制深度解析EMQX 集群最大 TPS 许可证告警机制深度解析 导读 本文围绕 EMQX 企业版EE新增的 集群最大 TPS每秒事务数许可证告警 功能展开详细说明后端物联网消息队列通信Nightingale 集成 EMQX基于 Dashboard API 的 MQTT 集群指标采集与告警实战Nightingale 集成 EMQX基于 Dashboard API 的 MQTT 集群指标采集与告警实战 EMQX 插件是 Nightingale 生态中后端运维观测告警可观测性人工智能AI Agent上一篇3步打造爆款节奏游戏用Phaser实现音乐打击体验下一篇freecodecamp.cn社区内容审核工具提高审核效率的方法创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考