You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
8.6 KiB
8.6 KiB
短信服务部署指南
文档版本:v1.0
最后更新:2026-01-27
目录
前置条件
1. 基础环境
- ✅ PostgreSQL 17(已安装 UUID v7 扩展)
- ✅ Redis(用于限流)
- ✅ Python 3.12+
- ✅ Celery(用于定时任务)
2. 阿里云短信服务(生产环境)
如果需要真实发送短信,需要:
- 注册阿里云账号
- 开通短信服务
- 配置短信签名(如:道研组)
- 配置短信模板(包含
${code}变量) - 获取 AccessKey ID 和 Secret
配置步骤
1. 更新环境变量
编辑 server/.env 文件:
# ==================== 短信服务配置 ====================
# 测试模式(开发环境推荐)
SMS_TEST_MODE=True
# 生产模式配置(生产环境必填)
SMS_TEST_MODE=False
SMS_ACCESS_KEY_ID=your_access_key_id
SMS_ACCESS_KEY_SECRET=your_access_key_secret
SMS_SIGN_NAME=道研组
SMS_TEMPLATE_CODE=SMS_123456789
# ==================== Redis 配置 ====================
REDIS_URL=redis://localhost:6379/0
2. 安装依赖
确保已安装必要的 Python 包:
cd server
pip install redis httpx
或使用 requirements.txt:
pip install -r requirements.txt
数据库迁移
1. 执行迁移脚本
cd server
python app/migrations/011_sms_service_tables.py
2. 验证表结构
连接数据库,检查表是否创建成功:
-- 查看表结构
\d sms_verification_codes
-- 查看索引
\di sms_verification_codes*
-- 查看表注释
SELECT
col_description('sms_verification_codes'::regclass, 0) as table_comment,
column_name,
col_description('sms_verification_codes'::regclass, ordinal_position) as column_comment
FROM information_schema.columns
WHERE table_name = 'sms_verification_codes';
功能测试
1. 运行测试脚本
cd server
python test_sms_service.py
预期输出:
============================================================
短信服务测试
============================================================
[测试 1] 发送验证码
------------------------------------------------------------
✅ 发送成功: {'message': '验证码已发送', 'expires_in': 600}
📱 验证码: 123456
⏰ 过期时间: 2026-01-27 10:15:00
[测试 2] 验证验证码(正确)
------------------------------------------------------------
✅ 验证成功: True
[测试 3] 验证验证码(错误)
------------------------------------------------------------
❌ 验证失败(预期): 验证码不存在或已过期
[测试 4] 防刷机制(1分钟内重复发送)
------------------------------------------------------------
❌ 发送失败(预期): 验证码已发送,请稍后再试
[测试 5] 清理过期验证码
------------------------------------------------------------
🗑️ 清理记录数: 0
============================================================
✅ 所有测试完成
============================================================
2. API 测试
2.1 发送验证码
curl -X POST http://localhost:6170/api/v1/auth/sms/send \
-H "Content-Type: application/json" \
-d '{
"phone": "13800138000",
"countryCode": "+86",
"purpose": "login"
}'
预期响应:
{
"code": 200,
"message": "Success",
"data": {
"message": "验证码已发送",
"expiresIn": 600
}
}
2.2 查看日志获取验证码(测试模式)
# 查看 API 日志
docker-compose logs -f api | grep "验证码"
输出示例:
[测试模式] 跳过短信发送: phone=13800138000, code=123456
2.3 验证验证码
curl -X POST http://localhost:6170/api/v1/auth/sms/verify \
-H "Content-Type: application/json" \
-d '{
"phone": "13800138000",
"countryCode": "+86",
"code": "123456",
"purpose": "login"
}'
预期响应:
{
"code": 200,
"message": "Success",
"data": {
"success": true
}
}
生产环境配置
1. 阿里云短信服务配置
1.1 创建短信签名
- 登录阿里云控制台
- 进入短信服务 → 国内消息 → 签名管理
- 添加签名:
道研组 - 等待审核通过
1.2 创建短信模板
- 进入短信服务 → 国内消息 → 模板管理
- 添加模板:
- 模板名称:
验证码通知 - 模板内容:
您的验证码是${code},有效期10分钟,请勿泄露。 - 模板类型:
验证码
- 模板名称:
- 等待审核通过
- 记录模板 CODE(如:
SMS_123456789)
1.3 获取 AccessKey
- 进入阿里云控制台 → AccessKey 管理
- 创建 AccessKey
- 记录 AccessKey ID 和 Secret(仅显示一次)
2. 更新生产环境变量
# 生产环境配置
SMS_TEST_MODE=False
SMS_ACCESS_KEY_ID=LTAI5tXXXXXXXXXXXXXX
SMS_ACCESS_KEY_SECRET=xxxxxxxxxxxxxxxxxxxxxxxx
SMS_SIGN_NAME=道研组
SMS_TEMPLATE_CODE=SMS_123456789
3. 配置 Celery 定时任务
编辑 server/app/tasks/celery_app.py,添加定时任务配置:
from celery.schedules import crontab
app.conf.beat_schedule = {
# 清理过期短信验证码(每小时执行)
'clean-expired-sms-codes': {
'task': 'sms.clean_expired_codes',
'schedule': crontab(minute=0), # 每小时的第 0 分钟
},
}
4. 重启服务
# 重启 API 服务
docker-compose restart api
# 重启 Celery Worker
docker-compose restart celery-worker
# 重启 Celery Beat
docker-compose restart celery-beat
故障排查
问题 1:短信发送失败
症状:API 返回 500 错误,日志显示"短信发送失败"
可能原因:
- AccessKey 配置错误
- 短信签名或模板未审核通过
- 阿里云账户余额不足
- 网络连接问题
解决方案:
# 1. 检查配置
cat .env | grep SMS
# 2. 检查阿里云控制台
# - 签名状态:已审核
# - 模板状态:已审核
# - 账户余额:充足
# 3. 测试网络连接
curl https://dysmsapi.aliyuncs.com/
# 4. 查看详细日志
docker-compose logs -f api | grep "短信"
问题 2:验证码验证失败
症状:输入正确的验证码仍然提示"验证码错误"
可能原因:
- 验证码已过期(10分钟)
- 验证码已被使用
- 手机号或国家区号不匹配
解决方案:
-- 查询验证码记录
SELECT
id,
phone,
country_code,
code,
purpose,
expires_at,
verified,
created_at
FROM sms_verification_codes
WHERE phone = '13800138000'
ORDER BY created_at DESC
LIMIT 5;
问题 3:触发限流
症状:API 返回 429 错误,提示"发送过于频繁"
可能原因:
- 1分钟内发送超过 1 次(同手机号)
- 1小时内发送超过 5 次(同手机号)
- 1分钟内发送超过 3 次(同 IP)
解决方案:
# 查看 Redis 限流记录
redis-cli
# 查看手机号限流
KEYS sms:phone:*
# 查看 IP 限流
KEYS sms:ip:*
# 清除特定限流(仅测试环境)
DEL sms:phone:+86:13800138000:1min
DEL sms:phone:+86:13800138000:1hour
问题 4:定时任务未执行
症状:过期验证码未被清理
可能原因:
- Celery Beat 未启动
- 定时任务配置错误
解决方案:
# 检查 Celery Beat 状态
docker-compose ps celery-beat
# 查看 Celery Beat 日志
docker-compose logs -f celery-beat
# 手动触发清理任务
docker-compose exec celery-worker celery -A app.tasks.celery_app call sms.clean_expired_codes
监控建议
1. 关键指标
在生产环境中,建议监控以下指标:
| 指标 | 说明 | 告警阈值 |
|---|---|---|
| 发送成功率 | 短信发送成功/总发送次数 | < 95% |
| 验证成功率 | 验证码验证成功/总验证次数 | < 80% |
| 限流触发次数 | 防刷机制触发次数 | > 100/小时 |
| 平均响应时间 | API 响应时间 | > 2秒 |
2. 日志监控
关键日志关键字:
# 发送成功
grep "验证码已发送" api.log
# 验证成功
grep "验证码验证成功" api.log
# 发送失败
grep "短信发送失败" api.log
# 触发限流
grep "发送过于频繁" api.log
相关文档
文档版本:v1.0
最后更新:2026-01-27