[ PROMPT_NODE_24094 ]
Durable Objects 设计模式
[ SKILL_DOCUMENTATION ]
# Durable Objects 模式
## 何时使用哪种模式
| 需求 | 模式 | ID 策略 |
|------|---------|-------------|
| 每个用户/IP 的速率限制 | 速率限制 (Rate Limiting) | `idFromName(identifier)` |
| 互斥访问 | 分布式锁 (Distributed Lock) | `idFromName(resource)` |
| >1K 请求/秒的吞吐量 | 分片 (Sharding) | `newUniqueId()` 或哈希 |
| 实时更新 | WebSocket 协作 | `idFromName(room)` |
| 用户会话 | 会话管理 | `idFromName(sessionId)` |
| 后台清理 | 基于闹钟 (Alarm-based) | 任意 |
## RPC 与 fetch()
**RPC** (兼容性 ≥2024-04-03): 类型安全,更简单,新项目的默认选择
**fetch()**: 旧版兼容,HTTP 语义,代理
typescript
const count = await stub.increment(); // RPC
const count = await (await stub.fetch(req)).json(); // fetch()
## 分片 (高吞吐量)
单个 DO 最大支持约 1K 请求/秒。通过分片实现更高吞吐量:
typescript
export default {
async fetch(req: Request, env: Env): Promise {
const userId = new URL(req.url).searchParams.get("user");
const hash = hashCode(userId) % 100; // 100 个分片
const id = env.COUNTER.idFromName(`shard:${hash}`);
return env.COUNTER.get(id).fetch(req);
}
};
function hashCode(str: string): number {
let hash = 0;
for (let i = 0; i < str.length; i++) hash = ((hash << 5) - hash) + str.charCodeAt(i);
return Math.abs(hash);
}
**决策:**
- **分片数量**: 通常为 10-1000(从 100 开始,根据测量结果调整)
- **分片键**: 用户 ID、IP、会话 - 必须均匀分布(使用哈希)
- **聚合**: 使用协调器 DO 或外部系统 (D1, R2)
## 速率限制
typescript
async checkLimit(key: string, limit: number, windowMs: number): Promise {
const req = this.ctx.storage.sql.exec("SELECT COUNT(*) as count FROM requests WHERE key = ? AND timestamp > ?", key, Date.now() - windowMs).one();
if (req.count >= limit) return false;
this.ctx.storage.sql.exec("INSERT INTO requests (key, timestamp) VALUES (?, ?)", key, Date.now());
return true;
}
## 分布式锁
typescript
private held = false;
async acquire(timeoutMs = 5000): Promise {
if (this.held) return false;
this.held = true;
await this.ctx.storage.setAlarm(Date.now() + timeoutMs);
return true;
}
async release() { this.held = false; await this.ctx.storage.deleteAlarm(); }
async alarm() { this.held = false; } // 超时自动释放
## 休眠感知模式
在休眠期间保持状态:
typescript
async fetch(req: Request): Promise<Respo