活力39282
在线时间13640 小时
阅读权限200
管理员
自由的灵魂
- 积分
- 107434
- 主题
- 5630
- 回帖
- 26661
- 注册时间
- 2003-4-10
- 最后登录
- 2026-10-2
|
马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。
您需要 登录 才可以下载或查看,没有账号?立即注册
×
1、需求背景
管理员在删除用户时,需要自动向被删除用户的注册邮箱发送通知邮件。原方案直接调用 sendmail() 存在以下问题:
- 批量删除时触发 Nginx 502 超时
- 触发邮件服务商频率限制(QQ邮箱单次连接 ≤10 封)
- 发信失败无重试机制
- 命令行环境与 Web 环境不一致导致发信失败
2、解决方案
采用“数据库队列 + Crontab 定时触发”架构,将删除操作与邮件发送解耦。
核心流程:
- 后台删除用户 → 插入队列表 (status=0) → Crontab 每5分钟触发 → 取1封发送 → 成功(status=1)/失败(retry++)
复制代码
3、核心组件
| 组件 | 路径 | 作用 | | 队列表 | pre_common_mail_queue | 存储待发送邮件,字段:status、retry、next_try | | 入队代码 | source/function/function_delete.php | 删除用户时自动写入队列 | | 处理脚本 | api/mail_queue_cli.php | 命令行执行,每5分钟处理1封 | | Crontab | /5 * | 精确触发,不依赖论坛访问量 |
4、关键机制
| 机制 | 实现 | 效果 | | 限流 | 每5分钟1封 + sleep(1) | 完全避免邮件服务商频率限制 | | 重试 | 失败后延迟5-10分钟重试,最多3次 | 3次失败后标记 status=2 永久放弃 | | 双通道 | 独立脚本 + Discuz!计划任务 | 互为备份,任一通道故障不影响发信 | | 环境模拟 | 设置 $_SERVER 变量 | 命令行下完美运行 |
5、效果对比
| 指标 | 优化前 | 优化后 | | 批量删除超时 | ❌ 502 频繁 | ✅ 无超时 | | 邮件频率限制 | ❌ QQ邮箱 10封后封禁 | ✅ 每5分钟1封,完全合规 | | 失败重试 | ❌ 无,直接丢弃 | ✅ 3次重试后自动放弃 | | 依赖访问量 | ❌ Discuz!计划任务依赖用户访问 | ✅ Crontab 精确触发 | | 人工干预 | ❌ 需手动分批删除 | ✅ 全自动运行 |
6、技术沉淀
- 解耦是王道:将耗时操作(发信)从同步请求(删除用户)中分离,用队列异步处理
- 限流比并发更可靠:每5分钟1封的节奏比任何批量优化都更能绕过风控
- 命令行环境需模拟:$_SERVER['REMOTE_ADDR']、$_SERVER['REQUEST_URI'] 等变量必须手动设置
- 重试必须有上限:3次失败后永久放弃,避免无效地址拖垮系统
- 双通道备份:独立脚本 + Discuz!计划任务互备,提高可靠性
7、后续维护建议
| 事项 | 频率 | 操作 | | 检查日志 | 每周 | tail -20 /www/wwwlogs/mail_queue.log | | 清理永久失败记录 | 每月 | DELETE FROM pre_common_mail_queue WHERE status=2; | | 清理已发送记录 | 每季度 | DELETE FROM pre_common_mail_queue WHERE status=1 AND dateline < UNIX_TIMESTAMP(DATE_SUB(NOW(), INTERVAL 90 DAY)); | | 监控队列积压 | 持续 | SELECT COUNT(*) FROM pre_common_mail_queue WHERE status=0; (正常应为0或极小值) |
总结: 通过队列解耦与定时限流,成功构建了一套稳定、高效、零人工干预的邮件通知系统,彻底解决了批量删除用户时的邮件发送瓶颈。
相关帖子:
[2026-06-08] [功能] [点评邮件通知] - 点评邮件通知实现及邮件队列发送间隔优化为1分钟
|
|