Appearance
Cloudflare 持久对象
🌐 Cloudflare Durable Objects
Cloudflare Durable Objects 无法直接处理 HTTP 请求。相反,它们通过一个两步过程来工作:
🌐 Cloudflare Durable Objects cannot handle HTTP requests directly. Instead, they work through a two-step process:
- Worker 接收来自客户端的 HTTP 获取请求
- Worker 向 Durable Object 发起 RPC(远程过程调用)调用
- 持久对象处理 RPC 并将结果返回给 Worker。
- Worker 将 HTTP 响应发送回客户端
你可以在 Cloudflare Worker 中使用 Hono 作为路由,调用 RPC(远程过程调用)与 Durable Objects 进行交互。这是截至 Cloudflare Workers 兼容日期 2024-04-03 的推荐方法。
🌐 You can use Hono as the router in your Cloudflare Worker, calling RPCs (Remote Procedure Calls) to interact with Durable Objects. This is the recommended approach as of Cloudflare Workers compatibility date 2024-04-03.
示例:计数器持久对象
🌐 Example: Counter Durable Object
ts
import { DurableObject } from 'cloudflare:workers'
import { Hono } from 'hono'
export class Counter extends DurableObject {
// In-memory state
value = 0
constructor(ctx: DurableObjectState, env: unknown) {
super(ctx, env)
// `blockConcurrencyWhile()` ensures no requests are delivered until initialization completes.
ctx.blockConcurrencyWhile(async () => {
// After initialization, future reads do not need to access storage.
this.value = (await ctx.storage.get('value')) || 0
})
}
async getCounterValue() {
return this.value
}
async increment(amount = 1): Promise<number> {
this.value += amount
await this.ctx.storage.put('value', this.value)
return this.value
}
async decrement(amount = 1): Promise<number> {
this.value -= amount
await this.ctx.storage.put('value', this.value)
return this.value
}
}
// Create a new Hono app to handle incoming HTTP requests
type Bindings = {
COUNTER: DurableObjectNamespace<Counter>
}
const app = new Hono<{ Bindings: Bindings }>()
// Add routes to interact with the Durable Object
app.get('/counter', async (c) => {
const env = c.env
const id = env.COUNTER.idFromName('counter')
const stub = env.COUNTER.get(id)
const counterValue = await stub.getCounterValue()
return c.text(counterValue.toString())
})
app.post('/counter/increment', async (c) => {
const env = c.env
const id = env.COUNTER.idFromName('counter')
const stub = env.COUNTER.get(id)
const value = await stub.increment()
return c.text(value.toString())
})
app.post('/counter/decrement', async (c) => {
const env = c.env
const id = env.COUNTER.idFromName('counter')
const stub = env.COUNTER.get(id)
const value = await stub.decrement()
return c.text(value.toString())
})
// Export the Hono app as the Worker's fetch handler
export default appwrangler.jsonc:
jsonc
{
"$schema": "node_modules/wrangler/config-schema.json",
"name": "durable",
"main": "src/index.ts",
"compatibility_date": "2025-04-14",
"migrations": [
{
"new_sqlite_classes": ["Counter"],
"tag": "v1",
},
],
"durable_objects": {
"bindings": [
{
"class_name": "Counter",
"name": "COUNTER",
},
],
},
"observability": {
"enabled": true,
},
}现在你拥有一个与Durable Object接口的完整功能Hono应用!Hono路由提供了一个干净的API接口来与Durable Object的方法进行交互和公开。
🌐 Now you have a fully functional Hono application that interfaces with your Durable Object! The Hono router provides a clean API interface to interact with and expose your Durable Object's methods.