mcpField
C
cloudflare-durable-objects

cloudflare-durable-objects

github.com/secondsky云与 DevOps240227 次安装5 周前更新
代码仓库

关于 cloudflare-durable-objects

面向 Cloudflare Workers 开发者的 Durable Objects 技能,涵盖持久状态、单点协调及 WebSocket 休眠等开发主题。提供交互式设置、迁移、调试和优化流程,以及自动化 Agent。

主要功能

  1. 01项目脚手架与配置指导
  2. 02SQL 与键值存储参考
  3. 03WebSocket 休眠模式
  4. 04闹钟与 RPC 模式
  5. 05迁移、调试和优化工作流
  6. 06自动化错误修复与模式实现

适用场景

  1. 01创建聊天房间或会话管理
  2. 02实现限流与领导者选举
  3. 03配置 Durable Objects 迁移
  4. 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.md
alarms-api.md
best-practices.md
common-patterns.md
data-modeling.md
error-codes.md
gradual-deployments.md
migration-cheatsheet.md
migrations-guide.md
monitoring-debugging.md
performance-optimization.md
rpc-metadata.md
rpc-patterns.md
security-best-practices.md
state-api-reference.md
stubs-routing.md
top-errors.md
typescript-config.md
vitest-testing.md
websocket-hibernation.md
wrangler-commands.md
scripts/
check-versions.sh
migration-generator.sh
setup-vitest-do.sh
validate-do-config.sh
templates/
alarms-api-do.ts
basic-do.ts
gradual-deployment-config.jsonc
location-hints.ts
multi-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 创建方法:

  1. idFromName(name) - 命名 DO(最常见):确定性地将请求路由到全球同一实例
  2. newUniqueId() - 随机 ID:创建新的唯一实例,必须保存 ID 以供后续访问
  3. 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 类时,必须进行迁移。

四种迁移类型:

  1. 创建新的 DO:使用 new_sqlite_classes(推荐,1GB)或 new_classes(旧版 KV,128MB)
  2. 重命名 DO:使用带有 from/to 映射的 renamed_classes(保留数据,绑定会转发)
  3. 删除 DO:使用 deleted_classes(⚠️ 立即删除,无法撤销,所有存储都会丢失)
  4. 转移 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 的四种生产就绪模式:

  1. 速率限制 - 使用滑动窗口按用户限制速率,并使用 KV 存储跟踪请求
  2. 会话管理 - 使用 TTL 和 SQL 存储管理用户会话,并通过警报自动清理
  3. 领导者选举 - 使用 SQL 约束确保只有一个领导者,并采用心跳机制
  4. 多 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/

评论

支持 Markdown