资讯详情

资讯详情

EMQX 数据备份恢复中的配置导入依赖排序:Schema Registry 前置修复解析(Issue 14988)

后端物联网消息队列通信【免费下载链接】emqxThe most scalable and reliable MQTT broker for AI, IoT, IIoT and connected vehicles项目地址https://gitcode.com/gh_mirrors/em/emqx点击查看免费下载导读本文围绕 EMQX 开源仓库中 changes 目录记录的一个真实缺陷修复fix-14988展开当通过数据备份恢复Data Backup Restore导入集群配置时Schema ValidationSchema 校验与 Message Transformation消息转换等配置项可能先于其依赖的 Schema Registry 配置被导入从而触发配置校验失败。文章将结合仓库源码剖析 EMQX 备份恢复的完整链路、emqx_config_backup行为实现与emqx_conf_dep_registry依赖拓扑排序机制并给出规避该问题的运维建议帮助读者理解 EMQX 配置导入的顺序约束与依赖建模方式。问题背景备份恢复中的配置导入顺序缺陷在changes/ee/fix-14988.en.md中记录了这样一条变更Fixed an issue where schema validation or message transformation configurations could be imported before schema registry when restoring a backup, leading to validation errors.即在恢复备份时Schema Validation 或 Message Transformation 的配置可能在 Schema Registry 之前被导入导致校验错误。同一修复也出现在版本变更记录 changes/e5.9.0.en.md对应 Pull Request #14988中。要理解这个问题需要先回答两个问题EMQX 的备份文件里到底存了什么恢复时配置是如何被写回集群的为什么 Schema Validation / Message Transformation 与 Schema Registry 之间存在必须先导入谁的先后关系EMQX 数据备份与恢复的配置链路备份文件的构成EMQX 的数据备份Data Backup由 emqx_mgmt_data_backup.erl 实现。备份产物是一个.tar.gz归档其中包含META.hocon备份元数据记录versionEMQX 版本、editionCE/EE 版本、security_profile安全配置文件cluster.hocon全局集群配置的 HOCON 序列化结果来自emqx_config:read_override_conf(#{override_to cluster})mnesia/TableName内建数据库各表的备份文件ns/Namespace/cluster.hocon多租户namespace场景下每个命名空间的配置。归档内所有文件必须位于backup name/子目录下且只允许普通文件与目录导出时还会调用emqx_schema_registry_config:prepare_protobuf_files_for_export/1将 Schema Registry 中引用的 protobuf 文件内容一并内联保证备份包自包含。恢复时配置如何被写回恢复流程入口为emqx_mgmt_data_backup:import/1,2API 路径为POST /data/import见 emqx_mgmt_api_data_backup.erl完整调用链如下import/2 └─ do_import/2 解包、校验 META、安全 profile、版本与 edition └─ do_import_for_namespace/3 全局先导入 cluster.hocon 再导 mnesia 表 └─ import_cluster_hocon/2 └─ do_import_cluster_hocon/4 ├─ upgrade_raw_conf/2 schema 模块升级 ├─ validate_cluster_hocon/2 emqx_hocon:check 预检 └─ do_import_conf/3 真正写回配置 └─ emqx_conf_dep_registry:sorted_importer_modules()配置写回的核心在do_import_conf/3emqx_mgmt_data_backup.erl 第 1612-1622 行do_import_conf(Namespace, RawConf, Opts) - GenConfErrs filter_errors(maps:from_list(import_generic_conf(Namespace, RawConf))), maybe_print_conf_errors(GenConfErrs, Opts), Modules emqx_conf_dep_registry:sorted_importer_modules(), Errors lists:foldl( print_ok_results_collect_errors(Namespace, RawConf, Opts), GenConfErrs, Modules ), ...可以看到导入器importer模块的执行顺序不是固定写死的而是由emqx_conf_dep_registry:sorted_importer_modules()动态计算得出。这正是 #14988 修复的核心所在。导入依赖的拓扑排序机制emqx_config_backup 行为任何希望参与备份恢复配置导入的模块都需要实现emqx_config_backup行为emqx_config_backup.erl核心回调为-callback import_config(emqx_config:maybe_namespace(), RawConf :: map()) - {ok, ok_result()} | {error, error_result()} | {results, {[ok_result()], [error_result()]}}.本项目涉及的三个导入器及其实现位置配置根键导入器模块实现位置schema_registryemqx_schema_registry_configemqx_schema_registry_config.erlschema_validationemqx_schema_validation_configemqx_schema_validation_config.erlmessage_transformationemqx_message_transformation_configemqx_message_transformation_config.erl依赖声明文件 importer_dependencies.eterm导入器之间的依赖关系集中声明在 apps/emqx_conf/priv/importer_dependencies.eterm 中#{ emqx_rule_engine_config #{ root_keys [rule_engine], dependencies [emqx_bridge_v2, emqx_schema_registry_config] }, emqx_bridge_v2 #{ root_keys [actions, sources], dependencies [emqx_connector] }, emqx_connector #{ root_keys [connectors], dependencies [] }, emqx_message_transformation_config #{ root_keys [message_transformation], dependencies [emqx_schema_registry_config] }, emqx_schema_validation_config #{ root_keys [schema_validation], dependencies [emqx_schema_registry_config] } }这个文件精确记录了Schema Validation 与 Message Transformation 都依赖emqx_schema_registry_config。在 #14988 修复之前这类依赖关系要么缺失、要么未被导入流程采纳导致备份中同时包含这三类配置时schema_validation或message_transformation可能在schema_registry尚未写回时先行导入。有向无环图的构建与拓扑排序emqx_conf_dep_registry.erl 读取上述.eterm文件将依赖关系建模为有向无环图DAGdo_add_dependency(G, Module, Dependency) - digraph:add_vertex(G, Module), digraph:add_vertex(G, Dependency), case has_edge(G, Module, Dependency) of true - ok; false - case digraph:add_edge(G, Dependency, Module) of {error, _} - {error, {cycle, Dependency, Module}}; _ - ok end end. do_sorted_importer_modules(G, AllModules) - SortedDeps digraph_utils:topsort(G), OtherModules AllModules -- SortedDeps, SortedDeps OtherModules.要点边方向digraph:add_edge(G, Dependency, Module)表示依赖者排在依赖项之后即先导入emqx_schema_registry_config再导入emqx_schema_validation_config环检测若声明出循环依赖如a - b与b - ado_add_dependency/3会返回{error, {cycle, ...}}拒绝建立边模块中的 eunit 测试sort_test_覆盖了环检测场景拓扑排序digraph_utils:topsort/1产出满足依赖约束的执行序列未在依赖图中登记的导入器模块追加在排序结果之后根键唯一性断言do_initialize_dependency_graph/4断言每个 root key 只归属于一个导入器防止多个模块争抢同一个配置根。排序后的模块列表被do_import_conf/3依序调用各自的import_config/2从而保证Schema Registry 一定先于依赖它的 Schema Validation 与 Message Transformation 落盘。三个导入器的实现细节对比三个导入器都通过emqx_conf:update/3写回配置但处理方式略有不同Schema Registryemqx_schema_registry_config.erl 第 220-240 行读取旧配置后做deep_merge再整体更新schema_registry根随后在post_config_update中完成 schema 导入handle_import_schemas与外部注册表导入handle_import_external_registries。Schema Validationemqx_schema_validation_config.erl 第 247-262 行与Message Transformationemqx_message_transformation_config.erl 第 219-234 行均以{merge, RawConf0}的方式调用emqx_conf:update并附带rawconf_with_defaults true导入后通过post_config_update将每条校验规则 / 转换器注册到运行期注册表registry。由于 Schema Validation 的每条校验规则会引用 Schema Registry 中已注册的 schemaMessage Transformation 的转换器同理当 schema 尚未导入时注册流程就会因找不到引用的 schema 而校验失败——这正是 #14988 要消除的时序问题。修复后依赖拓扑保证了schema_registry根键永远先于schema_validation与message_transformation导入。修复验证从测试用例看保障仓库测试对修复形成了双重保障1. 依赖排序单元测试emqx_conf_dep_registry内嵌的 eunit 用例如simple test 1声明b依赖c期望顺序[c, b, a, d]直接验证了拓扑排序的正确性。2. 备份恢复集成测试 emqx_mgmt_data_backup_SUITE.erl 构建了包含connectors、actions、sources、rule_engine、schema_registry等多个配置根的备份场景t_export_cloud_subset第 255-299 行并断言导出包内配置根键集合与预期一致测试还通过 REST API 先创建名为schema1的 JSON Schema第 1779-1793 行随后执行emqx_mgmt_data_backup:export()/import()往返验证导入后数据完整如 retained 消息恢复场景第 246-253 行。这些用例覆盖了备份含 schema 及其消费者配置的路径确保依赖顺序修复不会回归。运维视角规避与排查建议对 EMQX 使用者而言可从以下几点受益于本次修复恢复含 Schema Validation / Message Transformation 的备份升级到包含 #14988 修复的版本如 5.9.0 及之后后POST /data/import恢复备份时会自动按依赖顺序导入配置不再出现先导入校验规则、后导入 schema导致的校验错误。观察导入结果导入完成后接口返回#{db_errors, config_errors}结果结构若仍出现配置根导入失败错误信息形如Failed to import the following config path: schema_validation, reason: ...可通过 emqx_mgmt_data_backup.erl 中的format_conf_errors/1、format_error/1定位具体原因。理解依赖声明文件的作用新增自定义配置导入器时需在apps/emqx_conf/priv/importer_dependencies.eterm中正确声明dependencies否则会出现与 #14988 类似的导入时序问题同时注意避免声明出环形依赖构建期会报{cycle, ...}错误。总结Issue #14988 修复的并非某个孤立 bug而是 EMQX 备份恢复体系中配置导入顺序这一系统性问题通过把导入器之间的依赖关系显式化importer_dependencies.eterm、以有向无环图做拓扑排序emqx_conf_dep_registry并让恢复流程严格依序调用各模块的import_config/2最终保证 Schema Registry 永远先于其消费者Schema Validation、Message Transformation、Rule Engine被导入。这一机制为后续新增任何具有依赖关系的配置模块提供了可扩展的排序框架是理解 EMQX 备份恢复实现与配置依赖建模的关键切入点。延伸阅读备份文件格式与校验逻辑见 emqx_mgmt_data_backup.erl配置导入器行为契约见 emqx_config_backup.erl依赖排序实现与单测见 emqx_conf_dep_registry.erl 与 importer_dependencies.eterm。赞分享后端物联网消息队列通信【免费下载链接】emqxThe most scalable and reliable MQTT broker for AI, IoT, IIoT and connected vehicles项目地址https://gitcode.com/gh_mirrors/em/emqx点击查看免费下载相关推荐listmonk容器编排备份恢复配置与数据恢复listmonk容器编排备份恢复配置与数据恢复 你是否曾因服务器故障丢失过重要的邮件列表数据是否担心过配置文件损坏导致服务无法启动本文将通过容器化部署场景后端企业应用EMQX Schema Registry 修复draft-06 JSON Schema 中 examples 注解导致合法数据被误判为非法EMQX Schema Registry 修复draft 06 JSON Schema 中 examples 注解导致合法数据被误判为非法 导读 在 EMQX后端物联网消息队列通信grpc-gateway备份恢复配置数据备份与灾难恢复方案grpc gateway备份恢复配置数据备份与灾难恢复方案 概述 在微服务架构中gRPC Gateway作为gRPC服务与RESTful API之间的桥梁后端API网关开发工具gRPC创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
觉得有用,分享给同行:

为您的企业打造数字门面

稳重轻奢商务风格,端正雅致视觉,长效耐看不易过时。

立即咨询 →