
如何在 MongoDB 的 IDL 文件中定义新的 server parameter 并支持运行时设置【免费下载链接】mongoThe MongoDB Database项目地址: https://gitcode.com/GitHub_Trending/mo/mongoMongoDB 服务端mongod和mongos的很多行为都通过 server parameter 配置比如控制日志级别verbosity的logLevel既能在启动时设置也能在运行时通过命令修改。如果你要为服务端新增一个可配置项并且希望它在运行时可以修改而不只是启动参数正确的做法是在 IDL 文件的server_parameters段中声明它IDL 编译器会解析这段 YAML 并生成 C 代码生成代码会在进程启动时自动把参数注册到运行时无需手写注册逻辑。本文基于 docs/server_parameters.md 和 docs/idl.md给出从定义、接入构建到启动时/运行时设置与验证的完整路径。前提条件你的代码库已经在使用 IDL 机制。IDL 是用 YAML 1.1 编写的 DSL编译器位于 buildscripts/idl/生成的 C 支持代码位于 src/mongo/idl 目录。一个 IDL 文件由若干顶层 section 组成其中server_parameterssection 专门用于声明 server parameter见 docs/idl.md 的 The IDL file 一节。构建系统Bazel负责调用 IDL 编译器生成_gen.h/_gen.cpp两个文件。参考实例现成的logLevel参数定义在 src/mongo/db/commands/parameters.idl带存储的测试参数示例在 src/mongo/idl/server_parameter_with_storage_test.idl。在 IDL 文件中声明一个可运行时修改的参数server_parameters段中每个条目对应一个参数参数名在服务器实例内必须唯一。完整语法字段含义以 docs/server_parameters.md 的 Server Parameters Syntax 一节为准server_parameters: nameOfParameter: # string set_at: # string or list of strings description: # string cpp_vartype: # string cpp_varname: # string default: # string or expression map validator: # Map: lt / gt / lte / gte / callback on_update: # string redact: # bool其中set_at和description是必填字段redact也是必填字段且必须显式写为false才能关闭脱敏设为true时该参数的值会在日志/输出中被替换为占位符适合密码类设置。要支持运行时修改set_at必须包含runtime取值为startup、runtime、[startup, runtime]或cluster之一。关键约束当runtime与cpp_varname一起指定时decltype(cpp_varname)必须是线程安全的存储类型文档明确列出的类型为AtomicT、std::atomicT或boost::synchronizedT。下面是一个可直接对照的最小示例字段取值方式参照 src/mongo/idl/server_parameter_with_storage_test.idl 中stdIntDeclared等条目的写法声明一个整数参数可在启动和运行时修改取值范围 0 到 999global: cpp_namespace: mongo imports: - mongo/db/basic_types.idl server_parameters: myExampleParam: set_at: [startup, runtime] description: An example runtime-settable integer parameter cpp_vartype: Atomicint cpp_varname: gMyExampleParam default: 0 validator: gte: 0 lt: 100 redact: false示例中各字段的作用均来自源文档cpp_vartypecpp_varname声明底层存储。两者同时给出时IDL 会把存储声明为全局变量并在生成的头文件中 extern 出来供你的 C 代码直接读取。default初始值可以是字面量字符串也可以是包含expr字段的 YAML map表达式 mapexpr的值是任意 C 表达式例如std::numeric_limitsint::max()未显式给出is_constexpr: false时该表达式会被包进[]{ constexpr auto value expr; return value; }()以保证不依赖运行时信息。validator零到多条校验规则全部通过新值才算有效。lt/gt/lte/gte提供简单数值边界其他校验场景用callback指定一个 C 函数或静态方法其原型为Status(const cpp_vartype, const boost::optionalTenantId)。注意各校验规则含 callback的执行顺序不保证若要在所有校验完成后执行动作应使用on_update而不是validator.callback。on_update所有校验规则成功完成且新值已存入后调用的 C 回调原型为Status(const cpp_vartype);。imports中的mongo/db/basic_types.idl是 IDL 的基础类型文件声明了标准 BSON 类型docs/idl.md 指出没有它 IDL 不知道如何读写 string、int 等基本类型。condition、test_only、deprecated_name、is_deprecated等字段可按需添加语义以 docs/server_parameters.md 为准例如test_only: true表示在未指定enableTestCommands时禁用该参数is_deprecated会在参数被使用时向用户发出警告。把 IDL 文件接入 Bazel 构建生成_gen.h/_gen.cpp需要构建系统调用 IDL 编译器。如果你在已有的 IDL 文件如parameters.idl的server_parameters段里加条目只需确保对应的生成目标已存在。src/mongo/db/commands/BUILD.bazel 中parameters.idl对应的就是idl_generator目标src parameters.idl。如果是新建 IDL 文件参照 docs/idl.md 的示例在所在目录的BUILD.bazel中添加mongo_idl_library( namemy_example, src[ my_example.idl, ], deps[ //src/mongo/idl:idl_parser, ], )Bazel 知道如何调用 IDL 编译器并在构建目录生成 C 代码生成的文件头部有警告说明不能手工修改重新构建会覆盖文件顶部还打印了不经过构建系统时的手动生成命令如python buildscripts/idl/idlc.py idl 文件路径见 docs/idl.md Overview 一节。在 C 中读取参数值文档给出的两种获取方式直接访问参数对应的 C 表达式例如读serverGlobalParams.quiet获得quiet的当前值用上面的示例就是读取gMyExampleParam由cpp_vartypecpp_varname生成并在头文件 extern 的全局变量。注册变更回调例如 src/mongo/db/ftdc/ftdc_server.idl 中diagnosticDataCollectionFileSizeMB使用onUpdateFTDCFileSize。对应到 IDL 里就是on_update字段。每个被声明的 server parameter 都会在进程启动时生成一段自注册代码文档给出的示例块如下文档示例展示scramIterationCount的生成结果其中addBoundpredicate::GTE(5000)来自该参数配置的 validator/** * Iteration count to use when creating new users with * SCRAM-SHA-1 credentials */ MONGO_COMPILER_VARIABLE_UNUSED auto* scp_unique_ident [] { using T decltype(saslGlobalParams.scramSHA1IterationCount); constexpr auto setAt ServerParameterType::kStartupAndRuntime; auto ret new IDLServerParameterWithStorageT( scramIterationCount, saslGlobalParams.scramSHA1IterationCount, setAt); ret-addBoundpredicate::GTE(5000); return ret; }();生成代码嵌套在global.cpp_namespace定义的命名空间内参数用到的全局变量、回调等符号需要通过 IDL 常规的globals.cpp_includes导入对应头文件。例如 validator callbackvalidateOpensslCipherConfig声明在mongo/util/net/ssl_parameters.h中就需要在cpp_includes里列出该头文件。验证启动时设置、运行时设置与查询参数能否被设置由set_at决定启动时set_at含startup使用命令行选项--setParameter传入参数。运行时set_at含runtime使用setParameter命令修改getParameter命令可用于查询任意 server parameter 的当前值。也就是说验证你新参数是否生效的路径是先用--setParameter myExampleParam合法值启动配合validator检查非法值会被拒绝运行中再通过setParameter修改最后用getParameter确认当前值。若参数名唯一性、类型或校验配置有误会在编译或 IDL 解析阶段报错而不是运行期静默失败。可选分支用 cpp_class 实现自定义 ServerParameter 类如果简单的存储 校验不够用例如logLevel可以声明cpp_class让 IDL 在gen.h中生成一个ServerParameter子类由你实现解析逻辑。logLevel的声明长这样来自 src/mongo/db/commands/parameters.idlserver_parameters: logLevel: description: Specifies the verbosity of logging set_at: [startup, runtime] cpp_class: name: LogLevelServerParameter override_set: true redact: false指定cpp_class后cpp_varname未定义时cpp_class必填各方法的实现要求如下表来自 docs/server_parameters.md Specialized Server ParametersServerParameter方法是否可覆盖默认行为构造函数可选只实例化 name 和 type。set()可选调用setFromString()处理新值的字符串表示。setFromString()必须实现无实现则无法编译。append() // redacttrue可选用占位符替换参数值。append() // redactfalse必须实现无实现则无法编译。validate()可选直接返回Status::OK()不做任何检查。warnIfDeprecated()可选若已弃用首次使用时警告。方法签名如Status {name}::setFromString(StringData value, const boost::optionalTenantId tenantId);。默认情况下 server parameter 不感知租户tenantId恒为boost::none集群参数除外。完整实现示例见 src/mongo/idl/server_parameter_specialized_test.idl 与 src/mongo/idl/server_parameter_specialized_test.h。限制与边界redact必填且需显式赋值set_at与description必填。运行时参数必须使用线程安全存储类型AtomicT、std::atomicT、boost::synchronizedT这是文档明确的硬性要求。set_at: cluster定义的是集群 server parameter只能通过setClusterParameter在运行时设置并持久化到config.clusterParameters集合omit_in_ftdc字段也只对集群参数可用普通参数的getParameter查询路径与它不同本文不展开该拓扑下的操作流程。生成文件_gen.h/_gen.cpp不可手工修改改动只能落在 IDL 源文件上重新构建时会被重新生成。下一步如果你的 IDL 声明本身要扩展新增字段或语法docs/idl.md Developer Workflow 一节要求在idl_test.cpp、buildscripts/idl/tests 中补测试并更新idl_schema.json的 schema调试 IDL 脚本时建议直接调用 IDL 编译器而不是走构建系统以加快迭代。【免费下载链接】mongoThe MongoDB Database项目地址: https://gitcode.com/GitHub_Trending/mo/mongo创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考