这是一份后来补写的设计清单。
场景包括数据导出、日志打包、系统升级、病毒库更新。它们的共同点是:用户通过 HTTP 发起,但任务不应该依赖这条 HTTP 连接活着。
接口应该尽快返回什么
不是文件,也不是一句“正在处理”,而是一个任务 ID:
{
"taskId": "export-20250319-001",
"status": "pending"
}
随后提供任务查询和文件下载接口。前端可以轮询,也可以通过 SSE/WebSocket 接收变化。
后台任务至少要回答这些问题
- 谁创建的任务?
- 当前是排队、运行、成功、失败还是取消?
- 什么时候开始、什么时候结束?
- 失败原因是什么?
- 相同参数能否重复创建?
- 服务重启后,
running状态如何修正? - 临时文件多久删除?
- 文件是否只能由创建者下载?
- 磁盘空间不足时在哪一步失败?
不要把 goroutine 当成任务系统
在 Handler 里直接 go export() 可以快速异步,但进程重启后没有状态,任务量也没有上限。至少需要持久化任务记录、有界 worker、超时和并发控制。更重要的任务还需要恢复或补偿机制。
系统升级更特殊
升级不仅耗时,还会主动重启自己。上传包需要检查版本、目录结构、重复版本和文件完整性;执行前要备份;重启前要把状态写到进程之外;失败时要留下能够回滚和诊断的信息。
曾经把上传超时放宽到 6 小时,是为了先解决现场大文件无法上传的问题。但超时时间再长,也不能替代任务建模。连接不断只是运气好,状态可恢复才是设计。