# 短信验证码功能部署指南 ## 概述 本文档说明如何在生产环境中部署短信验证码功能,包括环境配置、数据库迁移、服务配置等。 ## 前置条件 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/0;Celery 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: 初始版本 - 添加短信验证码功能 - 添加账户管理功能