EMQX 停止缓存订阅(Subscribe)ACL 授权检查结果:原理、实现与调优指南
后端物联网消息队列通信【免费下载链接】emqxThe most scalable and reliable MQTT broker for AI, IoT, IIoT and connected vehicles项目地址https://gitcode.com/gh_mirrors/em/emqx点击查看免费下载导读本文围绕 EMQX 5.x 中一项针对授权Authorization / ACL缓存的重要行为调整展开订阅subscribe操作的 ACL 检查结果不再进入授权缓存而发布publish操作仍然照常缓存。该改动源于 changes/ee/fix-16550.en.md其动机非常直接——MQTT 订阅通常在连接生命周期内只发生一次为它缓存检查结果绝大多数时候只是白白占用内存。读完本文你将理解 EMQX 授权缓存的完整读写路径、订阅为何被从缓存中剔除、这一行为对内存与规则热更新的影响以及如何通过authorization.cache配置enable/max_size/ttl/excludes对缓存行为做精细化控制。一、改动背景为什么订阅检查结果不值得缓存原文档给出的理由只有一句话但信息密度很高MQTT subscription is mostly done once per connection life cycle. Holding the subscribe ACL check result in cache is most of the time a waste of RAM.翻译过来即MQTT 订阅在大多数场景下每个连接生命周期内只执行一次为此类一次性检查结果长期持有缓存条目大部分时间都是对 RAM 的浪费。结合 MQTT 协议语义可以这样理解一个客户端连接建立后通常只做一次或少数几次SUBSCRIBE然后长时间收发消息直到断开发布PUBLISH则不同一条连接上可能持续高频地往同一主题发布消息同一动作, 主题组合会被反复命中缓存收益极高订阅一旦成功后续消息投递由订阅树session/subscription 表管理并不会再次触发该主题的 ACL 检查因此缓存订阅检查结果几乎没有“复用”机会。从 emqx_access_control.erl 的授权入口可以看出EMQX 的授权缓存是按进程channel 进程与主题维度设计的每次命中缓存都会跳过整条授权链路的执行对订阅这种“一次性动作”而言跳过执行换来的收益远小于为它维护缓存条目的成本。二、实现证据缓存模块如何对 subscribe 说不改动最核心的实现位于授权缓存模块 emqx_authz_cache.erl。该模块以“动作 主题”为键维护缓存键形如{?MODULE, Topic, QoS, Retain}见 emqx_authz_cache.erl值形如{AuthzResult, CachedAt}。针对订阅动作模块在读写两侧都做了短路处理读取侧——get_authz_cache/2对subscribe动作直接返回not_found不进入任何缓存查找%% apps/emqx/src/emqx_authz_cache.erl get_authz_cache(#{action_type : subscribe}, _Topic) - not_found; get_authz_cache(PubSub, Topic) - case erlang:get(cache_k(PubSub, Topic)) of undefined - not_found; {AuthzResult, CachedAt} - if_expired(get_cache_ttl(), CachedAt, ...) end.写入侧——put_authz_cache/3对subscribe动作直接返回ok什么都不写%% apps/emqx/src/emqx_authz_cache.erl put_authz_cache(#{action_type : subscribe}, _Topic, _AuthzResult) - ok; put_authz_cache(Pub, Topic, AuthzResult) - ... %% 发布动作才真正写入缓存也就是说即使在authorize/4的入口处emqx_authz_cache:is_enabled(Topic)判定该主题允许缓存订阅动作的检查结果也永远不会被写入缓存、永远不会命中缓存。订阅 ACL 检查因此始终走完整的授权链路run_hooks(client.authorize, ...)保证每一次订阅都基于最新规则与最新客户端上下文实时裁决。三、调用链订阅检查如何绕过缓存订阅授权检查的完整调用链如下客户端发送SUBSCRIBE报文channel 进程在 emqx_channel.erl 的do_check_sub_authzs2/3中对每个 Topic Filter 逐一做授权检查主题过滤器中带 QoS由authz_action/1构造出?AUTHZ_SUBSCRIBE(QoS)动作见 emqx_channel.erl共享订阅如$share/g/t/#只检查真实主题t/#由emqx_topic:get_shared_real_topic/1处理见 emqx_channel.erl调用emqx_access_control:authorize(AuthzContext, Action, Topic)在 emqx_access_control.erl 中先经emqx_authz_cache:is_enabled(Topic)判断主题是否启用缓存若启用则进入check_authorization_cache/3check_authorization_cache/3见 emqx_access_control.erl调用emqx_authz_cache:get_authz_cache(Action, Topic)——对subscribe动作返回not_found于是走do_authorize_with_cache_policy/3执行真实的规则匹配规则匹配结果返回后尝试put_authz_cache(Action, Topic, AuthzResult)——对subscribe动作同样被短路为ok。最终效果是订阅路径 每次实时全量检查零缓存发布路径 命中缓存时直接返回未命中才执行检查并回填缓存。四、配套机制发布缓存如何工作对照理解理解了订阅不缓存再对照发布缓存机制会更有画面感。发布路径的缓存逻辑同一文件、同一套键值结构包含如下关键点命中判定check_authorization_cache/3在not_found时计数cache_miss命中时计数cache_hit并触发client.check_authz_complete钩子钩子参数中会带上来源标记cache见 emqx_access_control.erl因此外部可以通过该钩子观察到某次授权结果是来自缓存还是实时检查是否可缓存授权链路的返回结果中若带有is_cacheable false则即使发布动作也不会写入缓存由should_cache_authz_result/1控制见 emqx_access_control.erl。这为“某些动态来源如实时计算的规则天然不可缓存”提供了扩展点容量与淘汰缓存条数受max_size限制默认 32键以队列queue维护先进先出顺序缓存满且最新条目未过期时淘汰最旧条目evict_authz_cache若满且全部过期则整体清空见 emqx_authz_cache.erlTTL 与全局排空条目带时间戳过期即失效drain_cache/0会在persistent_term中写入一个全局排空时间戳使所有早于该时间戳的缓存条目立即视为过期见 emqx_authz_cache.erl 与 emqx_authz_cache.erl。ACL 规则或授权配置变更时EMQX 会调用emqx_authz_cache:drain_cache()主动失效缓存见 emqx_authz/emqx_authz.erl避免旧规则被继续命中按客户端定向清理drain_cache/1可通过 ClientId 定向向对应 channel 进程发送clean_authz_cache消息channel 进程收到后清空自己的授权缓存见 emqx_channel.erl。因为订阅不再写入缓存drain_cache之后也无需担心残留的订阅缓存条目——测试用例 emqx_authz_cache_SUITE.erl 中甚至特意注释“subscribe is not cached, so we publish to verify cache works after drain”即用发布操作来验证排空后缓存重建仍正常。五、配置项authorization.cache 全参数说明该行为与authorization.cache配置块紧密相关schema 定义位于 emqx_schema.erl字段说明与默认值如下配置项类型默认值说明authorization.cache.enablebooleantrue是否启用授权缓存订阅动作不受影响始终不缓存authorization.cache.max_sizeinteger1–104857632每个 channel 进程缓存的最大条目数达到上限后按 FIFO 淘汰最旧条目authorization.cache.ttlduration1m缓存条目存活时间超过 TTL 的条目在读取/清理时失效authorization.cache.excludesarray of binary[]匹配这些主题模式如nocache/#的授权结果不缓存对应的 i18n 描述可参见 rel/i18n/emqx_schema.hocon 与 rel/i18n/emqx_schema.hoconexcludes的官方描述为“Exclude caching ACL check results for topics matching the given patterns”。配置示例emqx.conf/ HOCONauthorization { cache { enable true max_size 32 ttl 1m excludes [nocache/#, system//status] } }几点实操建议enable与订阅无关即使enable true订阅检查结果依然不缓存enable false时发布检查也全部实时执行适合 ACL 规则极其频繁变化的场景代价是发布性能下降excludes的典型用途对 ACL 结果高度动态、随客户端上下文实时变化的主题如设备上线后才确定的权限可在excludes中列出以彻底绕过缓存对订阅动作而言无需配置它天然就不缓存max_size与ttl的权衡缓存条目存于 channel 进程的进程字典erlang:get/put中max_size直接影响单连接内存占用由于订阅不再参与缓存同一连接上缓存条目仅由发布动作产生相同max_size下实际占用的 RAM 较改动前显著下降。六、内存收益与行为影响评估内存收益以典型物联网场景为例一条连接上客户端往往订阅 1N 个主题、随后持续上报数据。改动前每个订阅主题的检查结果都会占用一个缓存条目直到 TTL 到期或被淘汰改动后这部分内存完全省去缓存只服务于真正高频复用的发布主题。在多租户网关、消息量大、连接数高的部署中这一改动能直接降低每个 channel 进程的进程字典占用。行为影响订阅检查每次都实时执行ACL 规则变更后无需等待 TTL 或手动 drain新的订阅立即应用最新规则订阅路径每次都会触发完整的client.authorize钩子链订阅频率极高的场景如短时间内反复订阅/退订检查开销会高于改动前但此类行为在 MQTT 实践中并不常见与节省的内存相比通常值得发布路径行为不变缓存命中率、cache_hit/cache_miss指标与排空机制均不受影响。七、测试验证仓库中的 emqx_authz_cache_SUITE.erl 覆盖了授权缓存的关键行为可直接佐证本文结论t_cache_exclude第27-37行将nocache/#加入excludes后订阅nocache//#并发布消息断言缓存列表为空验证excludes生效t_clean_authz_cache第39-59行先订阅并发布以产生缓存条目再向 channel 进程发送clean_authz_cache消息断言缓存被清空验证定向清理路径t_drain_authz_cache第61-80行调用drain_cache/0后缓存条目立即失效随后通过发布操作验证缓存能够重建且注释明确指出“订阅不缓存故用发布来验证”。这些用例与 emqx_authz_cache.erl 中订阅短路的实现相互印证共同构成该改动的完整证据链。小结EMQX 通过 fix-16550.en.md 这项改动将授权缓存的适用范围收敛为“发布动作 可缓存来源 未排除主题”订阅动作的检查结果彻底不落缓存。从实现上看这是 emqx_authz_cache.erl 中读写两侧各一行 pattern 匹配的短路从效果上看它贴合 MQTT 订阅“连接生命周期内低频发生”的语义在几乎不影响正确性的前提下省掉了大量冗余内存。对运维与开发者而言理解这一行为后可以更准确地利用authorization.cache的enable/max_size/ttl/excludes做内存与实时性的精细化权衡。赞分享后端物联网消息队列通信【免费下载链接】emqxThe most scalable and reliable MQTT broker for AI, IoT, IIoT and connected vehicles项目地址https://gitcode.com/gh_mirrors/em/emqx点击查看免费下载相关推荐EMQX Auto Subscribe 自动订阅功能详解配置模板、占位符与源码实现原理EMQX Auto Subscribe 自动订阅功能详解配置模板、占位符与源码实现原理 EMQX 的 emqx_auto_subscribe 应用位于 ap后端物联网消息队列通信EMQX 加固安全模式下的内部订阅校验topic 校验、授权、MQTT 能力检查与订阅 Hook 全解析EMQX 加固安全模式下的内部订阅校验topic 校验、授权、MQTT 能力检查与订阅 Hook 全解析 导读 本文围绕 EMQX 安全加固hardened后端物联网消息队列通信EMQX 授权缓存authz cache内存优化客户端断开即清理的设计与实现EMQX 授权缓存authz cache内存优化客户端断开即清理的设计与实现 本文围绕 EMQX 中 PR 15899 引入的优化——客户端断开连接时立即后端物联网消息队列通信创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

相关新闻

统一身份认证系统落地实战:分级认证、单点登录与数据同步避坑指南

统一身份认证系统落地实战:分级认证、单点登录与数据同步避坑指南

简介:这份《统一身份认证系统技术方案》PDF面向系统架构师、后端开发与信息安全从业者,聚焦统一认证与授权管理平台的落地设计,可用于智慧海事等政企项目的方案参考与技术选型。资源为单个PDF文件,压缩包约2.74MB,内容…

2026/9/25 5:17:05 阅读更多 →
GORM PostgreSQL 驱动实战指南:从 DSN 连接到源码级配置解析

GORM PostgreSQL 驱动实战指南:从 DSN 连接到源码级配置解析

网络安全 【免费下载链接】sliver Adversary Emulation Framework 项目地址: https://gitcode.com/gh_mirrors/sl/sliver 点击查看 免费下载 本篇技术指南以 GORM 官方 PostgreSQL 驱动(gorm.io/driver/postgres)为核心,系统讲解…

2026/9/25 5:17:05 阅读更多 →
EasyXMen诊断模块Dcm深度剖析:UDS服务从报文接收到响应发送的全过程

EasyXMen诊断模块Dcm深度剖析:UDS服务从报文接收到响应发送的全过程

EasyXMen诊断模块Dcm深度剖析:UDS服务从报文接收到响应发送的全过程 【免费下载链接】开源小满EasyXMen代码仓库 持续18年精心打造的安全车控操作系统BSW代码。 项目地址: https://gitcode.com/easyxmen/XMen 🔍 EasyXMen(开源小满&am…

2026/9/25 5:17:04 阅读更多 →

最新新闻

STM32驱动DHT11温湿度传感器:单总线时序与HAL库实现

STM32驱动DHT11温湿度传感器:单总线时序与HAL库实现

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/9/25 6:41:11 阅读更多 →
STM32 SWD/JTAG通信失败排查指南:从接线到救砖的完整流程

STM32 SWD/JTAG通信失败排查指南:从接线到救砖的完整流程

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/9/25 6:41:11 阅读更多 →
开源30MHz任意波形发生器:DDS原理、原理图与调试波形全解析

开源30MHz任意波形发生器:DDS原理、原理图与调试波形全解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/9/25 6:41:10 阅读更多 →
随机短视频管理系统源码实战:Vue3后台+FastAPI调度全解析

随机短视频管理系统源码实战:Vue3后台+FastAPI调度全解析

简介:这是一套基于PHPMySQL构建的全新UI随机美女短视频管理系统源码,适合有PHP基础、希望快速搭建短视频内容管理平台的开发者或运营人员使用。系统采用前后端分离设计,前端适配手机、平板与桌面浏览器,后台基于RBAC权限模型支持管…

2026/9/25 6:41:10 阅读更多 →
R与RStudio版本更新全攻略:跨平台操作与包迁移技巧

R与RStudio版本更新全攻略:跨平台操作与包迁移技巧

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/9/25 6:41:10 阅读更多 →
探地雷达GPR数据处理全流程:从A-Scan到B-Scan、速度分析与三维切片

探地雷达GPR数据处理全流程:从A-Scan到B-Scan、速度分析与三维切片

简介:GPR.zip打包了一份面向探地雷达从业者与学习者的完整资料,内容涵盖GPR数据原理、无损检测应用及GPRConsole软件源码,适合地质勘查、工程检测、考古等领域的算法研究与二次开发。压缩包共28个文件,以C源码为主,包括…

2026/9/25 6:40:10 阅读更多 →

日新闻

AI元人文:从工具使用到思维重构的深度探索

AI元人文:从工具使用到思维重构的深度探索

最近半年我一直在琢磨一件事:AI元人文到底是什么?说白了,就是“用元视角重新审视人与AI的关系”,也在“探索AI如何反向逼着我们发现自己的思考边界”。标题里的“元探索”,在我看就是一层套一层的追问——当你用AI解决…

2026/9/25 0:00:41 阅读更多 →
Python+CNN车牌识别实战:从数据预处理到模型训练与部署

Python+CNN车牌识别实战:从数据预处理到模型训练与部署

简介:基于Python与卷积神经网络的车牌识别项目,面向计算机视觉初学者及智能交通开发者,目标是帮助用户掌握从数据预处理、模型构建到实际部署的完整流程。压缩包共25个文件,包含jpg/png图像样本、py训练脚本、md说明文档、dat数据…

2026/9/25 0:00:41 阅读更多 →
Vim基础操作全攻略:保存退出、模式切换与高频命令实战

Vim基础操作全攻略:保存退出、模式切换与高频命令实战

1. 项目概述1.1 核心需求解析今天聊聊Vim。写这个题目的原因是:几乎每个后端开发者、运维人员、数据工程师某天都会遇到一个场景——深夜加班,服务器登录界面只有黑底白字,编辑器只有vi/vim,你必须在五分钟内完成一次配置修改并保…

2026/9/25 0:00:41 阅读更多 →

周新闻

Flutter for OpenHarmony游戏卡片渐变背景实战:从原理到性能优化

Flutter for OpenHarmony游戏卡片渐变背景实战:从原理到性能优化

直接铺开项目本身吧。这几个月我一直在折腾一件事:用Flutter给OpenHarmony做一款游戏集合类的App,说白了就是把若干小游戏塞进一个壳里,用统一入口分发。这个方向本身不算新鲜,真正让我花了不少心思的,是首页那堆游戏卡…

2026/9/24 14:34:13 阅读更多 →
Word表格编号全攻略:从列表编号到题注交叉引用

Word表格编号全攻略:从列表编号到题注交叉引用

写Word文档,最让人头疼的往往是那些“看起来不起眼”的小问题。比如表格编号这事:今天在表后面多加了两个空白行,明天给客户交稿前发现整个章节的编号全部错位,光是挨个改序号就能耗掉大半个下午。我前阵子帮人整理一份上百页的技…

2026/9/24 9:10:42 阅读更多 →
从第一个站到第二个站:独立开发者的静态网站选型与落地实践

从第一个站到第二个站:独立开发者的静态网站选型与落地实践

1. 项目概述1.1 核心需求解析做独立开发者这几年,说实话,第一个网站上线的那天晚上我兴奋得没睡着。但等它跑了半年,流量惨淡、功能臃肿、代码自己都懒得看第二遍之后,我才慢慢琢磨明白一个道理:第一个网站是练手&…

2026/9/24 14:33:56 阅读更多 →

月新闻

持续集成 流水线自动化与 声明式交付 实践:原型怎样变成可用功能

持续集成 流水线自动化与 声明式交付 实践:原型怎样变成可用功能

持续集成 流水线自动化与 声明式交付 实践:原型怎样变成可用功能分类:[AI/大模型]细分主题:AI 增强型 CI/CD 流水线自动化与 GitOps 实践:Agent 工作流、工具调用与任务拆解:从原型到生产的验收清单很多团队在尝试用大…

2026/9/24 12:50:34 阅读更多 →
容器编排 生产环境运维与排障实战:复盘记录怎样真正派上用场

容器编排 生产环境运维与排障实战:复盘记录怎样真正派上用场

容器编排 生产环境运维与排障实战:复盘记录怎样真正派上用场分类:[工程技术]细分主题:Kubernetes 生产环境运维与排障实战:可复制的项目复盘模板与决策记录大部分团队的事故复盘报告,最后都变成了躺在 Confluence 或钉…

2026/9/24 14:33:48 阅读更多 →
容器 容器化技术与镜像安全管理:核心链路应该先拆哪一步

容器 容器化技术与镜像安全管理:核心链路应该先拆哪一步

容器 容器化技术与镜像安全管理:核心链路应该先拆哪一步分类:[工程技术]细分主题:Docker 容器化技术与镜像安全管理:核心链路的逐步实现与关键代码取舍面对一个积累了五六年历史包袱的单体架构应用(包含 Web 接口、后台…

2026/9/24 12:49:17 阅读更多 →