正在加载,请稍候…

Cloudflare Workers Edge Computing: Building Globally Distributed Applications

Build globally distributed applications with Cloudflare Workers: KV storage, Durable Objects for consistency, R2 object storage, Queue consumers, and latency optimization across 300+ edge locations.

Cloudflare Workers: Edge Computing in Practice

Cloudflare Workers run your JavaScript or WASM within milliseconds of every user on Earth, across 300+ data centers. Unlike traditional serverless that runs in a single region, Workers run in the nearest PoP to the requesting user.

The Workers Execution Model

Workers use the V8 isolate model - not containers or VMs. Each request gets a fresh V8 context that starts in ~0ms (no cold starts). Memory is isolated between requests.

// workers/api.js - Basic Worker structure
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: Globally Replicated Key-Value Storage

Workers KV is eventually consistent (15s propagation), perfect for configuration, feature flags, and cached content:

async function getFeatureFlags(env) {
    // KV reads have ~1ms latency (served from local PoP cache)
    return await env.CONFIG.get('feature-flags', 'json') ?? { newCheckout: false };
}

// Write with metadata and TTL
await env.CONFIG.put('feature-flags', JSON.stringify({ newCheckout: true }), {
    expirationTtl: 3600,
    metadata: { updatedAt: Date.now() }
});

// List keys with prefix
const keys = await env.CONFIG.list({ prefix: 'user:', limit: 100 });

Durable Objects: Consistent State at the Edge

Durable Objects solve the CAP theorem challenge - each object runs in exactly ONE location globally, providing strong consistency:

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: Reliable Background Processing

// Producer
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 });
    }
};

// Consumer
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-Compatible Object Storage (No Egress Fees)

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 });
    }
};

Geographic Routing

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 Configuration

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" }]

Cost Model vs Traditional Serverless

Cloudflare Workers AWS Lambda
Cold start 0ms (isolates) 100-500ms (containers)
Free tier 100K req/day 1M req/month
Regions 300+ PoPs ~30 regions
Max duration 30s (paid) 15 minutes

Workers excel for: API gateways, A/B testing, auth edge validation, HTML streaming, and caching layers.