关于 cloudflare-durable-objects
面向 Cloudflare Workers 开发者的 Durable Objects 技能,涵盖持久状态、单点协调及 WebSocket 休眠等开发主题。提供交互式设置、迁移、调试和优化流程,以及自动化 Agent。
主要功能
- 01项目脚手架与配置指导
- 02SQL 与键值存储参考
- 03WebSocket 休眠模式
- 04闹钟与 RPC 模式
- 05迁移、调试和优化工作流
- 06自动化错误修复与模式实现
适用场景
- 01创建聊天房间或会话管理
- 02实现限流与领导者选举
- 03配置 Durable Objects 迁移
- 04排查或优化现有实现
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ secondsky/ claude-skills --skill cloudflare-durable-objects安装后在 Claude Code 中输入/cloudflare-durable-objects确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
references/advanced-sql-patterns.mdalarms-api.mdbest-practices.mdcommon-patterns.mddata-modeling.mderror-codes.mdgradual-deployments.mdmigration-cheatsheet.mdmigrations-guide.mdmonitoring-debugging.mdperformance-optimization.mdrpc-metadata.mdrpc-patterns.mdsecurity-best-practices.mdstate-api-reference.mdstubs-routing.mdtop-errors.mdtypescript-config.mdvitest-testing.mdwebsocket-hibernation.mdwrangler-commands.mdscripts/check-versions.shmigration-generator.shsetup-vitest-do.shvalidate-do-config.shtemplates/alarms-api-do.tsbasic-do.tsgradual-deployment-config.jsonclocation-hints.tsmulti-do-coordination.ts详细介绍
Cloudflare Durable Objects
状态:生产就绪 ✅ 最后更新:2025-11-25 依赖项:cloudflare-worker-base(推荐) 最新版本:[email protected]+、@cloudflare/[email protected]+ 官方文档:https://developers.cloudflare.com/durable-objects/
目录
什么是 Durable Objects? • 快速开始 • 何时加载参考资料 • 类结构 • 状态 API • WebSocket 休眠 • 闹钟 • RPC 与 HTTP • Stub 与路由 • 迁移 • 常见模式 • 关键规则 • 已知问题
什么是 Durable Objects?
全局唯一、有状态的对象,支持单点协调、强一致性(ACID)、WebSocket 休眠(数千个连接)、SQLite 存储(1GB)和闹钟 API。
适用场景: 聊天室、多人游戏、速率限制、会话管理、领导者选举、有状态工作流
快速开始(10 分钟)
选项 1:搭建新的 DO 项目
npm create cloudflare@latest my-durable-app -- \
--template=cloudflare/durable-objects-template --ts --git --deploy false
cd my-durable-app && bun install && npm run dev
选项 2:添加到现有 Worker
1. 安装类型:
bun add -d @cloudflare/workers-types
2. 创建 DO 类(src/counter.ts):
import { DurableObject } from 'cloudflare:workers';
export class Counter extends DurableObject {
async increment(): Promise<number> {
let value: number = (await this.ctx.storage.get('value')) || 0;
await this.ctx.storage.put('value', ++value);
return value;
}
}
export default Counter; // CRITICAL
3. 配置(wrangler.jsonc):
{
"durable_objects": {
"bindings": [{ "name": "COUNTER", "class_name": "Counter" }]
},
"migrations": [
{ "tag": "v1", "new_sqlite_classes": ["Counter"] }
]
}
4. 从 Worker 调用(src/index.ts):
import { Counter } from './counter';
interface Env {
COUNTER: DurableObjectNamespace<Counter>;
}
export { Counter };
export default {
async fetch(request: Request, env: Env): Promise<Response> {
const stub = env.COUNTER.getByName('global-counter');
return new Response(`Count: ${await stub.increment()}`);
},
};
部署:
bunx wrangler deploy
可用命令
使用以下交互式命令,按引导完成工作流:
-
/do-setup- 使用交互式设置向导初始化新 DO 项目- 选择存储后端(SQL、KV 或两者)
- 选择用例模式(WebSocket、会话、速率限制等)
- 可选配置 Vitest 测试
- 生成完整的 DO 实现
-
/do-migrate- 交互式迁移助手- 创建新类(new_sqlite_classes、new_classes)
- 重命名现有类(renamed_classes)
- 删除类并进行安全确认(deleted_classes)
- 在脚本之间转移类(transferred_classes)
- 自动递增迁移标签(v1、v2、v3...)
-
/do-debug- 分步调试工作流- 检测错误类别(部署、运行时、性能等)
- 对配置和代码运行诊断检查
- 提供包含代码示例的具体修复方法
- 指导本地测试和生产环境验证
-
/do-patterns- 模式选择向导- 根据用例推荐 DO 模式
- 支持 WebSocket、速率限制、会话、分析、领导者选举
- 生成完整的模式实现
- 提供最佳实践和优化建议
-
/do-optimize- 性能优化助手- 分析现有 DO 代码,查找瓶颈
- 提供有针对性的优化建议
- 涵盖构造函数、查询、WebSocket、内存和闹钟
- 衡量性能改进
自主 Agent
这些 Agent 无需用户交互即可自主工作:
-
do-debugger- 自动检测并修复错误- 验证 wrangler.jsonc 配置
- 检测 16 种以上常见 DO 错误
- 自动应用修复并创建备份
- 报告前测试修复效果
-
do-setup-assistant- 自动搭建项目- 根据自然语言分析用户需求
- 生成完整的 DO 实现
- 创建测试、文档和验证
- 支持所有用例模式
-
do-pattern-implementer- 生产环境模式实现- 分析现有 DO 代码
- 按优先级推荐模式
- 实现 TTL 清理、RPC 元数据、SQL 索引等
- 生成针对特定模式的测试
何时加载参考资料
用户提及时立即加载:
state-api-reference.md→ “storage”“sql”“database”“query”“get/put”“KV”“1GB limit”websocket-hibernation.md→ “websocket”“real-time”“chat”“hibernation”“serializeAttachment”alarms-api.md→ “alarms”“scheduled tasks”“cron”“periodic”“batch processing”rpc-patterns.md→ “RPC”“fetch”“HTTP”“methods”“routing”rpc-metadata.md→ “RpcTarget”“metadata”“DO name”“idFromName access”stubs-routing.md→ “stubs”“idFromName”“newUniqueId”“location hints”“jurisdiction”migrations-guide.md→ “migrations”“rename”“delete”“transfer”“schema changes”migration-cheatsheet.md→ “migration quick reference”“migration types”“common migrations”common-patterns.md→ “patterns”“examples”“rate limiting”“sessions”“leader election”vitest-testing.md→ “test”“testing”“vitest”“unit test”“@cloudflare/vitest-pool-workers”gradual-deployments.md→ “gradual”“deployment”“traffic split”“rollout”“canary”typescript-config.md→ “TypeScript”“types”“tsconfig”“wrangler.jsonc”“bindings”advanced-sql-patterns.md→ “CTE”“window functions”“FTS5”“full-text search”“JSON functions”“complex SQL”security-best-practices.md→ “security”“authentication”“authorization”“SQL injection”“CORS”“encryption”“rate limiting”error-codes.md→ “error codes”“error catalog”“specific error”“E001”“troubleshooting”top-errors.md→ 错误、“not working”、调试、“binding not found”
主动加载时机:
- 构建新功能 → 从
common-patterns.md加载相关模式 - 调试问题 → 加载
error-codes.md查找具体错误,然后加载top-errors.md - 实现 WebSocket → 编码前加载
websocket-hibernation.md - 设置存储 → 加载
state-api-reference.md查看 SQL/KV API - 复杂 SQL 查询 → 加载
advanced-sql-patterns.md了解 CTE、窗口函数和 FTS5 - 安全审查 → 加载
security-best-practices.md了解身份验证、授权和 SQL 注入防护 - 创建首个 DO → 加载
stubs-routing.md了解 ID 方法 - 编写测试 → 加载
vitest-testing.md了解测试模式 - 规划部署 → 加载
gradual-deployments.md了解发布策略 - 需要迁移 → 加载
migration-cheatsheet.md快速查阅 - 在 DO 内使用 DO 名称 → 加载
rpc-metadata.md了解 RpcTarget 模式 - TypeScript 配置 → 加载
typescript-config.md了解设置
Durable Object 类结构
所有 DO 都继承 DurableObject,并且必须导出:
import { DurableObject } from 'cloudflare:workers';
export class MyDO extends DurableObject {
constructor(ctx: DurableObjectState, env: Env) {
super(ctx, env); // Required first line
// Keep minimal - heavy work blocks hibernation
ctx.blockConcurrencyWhile(async () => {
// Load from storage before handling requests
});
}
async myMethod(): Promise<string> { // RPC method (recommended)
return 'Hello!';
}
}
export default MyDO; // CRITICAL: Must export
this.ctx 提供: storage(SQL/KV)、id(唯一 ID)、waitUntil()、acceptWebSocket()
State API - 持久化存储
Durable Object 提供两种存储选项:
SQL API(SQLite 后端,推荐):
- 通过
ctx.storage.sql访问 - 每个实例最多 1GB 存储空间
- 支持事务、索引和游标的 SQL 查询
- 原子操作(deleteAll 要么全部完成,要么完全不执行)
- 在迁移中使用
new_sqlite_classes
键值 API(两个后端均可用):
- 通过
ctx.storage(get/put/delete/list)访问 - 简单的键值操作
- 支持异步事务
- KV 后端限制为 128MB,SQLite 后端限制为 1GB
快速示例:
export class Counter extends DurableObject {
sql: SqlStorage;
constructor(ctx: DurableObjectState, env: Env) {
super(ctx, env);
this.sql = ctx.storage.sql;
this.sql.exec('CREATE TABLE IF NOT EXISTS counts (key TEXT PRIMARY KEY, value INTEGER)');
}
async increment(): Promise<number> {
this.sql.exec('INSERT OR REPLACE INTO counts (key, value) VALUES (?, ?)', 'count', 1);
return this.sql.exec('SELECT value FROM counts WHERE key = ?', 'count').one<{value: number}>().value;
}
}
加载 references/state-api-reference.md,查看完整的 SQL 和 KV API 文档、游标操作、事务、参数化查询、存储限制和迁移模式。
WebSocket 休眠 API
每个 DO 实例可处理 数千个 WebSocket 连接,在空闲时(约 10 秒无活动)自动休眠,从而节省持续时间费用。DO 休眠时,连接仍在边缘节点保持打开状态。
关键规则:
- ✅ 使用
ctx.acceptWebSocket(server)(启用休眠) - ✅ 使用
ws.serializeAttachment(data)在休眠期间持久化元数据 - ✅ 在构造函数中使用
ctx.getWebSockets()恢复连接 - ❌ 不要使用
ws.accept()(标准 API,不支持休眠) - ❌ 不要使用
setTimeout/setInterval(会阻止休眠)
处理程序方法:webSocketMessage()、webSocketClose()、webSocketError()
快速模式:
export class ChatRoom extends DurableObject {
sessions: Map<WebSocket, any>;
constructor(ctx: DurableObjectState, env: Env) {
super(ctx, env);
this.sessions = new Map();
// Restore connections after hibernation
ctx.getWebSockets().forEach(ws => {
this.sessions.set(ws, ws.deserializeAttachment());
});
}
async fetch(request: Request): Promise<Response> {
const pair = new WebSocketPair();
const [client, server] = Object.values(pair);
this.ctx.acceptWebSocket(server); // ← Enables hibernation
server.serializeAttachment({ userId: 'alice' }); // ← Persists across hibernation
this.sessions.set(server, { userId: 'alice' });
return new Response(null, { status: 101, webSocket: client });
}
async webSocketMessage(ws: WebSocket, message: string): Promise<void> {
const session = this.sessions.get(ws);
// Broadcast to all
this.sessions.forEach((_, w) => w.send(message));
}
}
加载 references/websocket-hibernation.md,了解完整的处理程序模式、休眠生命周期、serializeAttachment API、连接管理、广播模式和休眠故障排查。
Alarms API - 定时任务
安排 DO 在未来某个时间唤醒,以执行批处理、清理、提醒或周期性任务。
核心 API:
await ctx.storage.setAlarm(timestamp)- 安排闹钟await ctx.storage.getAlarm()- 获取当前闹钟时间(未设置时为 null)await ctx.storage.deleteAlarm()- 取消闹钟async alarm(info)- 闹钟触发时调用的处理程序
主要功能:
- ✅ 保证至少执行一次,并自动重试(最多 6 次)
- ✅ 在休眠和驱逐后仍然有效
- ✅ 成功执行后自动删除
- ⚠️ 每个 DO 只能有一个闹钟(设置新闹钟会覆盖之前的闹钟)
快速模式:
export class Batcher extends DurableObject {
async addItem(item: string): Promise<void> {
await this.ctx.storage.put('items', [...existingItems, item]);
// Schedule batch processing if not already scheduled
if (await this.ctx.storage.getAlarm() === null) {
await this.ctx.storage.setAlarm(Date.now() + 10000); // 10 seconds
}
}
async alarm(info: { retryCount: number; isRetry: boolean }): Promise<void> {
const items = await this.ctx.storage.get('items');
await this.processBatch(items); // Send to API, write to DB, etc.
await this.ctx.storage.put('items', []); // Clear buffer
}
}
加载 references/alarms-api.md,了解周期性闹钟模式、重试处理、错误场景、清理任务和批处理策略。
RPC 与 HTTP Fetch
RPC(推荐):直接调用 DO 方法,例如 await stub.increment()。类型安全、简单且自动序列化。要求 compatibility_date >= 2024-04-03。
HTTP Fetch:传统的 HTTP 请求/响应,使用 async fetch(request) 处理程序。WebSocket 升级必须使用此方式。
快速比较:
// RPC Pattern (simpler)
export class Counter extends DurableObject {
async increment(): Promise<number> { // ← Direct method
let value = await this.ctx.storage.get<number>('count') || 0;
return ++value;
}
}
const count = await stub.increment(); // ← Direct call
// HTTP Fetch Pattern
export class Counter extends DurableObject {
async fetch(request: Request): Promise<Response> { // ← HTTP handler
const url = new URL(request.url);
if (url.pathname === '/increment') { /* ... */ }
}
}
const response = await stub.fetch('/increment', { method: 'POST' });
适用于 RPC:新项目、类型安全、简单的方法调用
适用于 HTTP Fetch:WebSocket 升级、复杂路由、旧版代码
加载 references/rpc-patterns.md,了解完整的 RPC 与 Fetch 对比、迁移指南、错误处理模式和方法可见性控制。
创建 Durable Object 存根并进行路由
要从 Worker 与 Durable Object 交互:获取 ID → 创建存根 → 调用方法。
三种 ID 创建方法:
idFromName(name)- 命名 DO(最常见):确定性地将请求路由到全球同一实例newUniqueId()- 随机 ID:创建新的唯一实例,必须保存 ID 以供后续访问idFromString(idString)- 根据已保存的 ID 字符串重新创建
获取存根:
// Method 1: From ID
const id = env.CHAT_ROOM.idFromName('room-123');
const stub = env.CHAT_ROOM.get(id);
// Method 2: Shortcut for named DOs (recommended)
const stub = env.CHAT_ROOM.getByName('room-123');
await stub.myMethod();
使用位置提示进行地理路由:
- 创建存根时设置
locationHint选项:{ locationHint: 'enam' } - 9 个区域:wnam、enam、sam、weur、eeur、apac、oc、afr、me
- 尽力而为(不保证),仅影响首次创建
使用管辖区限制实现数据驻留:
- 使用
newUniqueId({ jurisdiction: 'eu' })或{ jurisdiction: 'fedramp' } - 严格执行(DO 永远不会离开其管辖区)
- 不能与位置提示结合使用
- GDPR/FedRAMP 合规所必需
加载 references/stubs-routing.md,了解 ID 方法、存根管理、位置提示、管辖区限制、使用场景、最佳实践和错误处理模式的完整指南。
迁移 - 管理 DO 类
创建、重命名、删除或在 Workers 之间转移 DO 类时,必须进行迁移。
四种迁移类型:
- 创建新的 DO:使用
new_sqlite_classes(推荐,1GB)或new_classes(旧版 KV,128MB) - 重命名 DO:使用带有
from/to映射的renamed_classes(保留数据,绑定会转发) - 删除 DO:使用
deleted_classes(⚠️ 立即删除,无法撤销,所有存储都会丢失) - 转移 DO:使用带有
from_script的transferred_classes(将实例移至新的 Worker)
快速示例 - 使用 SQLite 创建新的 DO:
{
"durable_objects": {
"bindings": [{ "name": "COUNTER", "class_name": "Counter" }]
},
"migrations": [
{
"tag": "v1", // Unique identifier (append-only)
"new_sqlite_classes": ["Counter"]
}
]
}
重要规则:
- ❌ 迁移是原子操作(所有实例会一次性迁移,不支持渐进式发布)
- ❌ 无法为现有的 KV 支持的 DO 启用 SQLite(必须创建新类)
- ❌ 迁移标签必须唯一(不可重复使用,只能追加)
- ✅ 代码变更不需要迁移(只有架构变更需要)
- ✅ DO 类名在每个账户中唯一(跨所有 Workers)
加载 references/migrations-guide.md,了解完整的迁移模式、重命名/删除/转移流程、回滚策略和迁移注意事项。
常见模式
Cloudflare Durable Objects 的四种生产就绪模式:
- 速率限制 - 使用滑动窗口按用户限制速率,并使用 KV 存储跟踪请求
- 会话管理 - 使用 TTL 和 SQL 存储管理用户会话,并通过警报自动清理
- 领导者选举 - 使用 SQL 约束确保只有一个领导者,并采用心跳机制
- 多 DO 协调 - 游戏协调器 + 游戏房间模式,以及父子 DO 关系
快速示例 - 速率限制器:
export class RateLimiter extends DurableObject {
async checkLimit(userId: string, limit: number, window: number): Promise<boolean> {
const requests = await this.ctx.storage.get<number[]>(`rate:${userId}`) || [];
const validRequests = requests.filter(t => Date.now() - t < window);
if (validRequests.length >= limit) return false;
validRequests.push(Date.now());
await this.ctx.storage.put(`rate:${userId}`, validRequests);
return true;
}
}
加载 references/common-patterns.md,查看全部 4 种模式的完整实现,包括完整代码示例、SQL 架构、警报用法、错误处理和最佳实践。
关键规则
✅ 始终:
- 导出 DO 类:
export default MyDO - 在构造函数中首先调用
super(ctx, env) - 在迁移中使用
new_sqlite_classes(1GB,相比 KV 的 128MB) - 休眠时使用
ctx.acceptWebSocket()(而不是ws.accept()) - 将状态持久化到存储中(不要只保存在内存中)
- 使用警报代替 setTimeout/setInterval
- 使用参数化 SQL:
sql.exec('... WHERE id = ?', id) - 尽量减少构造函数中的工作,使用
blockConcurrencyWhile()
❌ 绝不:
- 不通过迁移创建 DO(会报错)
- 忘记导出类(找不到绑定)
- 使用 setTimeout/setInterval(会阻止休眠)
- WebSocket 仅依赖内存状态(使用 serializeAttachment)
- 渐进式部署迁移(迁移是原子操作)
- 为现有的 KV 支持的 DO 启用 SQLite(必须创建新类)
- 假设位置提示一定生效(仅尽力而为)
避免已知问题
此技能可避免 15 个以上的已记录问题。最关键的 3 个问题:
问题 #1:未导出类
错误:"binding not found" | 原因:未导出 DO 类
修复:export default MyDO;
问题 #2:缺少迁移
错误:"migrations required" | 原因:创建 DO 时未添加迁移条目
修复:在 migrations 中添加 { "tag": "v1", "new_sqlite_classes": ["MyDO"] }
问题 #3:setTimeout 会破坏休眠
错误:DO 从不休眠,费用高昂 | 原因:setTimeout 会阻止休眠
修复:改用 await ctx.storage.setAlarm(Date.now() + 1000)
还涵盖另外 12 个问题:迁移类型错误、构造函数开销、内存状态丢失、出站 WebSocket 无法休眠、全局唯一性理解有误、deleteAll 不完整、绑定不匹配、状态大小超限、迁移非原子、位置提示被忽略、警报重试失败、fetch 阻止休眠。
加载 references/top-errors.md,查看完整的错误目录,涵盖所有 15 个以上的问题、详细的预防策略、调试步骤和解决模式。
配置与 TypeScript
配置 wrangler.jsonc,设置 DO 绑定和迁移,并通过正确的导出设置 TypeScript 类型。
请加载 references/typescript-config.md,了解:wrangler.jsonc 结构、TypeScript 类型、Env 接口、tsconfig.json、常见类型问题
官方文档:https://developers.cloudflare.com/durable-objects/
- State API(SQL):https://developers.cloudflare.com/durable-objects/api/sqlite-storage-api/
- WebSocket 休眠:https://developers.cloudflare.com/durable-objects/best-practices/websockets/
- Alarms API:https://developers.cloudflare.com/durable-objects/api/alarms/
- 迁移:https://developers.cloudflare.com/durable-objects/reference/durable-objects-migrations/
- 最佳实践:https://developers.cloudflare.com/durable-objects/best-practices/
**有疑问?**请加载
references/top-errors.md查看常见问题,或查看templates/中的可运行示例