ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

EMQX 规则引擎 republish 动作的 Namespace 隔离修复:limit_selects_in_namespace 行为详解

EMQX 规则引擎 republish 动作的 Namespace 隔离修复:limit_selects_in_namespace 行为详解 后端物联网消息队列通信【免费下载链接】emqxThe most scalable and reliable MQTT broker for AI, IoT, IIoT and connected vehicles项目地址https://gitcode.com/gh_mirrors/em/emqx点击查看免费下载导读本文围绕 EMQX 规则引擎Rule Engine中republish动作在多租户 Namespace 场景下的发布行为修复展开当rule_engine.limit_selects_in_namespace开启默认开启时属于某个 Namespace 的规则通过republish重发布的消息如今会自动落到该规则所在的 Namespace 下即渲染主题前自动补上namespace/前缀从而与规则SELECT侧已有的 Namespace 限定保持一致。读完本文你将理解这条修复的来龙去脉、republish主题渲染与挂载mount的底层实现、limit_selects_in_namespace配置项的完整语义以及如何利用测试用例验证该行为。修复背景Namespace 与规则引擎的 SELECT 侧隔离EMQX 的规则引擎支持将规则归属于某个 Namespace以支撑多租户multi-tenant场景不同租户的数据通过 Namespace 隔离规则只能看到并处理自己 Namespace 内的流量。这一隔离在规则的**数据入口SELECT / FROM 侧**早已生效。在emqx_rule_events.erl的get_rules_for_topic/1与restrict_rules_to_namespace/2中可以看到当rule_engine.limit_selects_in_namespace true时规则匹配前会先解析消息所属的 Namespace通过消息 header 或客户端属性中的tns见get_namespace_from_message/1Namespace 规则只会匹配来自同一 Namespace的客户端发布的消息Ns0 Ns全局规则?global_ns则保持系统级可见性继续匹配任何 Namespace 的消息以保留非多租户部署下 6.2 之前的既有行为。也就是说规则“读”数据的入口已经被 Namespace 限定但修复之前规则“写”数据的出口——republish动作——却没有做对应的限定。修复前的缺陷republish 绕过 Namespace 限定republish是规则引擎的内置动作之一作用是把规则匹配到的消息重新发布到指定主题主题、QoS、Payload 等均支持通过模板如${topic}、${.field}动态渲染。相关实现位于emqx_rule_actions.erl的republish/3。修复前republish直接将渲染出的主题字符串作为发布目标{TopicString, _Errors1} render_template(TopicTemplate, Selected), ... Topic iolist_to_binary(TopicString), %% 修复前直接使用渲染结果由此产生一个隔离缺口一个 Namespace 规则把消息重发布后消息会以不带 Namespace 前缀的原始渲染主题进入 broker。这既与规则 SELECT 侧的 Namespace 限定不一致也意味着重发布的消息可能逃逸出该租户的 Namespace破坏多租户隔离语义。修复内容mount_rule_namespace 统一出口隔离本次修复在republish/3中引入mount_rule_namespace/2调用渲染出主题字符串后、真正发布前完成 Namespace 挂载见emqx_rule_actions.erl{TopicString, _Errors1} render_template(TopicTemplate, Selected), ... Topic mount_rule_namespace(Metadata, iolist_to_binary(TopicString)),mount_rule_namespace/2的实现逻辑emqx_rule_actions.erl精确地体现了本次修复的完整语义mount_rule_namespace(#{namespace : Namespace}, Topic) when is_binary(Namespace) - case emqx_rule_engine_config:get_limit_selects_in_namespace() of true - MountPoint Namespace/binary, /, case string:prefix(Topic, MountPoint) of nomatch - emqx_mountpoint:mount(MountPoint, Topic); _ - Topic end; false - Topic end; mount_rule_namespace(_Metadata, Topic) - Topic.可分解为四条明确的行为规则仅作用于带 Namespace 的规则只有当规则的 metadata 中namespace是非空二进制时才会触发挂载逻辑全局规则第二个子句直接保留渲染主题行为不受影响。受limit_selects_in_namespace开关控制开关为false时原样返回 Topic完整保留旧行为只有为true默认时才执行挂载。幂等防重复前缀通过string:prefix(Topic, MountPoint)检查渲染主题是否已经以namespace/开头若已带前缀则原样发布、不再重复添加。否则自动补前缀通过emqx_mountpoint:mount/2将namespace/拼接到主题前最终发布到namespace/topic。修复后的消息随后经safe_publish/7与do_safe_publish/2走正常入口发布emqx_rule_actions.erl消息 header 中会记录republish_by RuleId用于检测递归重发布同时可被 Trace 追踪。配置项rule_engine.limit_selects_in_namespace该行为由规则引擎配置rule_engine.limit_selects_in_namespace统一控制它是一个布尔型配置项默认值为true。配置定义见emqx_rule_engine_schema.erl{limit_selects_in_namespace, ?HOCON( boolean(), #{ default true, desc ?DESC(limit_selects_in_namespace) } )}对应的读取封装在emqx_rule_engine_config.erlget_limit_selects_in_namespace() - emqx_config:get([rule_engine, limit_selects_in_namespace], true).配置项的官方语义说明位于 rel/i18n/emqx_rule_engine_schema.hoconWhen enabled, rules will only trigger on messages published by clients on the same namespace as the rule itself.即开启后规则只会被与自己处于同一 Namespace 的客户端发布的消息触发——这描述的是 SELECT 侧的限制而本次修复把同样的限制延伸到了republish动作的输出侧使规则的“读”与“写”在 Namespace 语义上完全对齐。在生产配置emqx.conf中可按需显式声明例如rule_engine { limit_selects_in_namespace true }若要回退到修复前的旧行为重发布消息不带 Namespace 前缀则rule_engine { limit_selects_in_namespace false }兼容性考量模板自带前缀与全局规则本次修复在设计上刻意避免破坏存量用户具体体现在两处1. 渲染模板已自带 Namespace 前缀的情况对于习惯在 republish 模板中自行拼接前缀的用户例如模板写成${ns}/${topic}其中${ns}渲染后即等于规则 Namespacemount_rule_namespace/2中的string:prefix/2检查会命中主题将原样发布、不会重复添加前缀。因此这类模板的既有行为完全不受影响不会出现ns/ns/topic的双重前缀问题。2. 全局规则global namespace的情况mount_rule_namespace/2的第二条子句对不带 Namespace 的规则直接返回渲染主题同时 SELECT 侧的restrict_rules_to_namespace/2也明确规定全局规则保留系统级可见性。二者共同保证非多租户部署无 Namespace 概念下规则引擎行为与修复前完全一致。源码级验证测试用例如何覆盖该行为仓库中的 Common Test 用例对这一修复及相关语义进行了完整验证可作为理解与回归验证的依据1. Namespace 隔离 republish 端到端验证t_limit_selects_in_namespace/1构造了两个租户ns1、ns2的集群环境通过emqx_conf:update([rule_engine, limit_selects_in_namespace], true, ...)开启隔离并分别创建一个“诚实”规则属于ns1FROM ${ns}/t选择本 Namespace 主题一个“越界”规则属于ns2却试图FROM ${other_ns}/t窥探ns1的消息。随后ns1客户端向t发布消息并断言ns2客户端收不到任何 republish 结果?assertNotReceivens1客户端能收到 republish 的消息?assertReceivePublish。测试末尾将开关改为false后再次发布断言两个客户端都能收到——即关闭开关后限制解除、旧行为恢复与修复文档的描述一一对应。2. 全局规则不被 Namespace 流量误伤t_global_rule_matches_namespaced_traffic/1复现了一个 6.0 → 6.2.x 升级后的客户报告一个纯指标型全局规则无动作输出在发布客户端携带tns租户属性后停止匹配。用例验证在limit_selects_in_namespace true时全局规则仍必须匹配来自带 Namespace 客户端通过mqtt.client_attrs_init将 username 写入tns属性的消息规则指标matched/passed正常增长。此外emqx_rule_engine_SUITE.erl中的t_events_limit_selects_in_namespace与t_events_limit_selects_in_namespace_global也从事件触发角度验证了 Namespace 隔离与全局规则并存的行为。总结本次修复补齐了规则引擎多租户 Namespace 隔离的最后一环republish动作的输出侧。修复后场景修复前行为修复后行为开关默认开启Namespace 规则渲染主题无前缀直接发布到渲染主题逃逸 Namespace自动发布到namespace/topicNamespace 规则渲染主题已带namespace/前缀原样发布原样发布幂等不重复加前缀全局规则原样发布原样发布不受影响limit_selects_in_namespace false原样发布原样发布完整保留旧行为核心实现集中在mount_rule_namespace/2一处配合 SELECT 侧的restrict_rules_to_namespace/2使 Namespaced 规则的“读”与“写”两侧隔离语义一致同时通过幂等前缀检查与全局规则豁免保证了对存量配置的完全兼容。对多租户部署而言这条修复避免了重发布消息逃逸租户隔离边界的安全隐患对非多租户部署则无需任何配置改动即可保持原有行为。赞分享后端物联网消息队列通信【免费下载链接】emqxThe most scalable and reliable MQTT broker for AI, IoT, IIoT and connected vehicles项目地址https://gitcode.com/gh_mirrors/em/emqx点击查看免费下载相关推荐EMQX 规则引擎 Republish 动作修复direct_dispatch 空字符串与非布尔值的容错处理EMQX 规则引擎 Republish 动作修复direct_dispatch 空字符串与非布尔值的容错处理 本文围绕 EMQX 开源仓库 changelog后端物联网消息队列通信EMQX 规则引擎修复深度解析limit_selects_in_namespace 开启时全局命名空间规则事件失效问题EMQX 规则引擎修复深度解析limit_selects_in_namespace 开启时全局命名空间规则事件失效问题 本文围绕仓库变更记录 fix 1795后端物联网消息队列通信EMQX 规则引擎租户命名空间下的全局规则匹配修复limit_selects_in_namespace 机制与源码剖析EMQX 规则引擎租户命名空间下的全局规则匹配修复 limit_selects_in_namespace 机制与源码剖析 本篇文章围绕 EMQX 变更记录 f后端物联网消息队列通信上一篇RenderCV locale 字段完全指南多语言简历的本地化、日期格式与自定义方法下一篇Apache Arrow GLib 实战指南基于 GObject Introspection 的 C 绑定与多语言桥接创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表