用途
该技能面向在 Cloudflare 边缘平台上使用 Durable Objects 构建有状态、可协调应用的开发场景。适用于创建新的 Durable Object 类以实现有状态协调、实现 RPC 方法、闹钟或 WebSocket 处理器、审查现有 DO 代码是否符合最佳实践、配置 wrangler.jsonc/toml 的 DO 绑定与迁移、使用 Cloudflare 的 Vitest 集成编写测试,以及设计分片策略和父子关系。
主要能力
技能提供检索来源指引,建议在实现功能时获取相关文档页面,因为对 Durable Objects API 和配置的知识可能已过时,任何 DO 任务都应优先检索而非依赖预训练。检索资源包括:文档(https://developers.cloudflare.com/durable-objects/index.md)、API 参考(https://developers.cloudflare.com/durable-objects/api/index.md)、最佳实践(https://developers.cloudflare.com/durable-objects/best-practices/index.md)、示例(https://developers.cloudflare.com/durable-objects/examples/index.md)、角色与权限(https://developers.cloudflare.com/workers/authorization/durable-objects/index.md)。
参考文档包括:./references/rules.md(核心规则、存储、并发、RPC、闹钟)、测试参考(当前 Vitest 文档、迁移选择与测试选择)、./references/workers.md(Workers 处理器、类型、wrangler 配置、可观测性)。可搜索关键词:blockConcurrencyWhile、idFromName、getByName、setAlarm、sql.exec。
使用方式
Wrangler 配置示例:
// wrangler.jsonc
{
"durable_objects": {
"bindings": [{ "name": "MY_DO", "class_name": "MyDurableObject" }]
},
"migrations": [{ "tag": "v1", "new_sqlite_classes": ["MyDurableObject"] }]
}
基础 Durable Object 模式:
import { DurableObject } from "cloudflare:workers";
export interface Env {
MY_DO: DurableObjectNamespace<MyDurableObject>;
}
export class MyDurableObject extends DurableObject<Env> {
constructor(ctx: DurableObjectState, env: Env) {
super(ctx, env);
ctx.blockConcurrencyWhile(async () => {
this.ctx.storage.sql.exec(`
CREATE TABLE IF NOT EXISTS items (
id INTEGER PRIMARY KEY AUTOINCREMENT,
data TEXT NOT NULL
)
`);
});
}
async addItem(data: string): Promise<number> {
const result = this.ctx.storage.sql.exec<{ id: number }>(
"INSERT INTO items (data) VALUES (?) RETURNING id",
data
);
return result.one().id;
}
}
export default {
async fetch(request: Request, env: Env): Promise<Response> {
const stub = env.MY_DO.getByName("my-instance");
const id = await stub.addItem("hello");
return Response.json({ id });
},
};
Stub 创建方式:
// 确定性 - 多数情况下首选
const stub = env.MY_DO.getByName("room-123");
// 从已有 ID 字符串创建
const id = env.MY_DO.idFromString(storedIdString);
const stub = env.MY_DO.get(id);
// 新唯一 ID - 需在外部存储映射
const id = env.MY_DO.newUniqueId();
const stub = env.MY_DO.get(id);
存储操作:
// SQL(同步,推荐)
this.ctx.storage.sql.exec("INSERT INTO t (c) VALUES (?)", value);
const rows = this.ctx.storage.sql.exec<Row>("SELECT * FROM t").toArray();
// KV(异步)
await this.ctx.storage.put("key", value);
const val = await this.ctx.storage.get<Type>("key");
闹钟:
// 调度(替换现有闹钟)
await this.ctx.storage.setAlarm(Date.now() + 60_000);
// 处理器
async alarm(): Promise<void> {
// 处理计划任务
// 可选重新调度:await this.ctx.storage.setAlarm(...)
}
// 取消
await this.ctx.storage.deleteAlarm();
适用场景
适合使用 Durable Objects 的场景包括:协调(聊天室、多人游戏、协作文档)、强一致性(库存、预订系统、回合制游戏)、按实体存储(多租户 SaaS、按用户数据)、持久连接(WebSocket、实时通知)、按实体的计划任务(订阅续订、游戏超时)。
不适合使用的场景包括:无状态请求处理(应使用普通 Workers)、需要最大全球分布、高扇出的独立请求。
关键规则与限制
核心规则:围绕协调原子建模——每个聊天室/游戏/用户一个 DO,而非一个全局 DO;使用 getByName() 做确定性路由——相同输入对应相同 DO 实例;使用 SQLite 存储——在迁移中配置 new_sqlite_classes;在构造函数中初始化——仅对 schema 设置使用 blockConcurrencyWhile();使用 RPC 方法——而非 fetch() 处理器(兼容日期 >= 2024-04-03);先持久化后缓存——始终先写入存储再更新内存状态;每个 DO 一个闹钟——setAlarm() 会替换任何现有闹钟。
授权方面:Durable Objects 没有单独的角色或权限,访问权限跟随实现它们的 Worker。在授予可观测性或 Data Studio 访问权限前,应检索当前的 Durable Objects 授权指引,并将 Workers 角色限定到预期的 Worker 或 Workers 产品。
反模式(切勿使用):单个全局 DO 处理所有请求(瓶颈);在每个请求上使用 blockConcurrencyWhile()(扼杀吞吐量);仅在内存中存储关键状态(驱逐或崩溃时丢失);在相关存储写入之间使用 await(破坏原子性);在 fetch() 或外部 I/O 期间持有 blockConcurrencyWhile()。
测试方面:在配置测试套件或编写 Durable Object 测试前,应阅读测试参考,它指向当前设置、API 和示例,并标识需要覆盖的行为。