docs(backend): 完善 IMPROVEMENTS.md - 添加环境区分机制解决方案
This commit is contained in:
210
IMPROVEMENTS.md
210
IMPROVEMENTS.md
@@ -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
|
||||||
|
|||||||
Reference in New Issue
Block a user