什么时候该用 Queues,而不是 waitUntil 或 Workflows?
官方文档特别提到,ctx.waitUntil() 是非阻塞的,在里面调用 send() 或 sendBatch() 抛出的错误会被隐式忽略。也就是说,你以为交给队列的活,可能连入队都没成功,还没人知道。
所以答案是:请求之后的异步工作,只要不能丢、不该让用户等,就用 Queues;要严格顺序用 Durable Objects,要多步骤的长流程用 Workflows。 Queues 本身是一个持久、至少一次、不保序的缓冲区。
下面先看 waitUntil 和直接 fetch 为什么不够,再讲 Queues 的基本模型和适用边界。
为什么不直接 waitUntil 或 fetch?
朴素做法有两种:在请求里同步调用下游,或者用 ctx.waitUntil() 把工作挂到响应之后。
前者把下游的延迟和失败直接暴露给用户。后者没有持久化,也没有重试:Worker 实例被回收,或者下游报错,这件事就消失了。你需要的是一个持久缓冲区:生产者写入成功后消息不会丢,消费者按自己的节奏处理,失败可以重来。这就是 Queues。
Queues 的基本模型是什么?
生产者通过 Queue 绑定调用 send(body, options?) 或 sendBatch(messages, options?)。消费者是 Worker 默认导出上的 queue(batch, env, ctx) 处理器,收到的是一个 MessageBatch,里面是 Message 数组。
消费者有两种形态:Worker 消费者(push,平台调用你的 queue 处理器)和 HTTP pull 消费者,一个队列只能选其一。这里只讨论前者。保证上,消息至少投递一次、不保序,细节见 Cloudflare Queues 会重复投递消息吗?。绑定怎么配见 Wrangler 与绑定。
Queues 适合哪些场景?
- 请求之后的异步工作:发邮件、写审计日志、调用慢的第三方。
- 削峰:消费者并发可控,保护下游。
- 扇出:一个事件触发一批独立的小任务。
什么时候该换 Durable Objects?
需要严格顺序,或者“同一个 key 串行”时。Queues 的顺序只是 best effort,靠不住。Durable Objects 的单点串行才是这类需求该用的东西,典型用法见 Durable Objects 的典型模式。
什么时候该换 Workflows?
多步骤、步骤间有依赖、需要等人工审批或者睡几天时,用 Workflows。把这种逻辑硬塞进队列,最后会变成一堆靠消息体里的状态字段拼起来的状态机。
还有一点:Queues 没有返回值。需要请求加响应的,它不合适。
这篇主要是选型判断,我没有为它单独做实验。waitUntil里send()抛错被隐式忽略、消费者的两种形态和 best effort 的顺序,都是官方文档的说法,我没有在线上验证。行为会变化,以官方文档为准。