队列也是 API 契约的一部分

把工作放进队列会改变延迟、责任归属和故障语义,但不会让这些问题消失。

收到请求不等于完成任务

HTTP 202 Accepted 表示服务器已接受任务,并承担尝试执行它的责任。这不代表任务已经成功,甚至不代表工作线程已经开始处理。

客户端需要一个持久的任务标识,以及清楚易懂的状态信息:

{
  "job_id": "job_7f31",
  "state": "queued",
  "status_url": "/jobs/job_7f31"
}

重试会产生重复任务

工作线程可能已经完成副作用,却在确认消息前崩溃。于是队列会再次投递同一条消息。这就是普通的至少一次投递,并非罕见的边缘情况。

使用幂等键、数据库唯一约束,或可以安全重复执行的状态转换。应在提交副作用的位置保证这一不变量。

背压是一项产品决策

没有上限的队列只会把过载转化为延迟故障。设置容量限制、公布队列等待时间,并决定系统无法继续处理时要拒绝什么。今天清楚地返回 429 或 503,往往比明天悄悄完成一个已经过期的任务更友好。

队列属于 API 的一部分,因为队列语义最终会成为客户端感受到的语义。请在接口文档中写清楚。