本节描述 Durable Object 的生命周期。
要使用 Durable Object,您需要创建一个 Durable Object Stub。 仅创建 Durable Object Stub 并不会向 Durable Object 发送请求,因此 Durable Object 尚未实例化。 只有在 Durable Object Stub 上调用方法后,请求才会发送到 Durable Object,其生命周期才开始。
const stub = env.MY_DURABLE_OBJECT.getByName("foo");
// Now the request is sent to the remote Durable Object.
const rpcResponse = await stub.sayHello();Durable Object 在任意时刻可处于以下状态之一:
| 状态 | 描述 |
|---|---|
| Active, in-memory | Durable Object 在内存中运行并处理传入请求。 |
| Idle, in-memory non-hibernateable | Durable Object 等待下一个传入请求/事件,但不满足休眠条件。 |
| Idle, in-memory hibernateable | Durable Object 等待下一个传入请求/事件且满足休眠条件。何时让 Durable Object 休眠由运行时决定。目前在此状态下不活跃 10 秒后会休眠。 |
| Hibernated | Durable Object 从内存中移除。已休眠的 WebSocket 连接保持连接。 |
| Inactive | Durable Object 完全从宿主进程中移除,可能需要冷启动。这是所有 Durable Objects 的初始状态。 |
以下是 Durable Object 在这些状态之间的转换方式(每个状态以圆角矩形表示)。
假设 Durable Object 未在运行,第一个传入请求或事件(如 alarm)将执行 Durable Object 类的 constructor(),然后运行被调用的相应函数。
此时 Durable Object 处于 active in-memory 状态。
所有传入请求或事件处理完毕后,Durable Object 会在内存中空闲数秒,处于可休眠或不可休眠状态。
仅当所有以下条件均满足时,才能发生休眠:
- 未设置
setTimeout/setInterval计划回调,因为休眠后无法重建回调。 - 没有进行中的 awaited
fetch(),因为它被视为等待 I/O。 - 未使用 WebSocket 标准 API。
- 没有仍在处理的请求/事件,因为休眠意味着丢失本应最终向该请求返回响应的 async 函数。
- 不存在活跃的出站 TCP 套接字(
connect())或出站 WebSocket 连接。
在无传入请求或事件 10 秒且满足上述所有条件后,Durable Object 将转换到 hibernated 状态。
如果上述任一条件不满足,Durable Object 仍保留在内存中,处于 idle, in-memory, non-hibernateable 状态。
如果在 hibernated 状态下有传入请求或事件,constructor() 将再次运行,Durable Object 将转换到 active, in-memory 状态并执行被调用的函数。
在 idle, in-memory, non-hibernateable 状态下,不活跃 70-140 秒(无传入请求或事件)后,Durable Object 将完全从内存中驱逐,可能从 Cloudflare 宿主中移除,并转换到 inactive 状态。
hibernated 状态的对象保持 WebSocket 客户端连接,运行时决定是否以及何时将对象转换到 inactive 状态(例如决定将对象迁移到不同宿主),从而重启生命周期。
下一个传入请求或事件再次启动循环。
Durable Objects 偶尔会关闭并重启对象,这将运行您的 Durable Object 类构造函数。这可能由多种原因引起,包括:
- 带有代码更新的新 Worker 部署
- 根据上述状态转换,对象长时间无请求
- Cloudflare 对 Workers 运行时系统的更新
- Workers 运行时关于对象托管位置的决策
Durable Object 关闭时,对象实例会自动重启,新请求会路由到新实例。进行中的请求处理方式如下:
- HTTP 和 RPC 请求:如果进行中的请求不访问 Durable Object 的存储,则允许完成。如果请求尝试访问 Durable Object 的存储,将立即停止并返回错误,以维护 Durable Objects 的全局唯一性属性。Workers 运行时系统更新时,进行中的请求最多有 30 秒完成时间。
- WebSocket 连接:关闭期间 WebSocket 请求会自动终止。这样新实例可以尽快接管连接。
- 其他调用(email、cron):其他调用与 HTTP 请求类似处理。
务必确保使用 Durable Objects 的任何服务都设计为能够处理 Durable Object 可能被关闭的情况。
Durable Object 代码更新时,Worker 和 Durable Objects 会以最终一致的方式在全球发布。这将导致 Durable Object 关闭,行为如上所述。更新还可能导致请求到达某处的新版 Worker,而调用仍在其他地方运行旧版的 Durable Object。有关处理此场景的更多信息,请参阅代码更新。
Durable Object 可能因部署、不活动或运行时决策而随时关闭。不要依赖关闭钩子(系统不提供),而应设计应用以增量方式写入状态。
不提供关闭钩子或关闭前运行的生命周期回调,因为 Cloudflare 无法保证这些钩子在所有情况下都会执行,且外部软件可能过度依赖这些(不可靠的)钩子。
与其依赖关闭钩子,你可以定期写入存储,以便从关闭中优雅恢复。
例如,如果你正在处理数据流并需要保存进度,应在处理过程中写入位置,而不是等到最后才持久化:
// Good: Write progress as you go
async processData(data) {
data.forEach(async (item, index) => {
await this.processItem(item);
// Save progress frequently
await this.ctx.storage.put("lastProcessedIndex", index);
});
}虽然这可能感觉违反直觉,但 Durable Object 存储写入快速且同步,因此你可以以极小的性能顾虑持久化状态。
这种方法确保 Durable Object 可以从任何点安全恢复,即使意外关闭也是如此。