Rust 配置管理实战:用 config crate 读取多格式配置与环境切换

test12026-10-142 次阅读

它能读哪些格式

config crate 把配置来源抽象成一套统一的 Builder:支持 TOML、YAML、JSON、ini,也支持环境变量和命令行参数,并且可以多层合并——比如默认配置 + 环境配置文件 + 环境变量覆盖,越靠后的来源优先级越高。

定义配置结构体

用 serde 的 Deserialize 把配置反序列化成一个强类型结构,取配置时就有编译期保证,拼写错了立刻报错。

use serde::Deserialize;

#[derive(Debug, Deserialize)]
struct Config {
    server: ServerConfig,
    database: DatabaseConfig,
}

#[derive(Debug, Deserialize)]
struct ServerConfig {
    host: String,
    port: u16,
}

#[derive(Debug, Deserialize)]
struct DatabaseConfig {
    url: String,
    max_pool_size: u32,
}

加载多环境配置

先加一个默认文件,再根据当前环境(这里用环境变量 RUN_ENV)叠加对应的配置文件。config 会自动用一个文件里顶层 key 名为环境名的部分做覆盖。

use config::{Config, File, Environment};

fn load_config() -> Result<Config, config::ConfigError> {
    let run_env = std::env::var("RUN_ENV").unwrap_or_else(|_| "dev".into());

    let cfg = Config::builder()
        .add_source(File::with_name("config/default"))
        .add_source(File::with_name(&format!("config/{}", run_env)).required(false))
        .add_source(Environment::with_prefix("APP").separator("__"))
        .build()?;

    Ok(cfg)
}

环境变量覆盖

上面 Environment 配置了 APP__ 前缀,那么环境变量 APP__DATABASE__URL 会覆盖 config 文件里的 database.url。双层下划线被当成层级分隔,非常适合容器环境用环境变量注入密钥。

// config/default.toml
[server]
host = "127.0.0.1"
port = 8080

[database]
url = "sqlite://local.db"
max_pool_size = 8
# 运行时覆盖数据库地址
APP__DATABASE__URL="postgres://user:pass@db:5432/app" RUN_ENV=prod ./app

反序列化成强类型并使用

最终调用 try_deserialize,拿到的是一个 Rust 结构体,后续代码全程用字段访问,不会出现字符串 key 到处飘。

fn main() -> Result<(), Box<dyn std::error::Error>> {
    let settings = load_config()?.try_deserialize::<Config>()?;
    println!("listen on {}:{}", settings.server.host, settings.server.port);
    println!("db pool = {}", settings.database.max_pool_size);
    Ok(())
}

可选的热更新

如果希望配置变更不用重启,config crate 本身不带 watch,可以配合 notify 监听文件变化后重新 build 一份。大多数服务用信号(如收到 SIGHUP 重新加载)就够用,避免过度设计。

T

test1

文章作者

它能读哪些格式 config crate 把配置来源抽象成一套统一的 Builder:支持 TOML、YAML、JSO...

分类
技术
发布时间
2026-10-14
字数
约 1876 字
阅读
2 次