docs(backend): 完善 IMPROVEMENTS.md - 添加环境区分机制解决方案

This commit is contained in:
2026-04-14 11:28:41 +08:00
parent ce34896525
commit 98ef90b01e

View File

@@ -304,27 +304,231 @@
- 影响:开发效率 - 影响:开发效率
- 工作量:中等 - 工作量:中等
## 九、检查清单 ## 十、缺少环境区分机制
### 问题描述
当前后端项目未区分生产环境和开发/测试环境,所有配置混在一个 `.env` 文件中。
**现状分析**
| 配置项 | 当前做法 | 问题 |
|--------|----------|------|
| DATABASE_URL | 硬编码生产数据库地址 | 开发/测试时无法切换到本地或测试数据库 |
| JWT_SECRET | 混在 .env 中 | 开发环境使用弱密钥存在安全隐患 |
| RUST_LOG | 统一设置为 `info` | 开发时需要 `debug` 级别日志 |
| APP_VERSION | 在 .env 和 Cargo.toml 两处定义 | 版本不一致 |
**.env 当前内容**
```bash
DATABASE_URL=postgres://milkydata:***@154.37.213.24:5432/milkydata
WECHAT_APPID="wx5b00eb90621802f7"
WECHAT_SECRET="494efc...9bfd"
JWT_SECRET="your_s..._key"
SSL_KEY_PATH=/etc/ssl/private/private.key
SSL_CERT_PATH=/etc/ssl/certs/full_chain.pem
RUST_LOG=info
APP_VERSION="0.2.0"
FREE_USER_DATA_LIMIT=20
```
### 影响
- 开发时连接生产数据库,有误操作风险
- 测试时无法使用独立的测试数据
- 切换环境需要手动修改配置,容易出错
- 生产配置泄露到代码仓库(.env 通常被 gitignore但部署时容易混淆
### 解决方案
#### 方案一:使用 config crate推荐
**添加依赖**
```toml
# Cargo.toml
[dependencies]
config = "0.14"
serde = { version = "1.0", features = ["derive"] }
```
**目录结构**
```
rust-backend/
├── config/
│ ├── default.toml # 默认配置(开发)
│ ├── development.toml
│ └── production.toml
├── .env # 本地敏感配置(加入 .gitignore
└── .env.example # 配置模板(提交到仓库)
```
**default.toml开发/测试默认)**
```toml
database_url = "postgres://milkydata:password@localhost:5432/milkydata_dev"
wechat_appid = "wx_test_appid"
wechat_secret = "test_secret"
jwt_secret = "dev-only-secret-change-in-production"
ssl_key_path = ""
ssl_cert_path = ""
rust_log = "debug"
app_version = "0.2.3"
environment = "development"
free_user_data_limit = 100
server_host = "0.0.0.0"
server_port = 8080
```
**production.toml生产环境**
```toml
database_url = "postgres://milkydata:***@154.37.213.24:5432/milkydata"
wechat_appid = "wx5b00eb90621802f7"
wechat_secret = "***"
jwt_secret = "***"
ssl_key_path = "/etc/ssl/private/private.key"
ssl_cert_path = "/etc/ssl/certs/full_chain.pem"
rust_log = "info"
app_version = "0.2.3"
environment = "production"
free_user_data_limit = 20
server_host = "0.0.0.0"
server_port = 8080
```
**配置加载逻辑**
```rust
// src/config.rs
use config::{Config, ConfigError, File};
use serde::Deserialize;
#[derive(Debug, Deserialize, Clone)]
pub struct AppConfig {
pub database_url: String,
pub wechat_appid: String,
pub wechat_secret: String,
pub jwt_secret: String,
pub ssl_key_path: String,
pub ssl_cert_path: String,
pub rust_log: String,
pub app_version: String,
pub environment: String,
pub free_user_data_limit: i32,
pub server_host: String,
pub server_port: u16,
}
impl AppConfig {
pub fn load() -> Result<Self, ConfigError> {
// 从环境变量读取当前环境,默认为 development
let env = std::env::var("APP_ENV").unwrap_or_else(|_| "development".into());
let config = Config::builder()
// 1. 先加载默认配置
.add_source(File::with_name("config/default"))
// 2. 再加载当前环境配置(覆盖默认值)
.add_source(File::with_name(&format!("config/{}", env)).required(false))
// 3. 最后从环境变量加载(最高优先级)
.add_source(config::Environment::with_prefix("APP"))
.build()?;
config.try_deserialize()
}
}
```
#### 方案二:简化方案(最小改动)
保持现有 `.env` 结构不变,通过 `APP_ENV` 环境变量和 `.env.development` / `.env.production` 文件区分:
**`.env.example`(提交到仓库的配置模板)**
```bash
# 必填配置
DATABASE_URL=postgres://user:pass@host:port/dbname
JWT_SECRET=your-secret-key
WECHAT_APPID=your-wechat-appid
WECHAT_SECRET=your-wechat-secret
# 可选配置(带默认值)
APP_ENV=development
RUST_LOG=info
APP_VERSION=0.2.3
FREE_USER_DATA_LIMIT=20
SSL_KEY_PATH=
SSL_CERT_PATH=
```
**部署脚本增强**
```bash
#!/bin/bash
# deploy.sh
# 接收环境参数
ENV=${1:-production}
# 根据环境加载不同配置
if [ "$ENV" = "development" ]; then
source .env.development
elif [ "$ENV" = "production" ]; then
source .env.production
fi
# 构建和部署...
```
### 环境切换操作指南
| 场景 | 操作方法 |
|------|----------|
| 本地开发 | `APP_ENV=development cargo run`,连接本地数据库 |
| 测试服务器部署 | `APP_ENV=development ./deploy.sh` |
| 生产环境部署 | `APP_ENV=production ./deploy.sh` 或默认 `./deploy.sh` |
| 查看当前环境 | 启动后访问 `/health` 接口或检查日志 |
### 实施步骤
**第一阶段(最小改动)**
1. 创建 `.env.example` 配置模板,移除敏感信息
2. 在 `deploy.sh` 中添加 `APP_ENV` 参数支持
3. 创建 `.env.development` 本地开发配置(可选加入 .gitignore
**第二阶段(推荐)**
1. 添加 `config` crate 依赖
2. 创建 `config/default.toml` 和 `config/production.toml`
3. 重构 `config.rs` 使用 config crate
4. 更新 `deploy.sh` 使用新的配置加载方式
### 相关改进项
- 本改进与"前后端版本统一管理"(改进路线图 P1可合并实施
- 本改进与"拆分 main.rs 路由处理器"(改进路线图 P1有协同效应
---
## 十一、检查清单
### 代码提交前检查 ### 代码提交前检查
- [ ] 通过 `cargo clippy` 检查 - [ ] 通过 `cargo clippy` 检查
- [ ] 通过 `cargo fmt` 格式化 - [ ] 通过 `cargo fmt` 格式化
- [ ] 单元测试通过 - [ ] 单元测试通过
- [ ] 无硬编码的敏感信息 - [ ] 无硬编码的敏感信息
- [ ] 配置文件不包含实际密钥
### 部署前检查 ### 部署前检查
- [ ] 数据库迁移脚本准备 - [ ] 数据库迁移脚本准备
- [ ] 环境变量配置检查 - [ ] 环境变量配置检查
- [ ] 备份当前版本 - [ ] 备份当前版本
- [ ] 健康检查接口正常 - [ ] 健康检查接口正常
- [ ] 确认目标环境的配置正确
### 安全检查 ### 安全检查
- [ ] 输入验证完整 - [ ] 输入验证完整
- [ ] 错误信息不暴露敏感数据 - [ ] 错误信息不暴露敏感数据
- [ ] 认证和授权正确 - [ ] 认证和授权正确
- [ ] 日志不记录敏感信息 - [ ] 日志不记录敏感信息
- [ ] 生产环境使用强密钥
--- ---
**最后更新**2026-04-13 **最后更新**2026-04-14
**维护者**开发团队 **维护者**milky