EMQX 预安装插件在 Dashboard 启动后出现 Plugin Config Not Found 的修复解析
EMQX 预安装插件在 Dashboard 启动后出现 Plugin Config Not Found 的修复解析【免费下载链接】emqxThe most scalable and reliable MQTT broker for AI, IoT, IIoT and connected vehicles项目地址: https://gitcode.com/gh_mirrors/em/emqx导读本文围绕 EMQX 插件管理体系中一个真实缺陷的修复展开当插件包plugin package在节点启动前被直接解压到plugins/目录即预安装插件随后通过 Dashboard 将其启动时插件配置页面会报出Plugin Config Not Found错误。文章先还原问题现象与复现路径再沿着管理 API、插件状态机与本地配置缓存的调用链逐层定位根因最后结合当前仓库源码说明修复后的行为变化与验证方法。读完本文你将掌握 EMQX 插件从解压落盘到Dashboard 启动再到配置可读的完整生命周期并能独立诊断同类插件配置丢失问题。变更内容回顾本次变更对应变更记录 fix-16823.en.md修复的是Dashboard 插件管理中对预安装插件的处理问题核心结论可以概括为当插件包在节点启动之前被解压到plugins/目录时从 Dashboard 启动该插件配置页面不再报Plugin Config Not Found。一句话理解EMQX 节点启动时plugins/目录下已经存在解压好但从未被 EMQX 的插件配置系统登记过的插件过去从 Dashboard 启动这类插件后配置页无法读取到配置现在该场景已被修复。问题现象与复现路径复现路径在节点启动前将某个插件包手动解压到 EMQX 的plugins/安装目录安装目录的判定模式见 emqx_plugins_fs.erl即扫描install_dir()/*/release.json启动 EMQX 节点登录 Dashboard进入插件管理页面对上述预安装插件执行启动操作打开该插件的配置页面。症状在修复前第 5 步会看到类似Plugin Config Not Found的错误提示修复后配置页面能够正常展示插件配置包括插件自带的默认配置或空配置。错误从何而来Dashboard 配置接口的返回路径Plugin Config Not Found并非前端文案而是管理 API 在特定条件下返回的错误消息。在 emqx_mgmt_api_plugins.erl 的get_plugin_config/1中可以看到完整逻辑get_plugin_config(NameVsn) - case describe_api_plugin(NameVsn, #{}) of {ok, _} - case emqx_plugins:get_config(NameVsn, ?plugin_conf_not_found) of Config when is_map(Config) - {200, #{content-type application/json}, Config}; ?plugin_conf_not_found - {400, #{ code BAD_CONFIG, message Plugin Config Not Found }} end; _ - {404, plugin_not_found_msg()} end.关键点在于插件存在describe_api_plugin/2返回{ok, _}时接口调用emqx_plugins:get_config(NameVsn, ?plugin_conf_not_found)尝试读取配置若返回的是哨兵值?plugin_conf_not_found而非配置 map则接口以HTTP 400 BAD_CONFIG返回Plugin Config Not Found只有配置以 map 形式返回时才正常返回 200 与配置内容。也就是说这个错误本质上是插件已安装、但插件配置在配置系统中不可读的一种体现。继续追查emqx_plugins:get_config/2见 emqx_plugins.erlget_config(NameVsn) - get_config(NameVsn, #{}). get_config(NameVsn, Default) - get_cached_config(NameVsn, Default).可以看到Dashboard 读取的配置实际来自节点内存中的配置缓存get_cached_config/2。因此问题根因指向预安装插件在被 Dashboard 启动时配置缓存没有被正确初始化缓存中查不到该插件的配置。根因启动前的插件目录与配置缓存初始化预安装插件的磁盘状态emqx_plugins_fs:install_state/1见 emqx_plugins_fs.erl将插件安装目录的磁盘状态划分为三态installedrelease.json元数据可读且包内声明的所有应用均已完整解压incomplete目录存在但release.json不可读或声明的应用文件缺失解压中断等残留absent目录完全不存在。节点启动前手动解压的插件在磁盘上处于installed状态但并未被 EMQX 的插件启动/配置流程登记过——这正是问题发生的特殊之处。配置缓存的初始化链路插件配置缓存通过maybe_initialize_cached_config/1建立见 emqx_plugins.erlmaybe_initialize_cached_config(NameVsn) - case get_cached_config(NameVsn, ?plugin_conf_not_found) of ?plugin_conf_not_found - case ensure_local_config(NameVsn, ?normal) of ok - configure_from_local_config(NameVsn, stopped); {error, no_source_file} - %% Some plugins intentionally do not ship a default config file. %% Keep start behavior backward compatible for them. ok; {error, _} Error - Error end; _ - ok end.该函数的逻辑是缓存中查不到配置时先通过ensure_local_config/2建立本地配置再以configure_from_local_config/2把配置写入缓存。其中{error, no_source_file}分支专门处理插件有意不携带默认配置文件的场景保持向后兼容。而ensure_local_config/2见 emqx_plugins.erl在正常模式下会优先从集群其他节点拉取配置do_ensure_local_config(NameVsn, ?normal) - case peer_nodes() of [] - emqx_plugins_local_config:copy_default(NameVsn); Nodes - case get_config_from_any_node(Nodes, NameVsn, []) of {ok, Config} when is_map(Config) - emqx_plugins_local_config:update(NameVsn, Config); {error, Errors} - log_config_not_found(NameVsn, Errors), emqx_plugins_local_config:copy_default(NameVsn) end end.在单节点或集群中均查不到配置时回退到copy_default/1即从插件包自带的默认 HOCON 配置文件中拷贝一份。无本地配置文件时的回退顺序对于预安装插件读取配置时还会进入read_start_config_without_local_file/1见 emqx_plugins.erl其回退顺序为先查缓存配置get_cached_config/2缓存也没有时读取插件包内的默认 HOCONread_default_hocon/1默认文件也不存在时返回空配置{ok, empty, #{}}。可以推断本次修复正是围绕上述缓存初始化 默认配置回退路径展开确保预安装插件在 Dashboard 启动后maybe_initialize_cached_config/1等初始化逻辑能够可靠执行使get_cached_config/2不再返回?plugin_conf_not_found从而让配置接口返回正常配置默认配置或空配置而非 400 错误。修复后的行为变化结合当前仓库源码apps/emqx_plugins与apps/emqx_management修复后该场景的行为链路为启动Dashboard 触发插件启动emqx_plugins:ensure_started/1及配套的configure/3见 emqx_plugins.erl进入配置流程初始化ensure_local_config/2先尝试从集群其他节点同步配置失败则从插件包拷贝默认配置对于不携带默认配置文件的插件走no_source_file兼容分支缓存configure_from_local_config/2见 emqx_plugins.erl校验并写入缓存同时通过notify_config_change/4通知插件应用读取Dashboard 配置接口的get_plugin_config/1调用get_cached_config/2命中缓存返回 200 与配置内容不再出现Plugin Config Not Found。此外启动路径上ensure_installed/1见 emqx_plugins.erl会区分installed与_IncompleteOrAbsent两种磁盘状态installed时直接读取插件信息并configure不完整或缺失时才走reinstall/1重新安装。这也保证了预安装插件不需要重新安装即可正确进入配置流程。相关操作与验证相关 CLI 命令EMQX 插件管理同时提供 CLI 入口emqx ctl plugins ...可与 Dashboard 配合排查。例如在启用安全安装策略的环境下上传安装插件需要先授予安装许可该提示同样出现在管理 API 的错误消息中见 emqx_mgmt_api_plugins.erl# 为指定版本插件授予安装许可sha256 由包校验值决定 emqx ctl plugins allow name-vsn sha256:hex # 常用插件管理命令 emqx ctl plugins list # 查看所有插件状态 emqx ctl plugins install name-vsn # 安装插件 emqx ctl plugins start name-vsn # 启动插件验证步骤针对本修复场景可按下述步骤验证在节点启动前将插件包解压到plugins/目录并确认目录下存在release.json这是install_state/1判定installed的依据启动 EMQX 节点通过 Dashboard 或emqx ctl plugins start name-vsn启动该插件打开该插件的配置页面对应管理 API 的GET /plugins/{name}/config确认不再返回Plugin Config Not Found而是展示默认配置或空配置若插件包内未携带默认配置文件应确认走no_source_file兼容分支后配置页仍可正常打开对应空配置{ok, empty, #{}}分支。配置与状态文件的落盘位置插件安装目录plugins/每个插件以name-vsn为目录名安装元数据为release.json本地配置由emqx_plugins_local_config.erl管理通过ensure_config_dir/1确保配置目录存在配置以 HOCON 形式落盘集群同步单节点直接拷贝默认配置多节点时通过emqx_plugins_proto_v2/v3/v4等 RPC 协议从其他运行节点同步对应 emqx_plugins.erl 中get_config的 RPC 调用。小结Plugin Config Not Found的本质是插件已安装但配置在缓存中不可读。预安装插件由于在节点启动前才落盘缺少常规安装流程中的配置初始化导致 Dashboard 读取配置时落入 400 分支。本次修复完善了插件配置缓存初始化与默认配置回退链路使预安装插件从 Dashboard 启动后即可正常展示配置。相关源码集中在 emqx_plugins.erl配置缓存、本地配置初始化、emqx_plugins_fs.erl安装目录三态判定、release.json元数据与 emqx_mgmt_api_plugins.erlDashboard 配置接口可作为进一步排查插件配置问题的入口。【免费下载链接】emqxThe most scalable and reliable MQTT broker for AI, IoT, IIoT and connected vehicles项目地址: https://gitcode.com/gh_mirrors/em/emqx创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考