Workers 将默认报告客户端断连:取消信号需要传到哪里

用户关闭页面,服务端是否还要继续生成一份已经没人接收的报告?这个问题不只取决于连接有没有断开,还取决于应用能否收到通知,以及下游操作是否愿意响应取消。

Cloudflare 在 2026 年 11 月 2 日的更新公告中预告:兼容日期为 2026-11-17 或更晚的 Workers,将默认通过传入请求的 request.signal 报告客户端断连。已有 Worker 不会只因日历走到那一天就统一切换行为。

这不是首次提供该能力——官方在 2025 年 5 月已开放显式启用。此次新闻是默认行为的调整。对开发者更有实际价值的问题,是如何让取消沿着调用链传播,同时不误伤必须独立完成的工作。

背景:断连通知、停止工作和业务回滚是三件事

设想一个只读查询接口:Worker 收到请求,访问上游数据服务,整理结果,再返回客户端。如果用户中途退出,剩余结果可能已经没有消费方。

但收到断连事件,不等于所有后续操作都会自动停止。一个异步函数返回了 Promise,也不意味着它天然具备取消能力。DOM 标准用 AbortSignal 协调取消意图,由接收信号的 API 决定如何响应;Promise 本身没有通用的强制中止机制。

还要再分开一层:停止等待某个网络请求,不等于远端已经发生的业务写入被撤销。本文建议对写操作始终把“调用方不再等待”与“业务是否成功”分别处理,不能根据断连状态直接推断事务结果。

生效条件:看兼容日期和标志,不只看发布时间

根据新公告和兼容标志文档,可以按下表判断:

Worker 配置 客户端断连信号的启用方式
兼容日期早于 2026-11-17 可用 enable_request_signal 显式启用
兼容日期达到或晚于 2026-11-17 默认启用,不再需要上述启用标志
需要显式退出该行为 使用 disable_request_signal

这里的兼容日期是应用选择运行时行为的配置,不是发布到服务器的时间。官方说明,现有 Worker 在修改兼容日期或标志之前保留当前行为。

因此,今天评估这项能力,不必为了测试它就提前采用一个未来日期。可以保留现有日期,在测试版本的既有标志列表中加入 enable_request_signal,再验证行为;不要用一段示例配置覆盖项目原有的全部兼容标志。

以后升级兼容日期时,也应审阅这段日期范围内的其他变更。兼容日期可能同时选择多项运行时行为,不是只控制这一个开关。

技术核心:把信号显式交给下游

本次调整不会连带开启 request_signal_passthrough。官方特别要求,若要取消支持信号的操作,应明确传入 request.signal。

例如,下面是用于说明调用关系的只读上游请求片段:

1
2
3
4
const result = await fetch(env.READ_API_URL, {
method: "GET",
signal: request.signal,
});

这里的 request 来自 Worker 的请求处理函数,env.READ_API_URL 表示由应用配置的受信任上游地址。片段没有完整的错误处理,也没有在本文中部署测试。

信号传递后,底层请求才有机会根据客户端断连执行取消。假如中间还包了一层服务函数,这层接口也应接收并继续传递信号。只在最外层注册一个日志监听器,并不能证明内层请求已经停止。

反过来,并不是所有 SDK、数据库驱动或任务接口都支持同样的取消参数。应查阅实际依赖的接口定义,不能给任意函数增加一个 signal 字段,就把它视作生效。

这也解释了为什么应分别观察两件事:应用记录到取消事件,以及上游连接或任务确实结束。前者是通知,后者才是取消策略的实际结果。

哪些工作随请求取消,哪些需要独立完成

以下分类是本文的工程建议,不是 Cloudflare 新公告替业务作出的决定。

只为当前用户生成的查询结果、预览或下载内容,通常值得评估随请求取消。若工作已经没有接收方,继续占用资源可能没有必要;但能节省多少,取决于取消发生的位置、上游是否响应等条件,不能据此给出统一的性能或费用收益。

审计记录、已经接受的业务任务,则可能不应依赖浏览器连接存活。需要先定义可靠接收的时点,以及客户端重试时如何查询状态或避免重复执行。不能简单规定“只要断连就全部取消”,也不应把每项工作都放到后台继续运行。

ctx.waitUntil() 可以延长 Worker 调用的寿命,但它解决的是任务运行时间的问题,不会抹掉任务自身携带的取消信号。如果传入的异步操作已绑定 request.signal,把它交给 waitUntil() 不会使这个操作自动变成不可取消。

同时,waitUntil() 不是无限后台执行。官方文档对 HTTP 触发的 Worker 说明:响应发出后或客户端断连后,它最多延长 30 秒,且同一请求内的多个调用共享这段时间。需要可靠重试或更长执行过程的工作,应另行评估 Queues 等独立处理机制,而不是把所有保证都压在这 30 秒上。

实践启示:把断连纳入测试,而不是只增加一行日志

建议先在可控环境准备一个慢速、只读、能够观察请求结束状态的上游,再测试取消链路。本文没有对生产 Worker、网络策略或兼容配置作任何改动。

验收至少包含四类情况:

  1. 正常完成:客户端不断开,响应内容和状态保持预期,清理逻辑不应提前结束有效操作。
  2. 提前取消:在等待上游时中止客户端请求,同时观察 Worker 收到事件的时间与上游实际结束的时间。
  3. 已取消后继续调用:如果业务有多阶段读取,检查后续阶段是否仍会启动无用请求。
  4. 独立后台任务:验证有意保留的任务仍按设计完成,并检查超时、重试和重复处理。

对于大计算循环,也不能假定一次事件会强行打断正在执行的同步代码。应设计可检查取消状态的阶段,并考虑事件能够被处理的机会,而不是只在工作结束后检查一次。

观测上,可以区分客户端取消、服务端超时、上游失败和清理失败。不要把每次取消都当成平台故障;也不要反过来,只要发现信号已取消,就忽略同时出现的真实错误。日志中保留必要的关联标识即可,不必记录完整查询参数、请求体或身份凭据。

结语

这次变更让更多采用新兼容日期的 Worker 默认获得客户端断连通知,但真正停止无用工作仍需要应用接好信号链路。

上线前最值得确认的,是三项彼此独立的约定:什么配置启用了通知,哪些操作接受取消,以及哪些业务结果不能由连接状态决定。把它们分别验证,比仅增加一个断连监听器更接近完整的取消处理。

参考来源

文章目录
  1. 1. 背景:断连通知、停止工作和业务回滚是三件事
  2. 2. 生效条件:看兼容日期和标志,不只看发布时间
  3. 3. 技术核心:把信号显式交给下游
  4. 4. 哪些工作随请求取消,哪些需要独立完成
  5. 5. 实践启示:把断连纳入测试,而不是只增加一行日志
  6. 6. 结语
  7. 7. 参考来源
|