Cloudflare持久对象技能 cloudflare-durable-objects

这个技能是关于Cloudflare持久对象的,用于状态协调和实时应用,如聊天、多人在线游戏、WebSocket休眠、警报API等。关键词包括持久对象、WebSocket休眠、状态API、警报API、RPC模式、迁移管理、速率限制、会话管理、领导者选举。

Serverless 0 次安装 0 次浏览 更新于 3/8/2026

名称: cloudflare-durable-objects 描述: Cloudflare持久对象用于状态协调和实时应用。用于聊天、多人在线游戏、WebSocket休眠,或遇到类导出、迁移、警报错误。

关键词: 持久对象, cloudflare do, DurableObject类, do绑定, websocket休眠, do状态api, ctx.storage.sql, ctx.acceptWebSocket, webSocketMessage, alarm()处理程序, storage.setAlarm, idFromName, newUniqueId, getByName, DurableObjectStub, serializeAttachment, 实时cloudflare, 多人在线cloudflare, 聊天室workers, 协调cloudflare, 状态ful workers, new_sqlite_classes, do迁移, 位置提示, RPC方法, blockConcurrencyWhile, “do类导出”, “new_sqlite_classes”, “需要迁移”, “websocket休眠”, “警报api错误”, “全局唯一性”, “绑定未找到” 许可证: MIT

Cloudflare持久对象

状态: 生产就绪 ✅ 最后更新: 2025-11-25 依赖项: cloudflare-worker-base (推荐) 最新版本: wrangler@4.50.0+, @cloudflare/workers-types@4.20251125.0+ 官方文档: https://developers.cloudflare.com/durable-objects/

目录

什么是持久对象?快速开始何时加载参考类结构状态APIWebSocket休眠警报RPC vs HTTP存根与路由迁移常见模式关键规则已知问题预防

什么是持久对象?

全局唯一、状态ful对象,具有单点协调、强一致性(ACID)、WebSocket休眠(数千个连接)、SQLite存储(1GB)和警报API。

用于: 聊天室、多人在线游戏、速率限制、会话管理、领导者选举、状态ful工作流

快速开始(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;  // 关键

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(`计数: ${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、内存、警报
    • 测量性能改进

自治代理

这些代理无需用户交互即可自主工作:

  • 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 → errors、“not working”、debugging、“binding not found”

在以下情况下主动加载:

  • 构建新功能 → 从common-patterns.md加载相关模式
  • 调试问题 → 为特定错误加载error-codes.md,然后top-errors.md
  • 实现WebSocket → 编码前加载websocket-hibernation.md
  • 设置存储 → 为SQL/KV API加载state-api-reference.md
  • 复杂SQL查询 → 为CTE、窗口函数、FTS5加载advanced-sql-patterns.md
  • 安全审查 → 为认证、授权、SQL注入预防加载security-best-practices.md
  • 创建第一个DO → 为ID方法加载stubs-routing.md
  • 编写测试 → 为测试模式加载vitest-testing.md
  • 规划部署 → 为推出策略加载gradual-deployments.md
  • 需要迁移 → 为快速参考加载migration-cheatsheet.md
  • 在DO内使用DO名称 → 为RpcTarget模式加载rpc-metadata.md
  • TypeScript配置 → 为设置加载typescript-config.md

持久对象类结构

所有DO都继承DurableObject并且必须导出

import { DurableObject } from 'cloudflare:workers';

export class MyDO extends DurableObject {
  constructor(ctx: DurableObjectState, env: Env) {
    super(ctx, env);  // 必需第一行
    // 保持最小化 - 繁重工作会阻止休眠
    ctx.blockConcurrencyWhile(async () => {
      // 处理请求前从存储加载
    });
  }

  async myMethod(): Promise<string> {  // RPC方法(推荐)
    return 'Hello!';
  }
}

export default MyDO;  // 关键:必须导出

this.ctx提供: storage(SQL/KV)、id(唯一ID)、waitUntil()acceptWebSocket()


状态API - 持久存储

持久对象提供两种存储选项:

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();
    // 休眠后恢复连接
    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);  // ← 启用休眠
    server.serializeAttachment({ userId: 'alice' });  // ← 在休眠间持久化
    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);
    // 广播给所有人
    this.sessions.forEach((_, w) => w.send(message));
  }
}

加载references/websocket-hibernation.md获取完整处理程序模式、休眠生命周期、serializeAttachment API、连接管理、广播模式和休眠故障排除。


警报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]);

    // 如果尚未安排,则安排批处理
    if (await this.ctx.storage.getAlarm() === null) {
      await this.ctx.storage.setAlarm(Date.now() + 10000);  // 10秒
    }
  }

  async alarm(info: { retryCount: number; isRetry: boolean }): Promise<void> {
    const items = await this.ctx.storage.get('items');
    await this.processBatch(items);  // 发送到API、写入数据库等
    await this.ctx.storage.put('items', []);  // 清空缓冲区
  }
}

加载references/alarms-api.md获取周期性警报模式、重试处理、错误场景、清理作业和批处理策略。


RPC vs HTTP Fetch

RPC(推荐): 直接调用DO方法,如await stub.increment()。类型安全、简单、自动序列化。需要compatibility_date >= 2024-04-03

HTTP Fetch: 传统的HTTP请求/响应处理程序,带async fetch(request)。用于WebSocket升级。

快速比较:

// RPC模式(更简单)
export class Counter extends DurableObject {
  async increment(): Promise<number> {  // ← 直接方法
    let value = await this.ctx.storage.get<number>('count') || 0;
    return ++value;
  }
}
const count = await stub.increment();  // ← 直接调用

// HTTP Fetch模式
export class Counter extends DurableObject {
  async fetch(request: Request): Promise<Response> {  // ← HTTP处理程序
    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 vs Fetch比较、迁移指南、错误处理模式和方可见性控制。


创建持久对象存根和路由

从Worker与持久对象交互:获取ID创建存根调用方法

三种ID创建方法:

  1. idFromName(name) - 命名DO(最常见):确定性路由到全局相同实例
  2. newUniqueId() - 随机ID:新唯一实例,必须存储ID以便未来访问
  3. idFromString(idString) - 从保存的ID字符串重新创建

获取存根:

// 方法1: 从ID
const id = env.CHAT_ROOM.idFromName('room-123');
const stub = env.CHAT_ROOM.get(id);

// 方法2: 命名DO的快捷方式(推荐)
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: 使用renamed_classesfrom/to映射(数据保留,绑定转发)
  3. 删除DO: 使用deleted_classes(⚠️ 立即删除,无法撤销,所有存储丢失)
  4. 转移DO: 使用transferred_classesfrom_script(将实例移动到新Worker)

快速示例 - 用SQLite创建新DO:

{
  "durable_objects": {
    "bindings": [{ "name": "COUNTER", "class_name": "Counter" }]
  },
  "migrations": [
    {
      "tag": "v1",                    // 唯一标识符(仅追加)
      "new_sqlite_classes": ["Counter"]
    }
  ]
}

关键规则:

  • ❌ 迁移是原子的(所有实例同时迁移,无渐进推出)
  • ❌ 不能在现有KV支持的DO上启用SQLite(必须创建新类)
  • ❌ 迁移标签必须唯一(不能重用,仅追加)
  • ✅ 代码更改不需要迁移(仅架构更改需要)
  • ✅ DO类名称在账户中唯一(跨所有Workers)

加载references/migrations-guide.md获取完整迁移模式、重命名/删除/转移过程、回滚策略和迁移陷阱。


常见模式

四种生产就绪模式用于Cloudflare持久对象:

  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 vs 128MB KV)
  • 使用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 修复: 添加{ "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/