后端物联网消息队列通信【免费下载链接】emqxThe most scalable and reliable MQTT broker for AI, IoT, IIoT and connected vehicles项目地址https://gitcode.com/gh_mirrors/em/emqx点击查看免费下载导读本文围绕 EMQX当前开源仓库gh_mirrors/em/emqx的一项内存优化特性展开当以EMQX_FEATURESESSENTIAL启动节点时Erlang 代码加载模式默认由embedded切换为interactive从而让被裁剪disabled特性的.beam模块按需加载、不再常驻内存显著降低 ESSENTIAL 模式节点的常驻内存resident memory占用。读完本文你将掌握 ESSENTIAL 模式与特性裁剪的运作方式、CODE_LOADING_MODE的两种加载模式的差异、该优化在 bin/emqx 启动脚本中的落地位置以及如何显式覆盖该默认行为。背景EMQX 的特性裁剪与 ESSENTIAL 模式EMQX 支持通过环境变量EMQX_FEATURES在启动前选择节点加载的应用application集合这是一项 boot-time 能力定义与解析逻辑集中在 apps/emqx_machine/src/emqx_machine_features.erl 中FULL默认启动全部应用ESSENTIAL只启动核心 broker 以及认证/授权authn/authz相关的核心基础设施dashboard、REST API、数据集成data integration、各类网关、插件等可选特性全部不启动list逗号分隔的特性名列表如dashboard,data_integration启动核心 broker 加上所列特性。该环境变量的默认值、取值与说明可在 apps/emqx_conf/etc/emqx.envEMQX_FEATURES${EMQX_FEATURES:-FULL}默认注释掉中查看emqx命令bin/emqx软件包安装时为/usr/bin/emqx在每次调用时都会 source 该文件因此服务启动、前台启动、emqx ctl都能读到相同的值且该变量在解析emqx.conf之前生效无法写入emqx.conf。从源码结构看特性与具体应用umbrella app的映射关系维护在emqx_machine_features:known_features/0中例如dashboard特性包含emqx_dashboard、emqx_management等应用data_integration特性包含emqx_connector、emqx_bridge、emqx_rule_engine等应用并支持依赖解析如schema_registry是多个特性的依赖。启动时apps/emqx_machine/src/emqx_machine_boot.erl 的filter_allowed_umbrella_apps/1会调用emqx_machine_features:is_umbrella_application_enabled/1据此过滤出真正允许启动的应用列表核心应用emqx、emqx_machine、emqx_conf等始终在列认证/授权后端emqx_auth_*也被视为核心基础设施、永不裁剪见base_core_apps/0与auth_apps/0。核心变更ESSENTIAL 模式下默认切换到 interactive 代码加载本次变更对应 change 条目feat-17803同时记录于 changes/6.3.0.en.md的核心内容如下当以EMQX_FEATURESESSENTIAL启动 EMQX 时Erlang 代码加载模式默认变为interactive使得被禁用特性的.beam文件按需加载on demand而不是在启动时全部加载。由于被跳过特性的模块永远不会常驻内存ESSENTIAL 模式节点的常驻内存占用显著下降。该模式仍可通过显式设置CODE_LOADING_MODE覆盖。代码加载模式embedded 与 interactive 的区别Erlang/OTP 的代码服务器code server支持两种加载模式由 VM 启动参数-mode决定embedded所有模块在启动时一次性全部加载。代码服务器启动即把所有code path中的模块读入内存运行期间不再从磁盘加载新模块。优点是启动后行为确定、没有运行期加载开销缺点是任何被打包进发行版的模块无论是否被使用都会常驻内存导致较大的常驻内存占用。interactive模块按需加载lazy loading。只有被实际调用的模块才在首次调用时从磁盘加载到内存。优点是内存占用小、启动快缺点是首次调用某个模块时存在一次磁盘读取。传统上EMQX 的发行版为了追求启动后的运行稳定性默认采用embedded模式这正是 bin/emqx 中CODE_LOADING_MODE${CODE_LOADING_MODE:-embedded}约第 281 行的含义默认值embedded但允许被环境变量覆盖。变更的落地位置该默认行为切换发生在 bin/emqx 启动脚本中约第 263–267 行## starts only the slim apps list, and we flip code loading to interactive so ## the skipped apps .beam files dont sit resident in memory. if [ ${EMQX_FEATURES:-} ESSENTIAL ]; then export CODE_LOADING_MODE${CODE_LOADING_MODE:-interactive} fi这段逻辑的关键点仅当EMQX_FEATURES精确等于ESSENTIAL时才触发。FULL 预设或自定义特性列表如dashboard,data_integration不会自动切换仍然使用embedded默认值。这是因为自定义列表通常仍会加载较多模块保持embedded可以避免运行期按需加载的开销。使用${CODE_LOADING_MODE:-interactive}的“默认值替换”写法如果用户在环境中已经显式设置了CODE_LOADING_MODE则尊重用户设置、不覆盖只有当该变量未设置或为空时才默认interactive。这与脚本中CODE_LOADING_MODE${CODE_LOADING_MODE:-embedded}的写法一致体现了“显式设置优先、未设置走默认”的覆盖策略。变量最终传给 VM 启动参数。脚本后续在构造erlexec/iex启动命令行时会通过-mode $CODE_LOADING_MODEerl 控制台路径或--erl -mode $CODE_LOADING_MODEiex 控制台路径将模式传给 VM见 bin/emqx 约第 1295、1315 行。为什么能显著降低常驻内存在embedded模式下发行版中所有.beam模块——包括那些因 ESSENTIAL 特性裁剪而永远不会被调用的模块——都会在启动时被加载并常驻内存。ESSENTIAL 模式本意是裁掉 dashboard、数据集成、网关等大量可选应用但如果代码加载模式仍是embedded这些被裁应用的模块依然会占据内存内存收益大打折扣。切换到interactive后由于被裁剪特性的应用根本不会被启动filter_allowed_umbrella_apps/1已将其从启动列表过滤其模块永远不会被调用、也永远不会被加载因此.beam文件不会常驻内存。可以推断裁剪的功能越多内存节省越明显对于仅承载核心 MQTT 转发与认证/授权的最小节点这一优化能带来可观的常驻内存下降。如何在实践中使用与验证1. 以 ESSENTIAL 模式启动最直接的用法是在启动前设置环境变量export EMQX_FEATURESESSENTIAL ./bin/emqx start或使用 Docker 运行可参考仓库中的冒烟测试脚本 scripts/test/essential-auth-smoke/run.sh 的用法docker run -d --name emqx-essential \ -e EMQX_FEATURESESSENTIAL \ emqx/emqx-enterprise:latest注意ESSENTIAL 模式下 dashboard 与 REST API 不启动因此无法通过 dashboard 或管理 API 观察节点运行时管理可借助./bin/emqx ctl与./bin/emqx eval。2. 显式覆盖代码加载模式如果出于某些原因例如希望 ESSENTIAL 节点也保持embedded的确定性加载或反之在 FULL 模式下也启用按需加载可以直接设置CODE_LOADING_MODE# 在 ESSENTIAL 模式下强制回退到 embedded export EMQX_FEATURESESSENTIAL export CODE_LOADING_MODEembedded ./bin/emqx start # 或在 FULL 模式下主动启用 interactive按需加载 export EMQX_FEATURESFULL export CODE_LOADING_MODEinteractive ./bin/emqx start由于脚本采用${CODE_LOADING_MODE:-...}的写法任何显式设置都会优先于默认值。3. 观察生效结果启动后可通过./bin/emqx eval检查当前代码服务器模式与已加载模块数量例如./bin/emqx eval code:get_mode().ESSENTIAL 模式且未显式覆盖时应返回interactiveFULL 模式或显式设置CODE_LOADING_MODEembedded时应返回embedded。如需确认被裁剪特性的模块确实未加载可以对比code:all_loaded()返回的模块列表interactive 模式下不应包含emqx_dashboard、emqx_connector、emqx_bridge等被禁用应用的模块也可以结合系统工具观察节点 RSS 的下降。4. 一个可复现的 ESSENTIAL 冒烟示例仓库提供了完整的 ESSENTIAL 模式冒烟测试 scripts/test/essential-auth-smoke/run.sh它用-e EMQX_FEATURESESSENTIAL启动单节点通过bootstrap.csv种子内置数据库认证、acl.conf配置文件授权再以真实 MQTT 客户端验证认证/授权行为。该测试同时印证了两个事实ESSENTIAL 模式下认证/授权栈完整可用认证/授权被视为核心基础设施不会被裁剪脚本中未显式设置CODE_LOADING_MODE因此节点实际运行于interactive加载模式。特性解析与能力下发的源码佐证为了让内存优化的收益落在运行期EMQX 在启动时还会把特性解析结果以能力capability形式下发给基础emqx应用避免热路径对emqx_machine产生向上依赖apps/emqx_machine/src/emqx_machine_features.erl 的publish_capabilities/1在解析完EMQX_FEATURES后通过emqx_features:set_capability/2写入persistent_termapps/emqx/src/emqx_features.erl 提供observability_enabled/0、client_info_enabled/0访问器其模块文档明确指出能力未设置或处于 FULL 预设时默认返回true行为与之前完全一致而 ESSENTIAL 等受限模式下消息热路径上的可观测性计数、client-info 统计等记账逻辑可以被跳过。从源码结构可以推断该能力下发与interactive加载模式是一对互补设计前者让热路径在运行期跳过不必要的记账后者让被裁剪模块根本不进入内存两者共同服务于 ESSENTIAL 模式的“最小内存占用”目标。适用前提与注意事项以当前仓库EMQX 7.x 系列实际内容为准。本文引用的行为均来自当前仓库的 bin/emqx、apps/emqx_machine/src/emqx_machine_features.erl、apps/emqx_machine/src/emqx_machine_boot.erl 及 changes/6.3.0.en.md。特性裁剪在启动时一次性决定。某特性未启动就无法在运行期启用要改变特性集合必须修改EMQX_FEATURES并重启节点见 apps/emqx_conf/etc/emqx.env 中的说明。该默认切换只针对ESSENTIAL精确匹配。如果设置成自定义特性列表代码加载模式仍是embedded默认值集群中所有节点应保持一致的特性配置。interactive意味着运行期按需加载虽然被裁剪特性的模块永不加载但未被裁剪特性的模块会在首次调用时从磁盘加载首次调用可能引入少量延迟这是内存收益与确定性之间的权衡可通过显式设置CODE_LOADING_MODE在两者间切换。赞分享后端物联网消息队列通信【免费下载链接】emqxThe most scalable and reliable MQTT broker for AI, IoT, IIoT and connected vehicles项目地址https://gitcode.com/gh_mirrors/em/emqx点击查看免费下载相关推荐JSDoc注释规范详解param、return、type等15个必会标签一次学会JSDoc注释规范详解param、return、type等15个必会标签一次学会 JSDoc 是 JavaScript 开发者最常用的 API 文档生成开发工具文档EMQX 安全加固模式下访问控制 Hook 的 Fail-Close 处理机制详解EMQX 安全加固模式下访问控制 Hook 的 Fail Close 处理机制详解 导读 本文基于 EMQX 开源仓库 changes/ee/feat 1758后端物联网消息队列通信创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考