Files
life-echo/api/docs/部署指南.md
Sully 53e0065e3e refactor(api): TOML 配置 SSOT、统一错误契约、Auth/事务加固与可观测性 (#33)
配置 SSOT(TOML + .env)
统一错误契约
Auth 与事务边界
Redis / Celery 可靠性:业务 Redis(DB/0)与 Celery broker/backend(DB/1)显式拆分;连接池、sync client
可观测性(OpenTelemetry + LGTM)
2026-05-22 13:44:50 +08:00

598 lines
13 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 短信验证码功能部署指南
## 概述
本文档说明如何在生产环境中部署短信验证码功能,包括环境配置、数据库迁移、服务配置等。
## 前置条件
1. PostgreSQL 数据库已安装并运行
2. Redis 服务已安装并运行
3. 已注册腾讯云账号并开通短信服务
4. 已获取腾讯云短信服务凭证
## 部署步骤
### 1. 腾讯云短信服务配置
#### 1.1 登录腾讯云控制台
访问https://console.cloud.tencent.com/smsv2
#### 1.2 创建短信应用
1. 进入"应用管理"
2. 点击"创建应用"
3. 填写应用名称Life Echo
4. 记录生成的 SDK AppID
#### 1.3 配置短信签名
1. 进入"国内短信" -> "签名管理"
2. 点击"创建签名"
3. 填写签名内容(如:【人生回响】)
4. 选择签名类型App
5. 上传相关证明材料
6. 等待审核通过
#### 1.4 配置短信模板
创建一个通用的验证码模板(所有场景共用):
**验证码模板:**
```
【人生回响】您的验证码是:{1},有效期{2}分钟,请勿泄露给他人。
```
**模板参数说明:**
- `{1}` - 验证码6位数字
- `{2}` - 有效期分钟数5
**注意:** 所有场景(注册、登录、重置密码、修改手机号)共用同一个模板。
记录模板ID。
#### 1.5 获取API密钥
1. 访问https://console.cloud.tencent.com/cam/capi
2. 点击"新建密钥"
3. 记录 SecretId 和 SecretKey
4. **重要:妥善保管密钥,不要泄露**
### 2. 环境变量配置
配置分两层,详见 [configuration.md](configuration.md)
- **`.env`secrets + bootstrap**:数据库/Redis 连接串、`SECRET_KEY`、腾讯云 API 密钥等
- **`config/{APP_ENV}.toml`(非密钥)**SMS 应用 ID/签名/模板、JWT 过期时间、CORS 等
#### 2.1 编辑生产环境配置文件
编辑 `api/.env.production`(密钥与连接串):
```bash
APP_ENV=production
DATABASE_URL=postgresql://username:password@host:5432/life_echo
# Redis业务 DB/0Celery broker/backend 使用 DB/1
REDIS_URL=redis://redis:6379/0
REDIS_PASSWORD=your_redis_password_here
# 生产 compose 已显式注入;本地或自定义部署请设:
CELERY_REDIS_URL=redis://:your_redis_password_here@redis:6379/1
# 升级至 DB 分离后DB/0 上未消费的 Celery 队列会被丢弃(一次性 cutover
# REDIS_URL 使用 DB/15 时必须显式设置 CELERY_REDIS_URL无法 auto DB+1
# Auth生产务必openssl rand -hex 32
SECRET_KEY=your_strong_random_secret_here
# 腾讯云 API 密钥SMS / ASR / TTS / COS 共用)
TENCENT_SECRET_ID=your_secret_id_here
TENCENT_SECRET_KEY=your_secret_key_here
```
编辑 `api/config/production.toml`SMS 业务 ID 等非密钥项):
```toml
[deploy]
tencent_sms_sdk_app_id = "1400xxxxxx"
tencent_sms_sign_name = "人生回响"
tencent_sms_template_id = "123456"
api_cors_origins = "https://your-domain.com"
access_token_expire_minutes = 30
refresh_token_expire_days = 7
```
#### 2.2 配置说明
| 配置项 | 层级 | 说明 | 示例 |
|--------|------|------|------|
| `SECRET_KEY` | `.env` | JWT 签名密钥 | `openssl rand -hex 32` 输出 |
| `TENCENT_SECRET_ID` | `.env` | 腾讯云 API 密钥 ID | `AKIDxxxxxxxxxxxxx` |
| `TENCENT_SECRET_KEY` | `.env` | 腾讯云 API 密钥 Key | `xxxxxxxxxxxxxxxx` |
| `tencent_sms_sdk_app_id` | `config/production.toml` | 短信应用 ID | `1400xxxxxx` |
| `tencent_sms_sign_name` | `config/production.toml` | 短信签名(不含【】) | `人生回响` |
| `tencent_sms_template_id` | `config/production.toml` | 短信模板 ID所有场景共用 | `123456` |
| `api_cors_origins` | `config/production.toml` | 浏览器跨域允许来源(逗号分隔) | `https://lifecho.worldsplats.com` |
| `access_token_expire_minutes` | `config/production.toml` | Access token 有效期(分钟) | `30` |
| `refresh_token_expire_days` | `config/production.toml` | Refresh token 有效期(天) | `7` |
### 3. 数据库迁移
#### 3.1 备份数据库
```bash
# 备份现有数据库
pg_dump -U postgres -d life_echo > backup_$(date +%Y%m%d_%H%M%S).sql
```
#### 3.2 执行迁移脚本
```bash
# 方式1使用psql命令
psql -U postgres -d life_echo -f api/migrations/add_sms_verification.sql
# 方式2使用数据库管理工具
# 打开 pgAdmin 或其他工具,执行 add_sms_verification.sql 中的SQL语句
```
#### 3.3 验证迁移结果
```sql
-- 检查表是否创建成功
SELECT * FROM information_schema.tables
WHERE table_name = 'sms_verification_codes';
-- 检查索引是否创建成功
SELECT indexname FROM pg_indexes
WHERE tablename = 'sms_verification_codes';
-- 检查 refresh_tokens 表是否添加了 device_info 字段
SELECT column_name, data_type
FROM information_schema.columns
WHERE table_name = 'refresh_tokens' AND column_name = 'device_info';
```
### 4. 依赖安装
#### 4.1 更新Python依赖
```bash
cd api
pip install -r requirements.txt
```
确保 `requirements.txt` 中包含:
```
tencentcloud-sdk-python>=3.0.1000
```
#### 4.2 验证依赖安装
```bash
python -c "from tencentcloud.sms.v20210111 import sms_client; print('腾讯云SDK安装成功')"
```
### 5. 服务部署
#### 5.1 使用Docker部署
编辑 `api/docker-compose.yml`,添加环境变量:
```yaml
version: '3.8'
services:
api:
build: .
ports:
- "8000:8000"
env_file:
- .env
environment:
- APP_ENV=production
- DATABASE_URL=${DATABASE_URL}
- REDIS_URL=${REDIS_URL}
- REDIS_PASSWORD=${REDIS_PASSWORD}
- SECRET_KEY=${SECRET_KEY}
- TENCENT_SECRET_ID=${TENCENT_SECRET_ID}
- TENCENT_SECRET_KEY=${TENCENT_SECRET_KEY}
depends_on:
- postgres
- redis
restart: unless-stopped
postgres:
image: postgres:15
environment:
- POSTGRES_DB=life_echo
- POSTGRES_USER=postgres
- POSTGRES_PASSWORD=${POSTGRES_PASSWORD}
volumes:
- postgres_data:/var/lib/postgresql/data
restart: unless-stopped
redis:
image: redis:7
restart: unless-stopped
volumes:
postgres_data:
```
启动服务:
```bash
cd api
docker compose up -d
```
#### 5.2 使用Systemd部署
创建服务文件 `/etc/systemd/system/life-echo-api.service`
```ini
[Unit]
Description=Life Echo API Service
After=network.target postgresql.service redis.service
[Service]
Type=simple
User=www-data
WorkingDirectory=/path/to/life-echo/api
Environment="PATH=/path/to/venv/bin"
EnvironmentFile=/path/to/life-echo/api/.env.production
ExecStart=/path/to/venv/bin/python main.py
Restart=always
RestartSec=10
[Install]
WantedBy=multi-user.target
```
启动服务:
```bash
sudo systemctl daemon-reload
sudo systemctl enable life-echo-api
sudo systemctl start life-echo-api
sudo systemctl status life-echo-api
```
### 6. GitHub Actions配置
如果使用GitHub Actions自动部署需要配置Secrets
1. 进入GitHub仓库 -> Settings -> Secrets and variables -> Actions
2. 添加以下Secrets
| Secret名称 | 说明 |
|-----------|------|
| `SECRET_KEY` | JWT 签名密钥 |
| `TENCENT_SECRET_ID` | 腾讯云 API 密钥 ID |
| `TENCENT_SECRET_KEY` | 腾讯云 API 密钥 Key |
| `DATABASE_URL` | 数据库连接串 |
| `REDIS_PASSWORD` | Redis 密码(若启用) |
SMS 应用 ID、签名、模板 ID 等非密钥项在 `config/production.toml``[deploy]` 中维护,随代码发版。
参考文档:`github-actions-secrets.md`
### 7. 验证部署
#### 7.1 健康检查
```bash
curl http://localhost:8000/health
```
预期响应:
```json
{
"status": "healthy"
}
```
#### 7.2 测试发送验证码
```bash
curl -X POST http://localhost:8000/api/auth/sms/send \
-H "Content-Type: application/json" \
-d '{
"phone": "13800138000",
"purpose": "register"
}'
```
预期响应:
```json
{
"message": "验证码已发送",
"expires_in": 300
}
```
#### 7.3 检查日志
```bash
# Docker部署
docker compose logs -f api
# Systemd部署
sudo journalctl -u life-echo-api -f
```
### 8. 监控与告警
本地开发与预发可观测性栈OpenTelemetry + Grafana LGTM**[可观测性指南](observability.md)**。staging/production 全量接入为第二阶段(`docker-compose` profile
#### 8.1 配置日志监控
建议使用以下工具:
- **Grafana + Loki + Tempo + Prometheus**(仓库内 `deploy/observability/`,推荐)
- ELK Stack (Elasticsearch + Logstash + Kibana)
- 云服务商的日志服务
#### 8.2 配置性能监控
监控指标:
- API响应时间
- 短信发送成功率
- 验证码验证成功率
- 数据库查询性能
- Redis连接状态
#### 8.3 配置告警
告警规则:
- 短信发送失败率 > 5%
- API响应时间 > 2秒
- 数据库连接失败
- Redis连接失败
- 磁盘空间 < 20%
### 9. 安全加固
#### 9.1 防火墙配置
```bash
# 仅允许必要的端口
sudo ufw allow 22/tcp # SSH
sudo ufw allow 80/tcp # HTTP
sudo ufw allow 443/tcp # HTTPS
sudo ufw enable
```
#### 9.2 SSL证书配置
使用Let's Encrypt免费证书
```bash
sudo apt install certbot python3-certbot-nginx
sudo certbot --nginx -d api.your-domain.com
```
#### 9.3 限流配置
在Nginx中配置限流
```nginx
limit_req_zone $binary_remote_addr zone=sms_limit:10m rate=1r/m;
location /api/auth/sms/send {
limit_req zone=sms_limit burst=2 nodelay;
proxy_pass http://localhost:8000;
}
```
### 10. 备份与恢复
#### 10.1 数据库备份
设置自动备份:
```bash
# 创建备份脚本
cat > /usr/local/bin/backup-db.sh << 'EOF'
#!/bin/bash
BACKUP_DIR="/var/backups/postgresql"
DATE=$(date +%Y%m%d_%H%M%S)
mkdir -p $BACKUP_DIR
pg_dump -U postgres -d life_echo | gzip > $BACKUP_DIR/life_echo_$DATE.sql.gz
# 保留最近7天的备份
find $BACKUP_DIR -name "*.sql.gz" -mtime +7 -delete
EOF
chmod +x /usr/local/bin/backup-db.sh
# 添加到crontab每天凌晨2点执行
echo "0 2 * * * /usr/local/bin/backup-db.sh" | crontab -
```
#### 10.2 数据恢复
```bash
# 恢复数据库
gunzip < backup_file.sql.gz | psql -U postgres -d life_echo
```
### 11. 故障排查
#### 11.1 短信发送失败
**检查步骤:**
1. 验证环境变量与 TOML 配置
```bash
echo $TENCENT_SECRET_ID
# SMS 业务 ID 见 config/production.toml [deploy] tencent_sms_sdk_app_id
```
2. 检查腾讯云账户余额
3. 查看后端日志
```bash
grep "SMS" /var/log/life-echo-api.log
```
4. 测试API连接
```python
from tencentcloud.common import credential
from tencentcloud.sms.v20210111 import sms_client
cred = credential.Credential(SECRET_ID, SECRET_KEY)
client = sms_client.SmsClient(cred, "ap-guangzhou")
```
#### 11.2 验证码验证失败
**检查步骤:**
1. 查询数据库中的验证码记录
```sql
SELECT * FROM sms_verification_codes
WHERE phone = '13800138000'
ORDER BY created_at DESC
LIMIT 5;
```
2. 检查验证码是否过期
3. 检查验证码是否已使用
4. 检查用途是否匹配
#### 11.3 数据库连接失败
**检查步骤:**
1. 验证数据库服务状态
```bash
sudo systemctl status postgresql
```
2. 检查数据库连接配置
```bash
psql -U postgres -d life_echo -c "SELECT 1"
```
3. 查看数据库日志
```bash
sudo tail -f /var/log/postgresql/postgresql-15-main.log
```
### 12. 性能优化
#### 12.1 数据库优化
```sql
-- 分析表统计信息
ANALYZE sms_verification_codes;
-- 查看慢查询
SELECT * FROM pg_stat_statements
WHERE query LIKE '%sms_verification_codes%'
ORDER BY total_time DESC;
```
#### 12.2 Redis优化
```bash
# 配置Redis持久化
redis-cli CONFIG SET save "900 1 300 10 60 10000"
# 设置最大内存
redis-cli CONFIG SET maxmemory 256mb
redis-cli CONFIG SET maxmemory-policy allkeys-lru
```
#### 12.3 应用优化
- 使用连接池
- 启用缓存
- 异步发送短信
- 批量清理过期验证码
### 13. 定期维护
#### 13.1 清理过期验证码
创建定时任务:
```sql
-- 创建清理函数
CREATE OR REPLACE FUNCTION cleanup_expired_sms_codes()
RETURNS void AS $$
BEGIN
DELETE FROM sms_verification_codes
WHERE expires_at < NOW() - INTERVAL '1 day';
END;
$$ LANGUAGE plpgsql;
-- 每天凌晨3点执行使用pg_cron扩展
SELECT cron.schedule('cleanup-sms', '0 3 * * *', 'SELECT cleanup_expired_sms_codes()');
```
#### 13.2 监控数据库大小
```sql
SELECT
pg_size_pretty(pg_total_relation_size('sms_verification_codes')) as table_size,
(SELECT count(*) FROM sms_verification_codes) as record_count;
```
## 部署检查清单
- [ ] 腾讯云短信服务已配置
- [ ] 环境变量已正确设置
- [ ] 数据库迁移已执行
- [ ] 依赖包已安装
- [ ] 服务已启动并运行
- [ ] 健康检查通过
- [ ] 发送验证码测试通过
- [ ] 日志正常输出
- [ ] 监控已配置
- [ ] 告警已配置
- [ ] 备份已配置
- [ ] SSL证书已配置
- [ ] 防火墙已配置
- [ ] 限流已配置
## 回滚计划
如果部署出现问题,执行以下步骤回滚:
1. 停止新版本服务
```bash
docker compose down
# 或
sudo systemctl stop life-echo-api
```
2. 恢复数据库
```bash
psql -U postgres -d life_echo < backup_file.sql
```
3. 切换到旧版本代码
```bash
git checkout previous-version
```
4. 重启服务
```bash
docker compose up -d
# 或
sudo systemctl start life-echo-api
```
## 联系支持
如有问题,请联系:
- 技术支持邮箱support@your-domain.com
- 开发团队dev@your-domain.com
## 更新日志
- 2024-01-XX: 初始版本
- 添加短信验证码功能
- 添加账户管理功能