关于 durable-objects
面向使用 Cloudflare Durable Objects 构建边缘状态协调应用的编码技能,适合开发者实现和审查相关代码。它强调检索最新文档,并涵盖存储、并发、配置与测试规则。
主要功能
- 01状态协调实现指南
- 02RPC、闹钟与 WebSocket
- 03Wrangler 绑定和迁移
- 04SQLite 存储与并发规则
- 05Cloudflare Vitest 测试指南
适用场景
- 01实现聊天室或多人协作协调
- 02审查 Durable Object 代码
- 03配置绑定和迁移
- 04编写 Durable Object 测试
安装
复制下面的命令,在终端中运行。
$
npx skills add https:/ / github.com/ cloudflare/ skills --skill durable-objects安装后在 Claude Code 中输入/durable-objects确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
references/rules.mdtesting.mdworkers.md详细介绍
Durable Objects
使用 Durable Objects 在 Cloudflare 边缘构建有状态的协同应用。
检索资源
你对 Durable Objects API 和配置的了解可能已经过时。处理任何 Durable Objects 任务时,优先检索,而不是依赖预训练知识。
实现功能时,请获取相关文档页面。
适用场景
- 为有状态协同创建新的 Durable Object 类
- 实现 RPC 方法、闹钟或 WebSocket 处理程序
- 按最佳实践审查现有 DO 代码
- 为 DO 绑定和迁移配置 wrangler.jsonc/toml
- 使用 Cloudflare 的 Vitest 集成编写测试
- 设计分片策略及父子关系
参考文档
./references/rules.md- 核心规则、存储、并发、RPC、闹钟- 测试参考 - 当前 Vitest 文档、迁移选项和测试选择
./references/workers.md- Workers 处理程序、类型、wrangler 配置、可观测性
搜索:blockConcurrencyWhile、idFromName、getByName、setAlarm、sql.exec
核心原则
适合使用 Durable Objects 的场景
| 需求 | 示例 |
|---|---|
| 协同 | 聊天室、多人游戏、协作文档 |
| 强一致性 | 库存、预订系统、回合制游戏 |
| 按实体存储 | 多租户 SaaS、按用户存储的数据 |
| 持久连接 | WebSocket、实时通知 |
| 按实体执行计划任务 | 订阅续费、游戏超时 |
不要用于
- 无状态请求处理(使用普通 Workers)
- 对全局分布能力要求极高的场景
- 大量扇出式的独立请求
快速参考
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 });
},
};
关键规则
- 围绕协同单元建模 - 每个聊天室、游戏或用户对应一个 DO,而不是使用一个全局 DO
- 使用
getByName()实现确定性路由 - 相同输入 = 相同 DO 实例 - 使用 SQLite 存储 - 在迁移中配置
new_sqlite_classes - 在构造函数中初始化 - 仅使用
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()
创建 Stub
// Deterministic - preferred for most cases
const stub = env.MY_DO.getByName("room-123");
// From existing ID string
const id = env.MY_DO.idFromString(storedIdString);
const stub = env.MY_DO.get(id);
// New unique ID - store mapping externally
const id = env.MY_DO.newUniqueId();
const stub = env.MY_DO.get(id);
存储操作
// SQL (synchronous, recommended)
this.ctx.storage.sql.exec("INSERT INTO t (c) VALUES (?)", value);
const rows = this.ctx.storage.sql.exec<Row>("SELECT * FROM t").toArray();
// KV (async)
await this.ctx.storage.put("key", value);
const val = await this.ctx.storage.get<Type>("key");
闹钟
// Schedule (replaces existing)
await this.ctx.storage.setAlarm(Date.now() + 60_000);
// Handler
async alarm(): Promise<void> {
// Process scheduled work
// Optionally reschedule: await this.ctx.storage.setAlarm(...)
}
// Cancel
await this.ctx.storage.deleteAlarm();
测试
配置测试套件或编写 Durable Object 测试前,请先阅读测试参考。该文档会指向当前的设置方式、API 和示例,并说明需要覆盖的行为。
评论
支持 Markdown