
Cloudflare Workers:边缘计算实践
Cloudflare Workers 在距离地球上每个用户毫秒级延迟的 300 多个数据中心内运行您的 JavaScript 或 WASM。与在单个区域运行的传统无服务器不同,Workers 在离请求用户最近的 PoP 中运行。
Workers 执行模型
Workers 使用 V8 隔离模型——而非容器或虚拟机。每个请求获得一个全新的 V8 上下文,启动时间约为 0ms(无冷启动)。请求之间的内存是隔离的。
// workers/api.js - 基本 Worker 结构
export default {
async fetch(request, env, ctx) {
const url = new URL(request.url);
if (url.pathname.startsWith('/api/')) {
return handleAPI(request, env);
}
const cached = await env.CACHE.get(url.pathname, 'arrayBuffer');
if (cached) {
return new Response(cached, {
headers: { 'CF-Cache-Status': 'HIT', 'Cache-Control': 'public, max-age=3600' }
});
}
const response = await fetch(request);
ctx.waitUntil(
env.CACHE.put(url.pathname, response.clone().body, { expirationTtl: 3600 })
);
return response;
}
};

KV:全局复制的键值存储
Workers KV 是最终一致性的(15 秒传播),非常适合配置、功能标志和缓存内容:
async function getFeatureFlags(env) {
// KV 读取延迟约 1ms(从本地 PoP 缓存提供)
return await env.CONFIG.get('feature-flags', 'json') ?? { newCheckout: false };
}
// 带元数据和 TTL 写入
await env.CONFIG.put('feature-flags', JSON.stringify({ newCheckout: true }), {
expirationTtl: 3600,
metadata: { updatedAt: Date.now() }
});
// 带前缀列出键
const keys = await env.CONFIG.list({ prefix: 'user:', limit: 100 });
Durable Objects:边缘的一致状态
Durable Objects 解决了 CAP 定理的挑战——每个对象在全局恰好一个位置运行,提供强一致性:
export class RateLimiter {
constructor(state, env) { this.state = state; }
async fetch(request) {
const { userId, limit, windowSeconds } = await request.json();
const now = Date.now();
const windowStart = now - windowSeconds * 1000;
const requests = await this.state.storage.get('requests') ?? [];
const recent = requests.filter(ts => ts > windowStart);
if (recent.length >= limit) {
return Response.json({ allowed: false,
retryAfter: Math.ceil((recent[0] + windowSeconds * 1000 - now) / 1000) });
}
recent.push(now);
await this.state.storage.put('requests', recent);
return Response.json({ allowed: true, remaining: limit - recent.length });
}
}
export default {
async fetch(request, env) {
const userId = request.headers.get('X-User-Id');
const id = env.RATE_LIMITER.idFromName(userId);
const rateLimiter = env.RATE_LIMITER.get(id);
const result = await rateLimiter.fetch(new Request('http://do/', {
method: 'POST',
body: JSON.stringify({ userId, limit: 100, windowSeconds: 60 })
}));
const { allowed, retryAfter } = await result.json();
if (!allowed) return new Response('Rate limited', {
status: 429, headers: { 'Retry-After': retryAfter }
});
return handleRequest(request, env);
}
};

Queues:可靠的背景处理
// 生产者
export default {
async fetch(request, env) {
const order = await request.json();
await env.ORDER_QUEUE.send({ orderId: order.id, timestamp: Date.now() });
return Response.json({ queued: true });
}
};
// 消费者
export default {
async queue(batch, env) {
for (const message of batch.messages) {
try {
await processOrder(message.body, env);
message.ack();
} catch (error) {
message.retry({ delaySeconds: 30 });
}
}
}
};
R2:兼容 S3 的对象存储(无出站费用)
export default {
async fetch(request, env) {
const key = new URL(request.url).pathname.slice(1);
if (request.method === 'PUT') {
await env.BUCKET.put(key, request.body, {
httpMetadata: { contentType: request.headers.get('Content-Type') }
});
return new Response(null, { status: 201 });
}
const object = await env.BUCKET.get(key);
if (!object) return new Response('Not Found', { status: 404 });
const headers = new Headers();
object.writeHttpMetadata(headers);
return new Response(object.body, { headers });
}
};
地理路由
export default {
async fetch(request, env) {
const continent = request.cf.continent;
const backends = {
'NA': 'https://us-east.api.example.com',
'EU': 'https://eu-west.api.example.com',
'AS': 'https://ap-southeast.api.example.com',
};
const backend = backends[continent] ?? backends['NA'];
return fetch(backend + new URL(request.url).pathname, {
method: request.method,
headers: {
...Object.fromEntries(request.headers),
'X-Client-Country': request.cf.country,
},
body: request.body
});
}
};
wrangler.toml 配置
name = "my-edge-app"
main = "src/index.js"
compatibility_date = "2026-01-01"
[[kv_namespaces]]
binding = "CACHE"
id = "abc123def456"
[[r2_buckets]]
binding = "BUCKET"
bucket_name = "my-app-assets"
[[queues.producers]]
queue = "order-queue"
binding = "ORDER_QUEUE"
[durable_objects]
bindings = [{ name = "RATE_LIMITER", class_name = "RateLimiter" }]
成本模型 vs 传统无服务器
| Cloudflare Workers | AWS Lambda | |
|---|---|---|
| 冷启动 | 0ms(隔离) | 100-500ms(容器) |
| 免费层 | 10万请求/天 | 100万请求/月 |
| 区域 | 300+ PoP | 约30个区域 |
| 最大持续时间 | 30秒(付费) | 15分钟 |
Workers 适用于:API 网关、A/B 测试、边缘认证验证、HTML 流式传输和缓存层。