2026-01-27 11:36:24 +08:00
|
|
|
|
# 短信验证码功能部署指南
|
|
|
|
|
|
|
|
|
|
|
|
## 概述
|
|
|
|
|
|
|
|
|
|
|
|
本文档说明如何在生产环境中部署短信验证码功能,包括环境配置、数据库迁移、服务配置等。
|
|
|
|
|
|
|
|
|
|
|
|
## 前置条件
|
|
|
|
|
|
|
|
|
|
|
|
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. 环境变量配置
|
|
|
|
|
|
|
2026-05-22 13:44:50 +08:00
|
|
|
|
配置分两层,详见 [configuration.md](configuration.md):
|
|
|
|
|
|
|
|
|
|
|
|
- **`.env`(secrets + bootstrap)**:数据库/Redis 连接串、`SECRET_KEY`、腾讯云 API 密钥等
|
|
|
|
|
|
- **`config/{APP_ENV}.toml`(非密钥)**:SMS 应用 ID/签名/模板、JWT 过期时间、CORS 等
|
|
|
|
|
|
|
2026-01-27 11:36:24 +08:00
|
|
|
|
#### 2.1 编辑生产环境配置文件
|
|
|
|
|
|
|
2026-05-22 13:44:50 +08:00
|
|
|
|
编辑 `api/.env.production`(密钥与连接串):
|
2026-01-27 11:36:24 +08:00
|
|
|
|
|
|
|
|
|
|
```bash
|
2026-05-22 13:44:50 +08:00
|
|
|
|
APP_ENV=production
|
2026-01-27 11:36:24 +08:00
|
|
|
|
DATABASE_URL=postgresql://username:password@host:5432/life_echo
|
|
|
|
|
|
|
2026-05-22 13:44:50 +08:00
|
|
|
|
# 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
|
2026-01-27 11:36:24 +08:00
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
#### 2.2 配置说明
|
|
|
|
|
|
|
2026-05-22 13:44:50 +08:00
|
|
|
|
| 配置项 | 层级 | 说明 | 示例 |
|
|
|
|
|
|
|--------|------|------|------|
|
|
|
|
|
|
| `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` |
|
2026-01-27 11:36:24 +08:00
|
|
|
|
|
|
|
|
|
|
### 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"
|
2026-05-22 13:44:50 +08:00
|
|
|
|
env_file:
|
|
|
|
|
|
- .env
|
2026-01-27 11:36:24 +08:00
|
|
|
|
environment:
|
2026-05-22 13:44:50 +08:00
|
|
|
|
- APP_ENV=production
|
2026-01-27 11:36:24 +08:00
|
|
|
|
- DATABASE_URL=${DATABASE_URL}
|
|
|
|
|
|
- REDIS_URL=${REDIS_URL}
|
2026-05-22 13:44:50 +08:00
|
|
|
|
- REDIS_PASSWORD=${REDIS_PASSWORD}
|
|
|
|
|
|
- SECRET_KEY=${SECRET_KEY}
|
|
|
|
|
|
- TENCENT_SECRET_ID=${TENCENT_SECRET_ID}
|
|
|
|
|
|
- TENCENT_SECRET_KEY=${TENCENT_SECRET_KEY}
|
2026-01-27 11:36:24 +08:00
|
|
|
|
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
|
2026-03-25 17:40:04 +08:00
|
|
|
|
docker compose up -d
|
2026-01-27 11:36:24 +08:00
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
#### 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名称 | 说明 |
|
|
|
|
|
|
|-----------|------|
|
2026-05-22 13:44:50 +08:00
|
|
|
|
| `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]` 中维护,随代码发版。
|
2026-01-27 11:36:24 +08:00
|
|
|
|
|
|
|
|
|
|
参考文档:`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部署
|
2026-03-25 17:40:04 +08:00
|
|
|
|
docker compose logs -f api
|
2026-01-27 11:36:24 +08:00
|
|
|
|
|
|
|
|
|
|
# Systemd部署
|
|
|
|
|
|
sudo journalctl -u life-echo-api -f
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
### 8. 监控与告警
|
|
|
|
|
|
|
feat: OpenTelemetry LGTM observability, dev tooling, and memoir UX fixes (#31) (#32)
* add staging ios app build script
* feat(api): add OpenTelemetry LGTM stack for local observability
Wire OTel traces, metrics, and logs through a collector to Tempo,
Prometheus, and Loki, with custom LLM instrumentation, dev compose overlay,
Grafana provisioning, env templates, and development.sh auto-start.
* feat: expand observability, harden dev tooling, and fix expo staging UX
Add business and LLM Prometheus metrics with Grafana dashboards, alerting,
and a metrics verification script. Wire telemetry through adapters and core
LLM paths, and document the local LGTM workflow.
Fix development.sh for macOS bash 3.2, open Grafana and eval-web in Chrome,
and repair eval-web auto-open (unbound EVAL_WEB_BROWSER_SCHEDULED). Merge
internal-eval into the main dev script with improved compose handling.
Require EXPO_PUBLIC_* at build time, improve iOS HTTP ATS for staging IPs,
show memoir empty state instead of load errors when no chapters exist, and
add jest env setup plus chapter list response normalization.
* chore: enable Grafana Assistant Cursor plugin
* fix: memoir empty state and repair withdrawn 0020_chapters_book_id stamp
Show empty memoir UI when the chapter list succeeds with no items; treat auth/404 as non-fatal. Extend alembic revision repair so local dev DBs stamped with the removed 0020_chapters_book_id migration can roll back and upgrade to 0019.
---------
Co-authored-by: Kevin <kevin@brighteng.org>
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-05-20 15:14:13 +08:00
|
|
|
|
本地开发与预发可观测性栈(OpenTelemetry + Grafana LGTM)见 **[可观测性指南](observability.md)**。staging/production 全量接入为第二阶段(`docker-compose` profile)。
|
|
|
|
|
|
|
2026-01-27 11:36:24 +08:00
|
|
|
|
#### 8.1 配置日志监控
|
|
|
|
|
|
|
|
|
|
|
|
建议使用以下工具:
|
feat: OpenTelemetry LGTM observability, dev tooling, and memoir UX fixes (#31) (#32)
* add staging ios app build script
* feat(api): add OpenTelemetry LGTM stack for local observability
Wire OTel traces, metrics, and logs through a collector to Tempo,
Prometheus, and Loki, with custom LLM instrumentation, dev compose overlay,
Grafana provisioning, env templates, and development.sh auto-start.
* feat: expand observability, harden dev tooling, and fix expo staging UX
Add business and LLM Prometheus metrics with Grafana dashboards, alerting,
and a metrics verification script. Wire telemetry through adapters and core
LLM paths, and document the local LGTM workflow.
Fix development.sh for macOS bash 3.2, open Grafana and eval-web in Chrome,
and repair eval-web auto-open (unbound EVAL_WEB_BROWSER_SCHEDULED). Merge
internal-eval into the main dev script with improved compose handling.
Require EXPO_PUBLIC_* at build time, improve iOS HTTP ATS for staging IPs,
show memoir empty state instead of load errors when no chapters exist, and
add jest env setup plus chapter list response normalization.
* chore: enable Grafana Assistant Cursor plugin
* fix: memoir empty state and repair withdrawn 0020_chapters_book_id stamp
Show empty memoir UI when the chapter list succeeds with no items; treat auth/404 as non-fatal. Extend alembic revision repair so local dev DBs stamped with the removed 0020_chapters_book_id migration can roll back and upgrade to 0019.
---------
Co-authored-by: Kevin <kevin@brighteng.org>
Co-authored-by: Cursor <cursoragent@cursor.com>
2026-05-20 15:14:13 +08:00
|
|
|
|
- **Grafana + Loki + Tempo + Prometheus**(仓库内 `deploy/observability/`,推荐)
|
2026-01-27 11:36:24 +08:00
|
|
|
|
- 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 短信发送失败
|
|
|
|
|
|
|
|
|
|
|
|
**检查步骤:**
|
|
|
|
|
|
|
2026-05-22 13:44:50 +08:00
|
|
|
|
1. 验证环境变量与 TOML 配置
|
2026-01-27 11:36:24 +08:00
|
|
|
|
```bash
|
2026-05-22 13:44:50 +08:00
|
|
|
|
echo $TENCENT_SECRET_ID
|
|
|
|
|
|
# SMS 业务 ID 见 config/production.toml [deploy] tencent_sms_sdk_app_id
|
2026-01-27 11:36:24 +08:00
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
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
|
2026-03-25 17:40:04 +08:00
|
|
|
|
docker compose down
|
2026-01-27 11:36:24 +08:00
|
|
|
|
# 或
|
|
|
|
|
|
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
|
2026-03-25 17:40:04 +08:00
|
|
|
|
docker compose up -d
|
2026-01-27 11:36:24 +08:00
|
|
|
|
# 或
|
|
|
|
|
|
sudo systemctl start life-echo-api
|
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
|
|
## 联系支持
|
|
|
|
|
|
|
|
|
|
|
|
如有问题,请联系:
|
|
|
|
|
|
- 技术支持邮箱:support@your-domain.com
|
|
|
|
|
|
- 开发团队:dev@your-domain.com
|
|
|
|
|
|
|
|
|
|
|
|
## 更新日志
|
|
|
|
|
|
|
|
|
|
|
|
- 2024-01-XX: 初始版本
|
|
|
|
|
|
- 添加短信验证码功能
|
|
|
|
|
|
- 添加账户管理功能
|