You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Cloudflare Worker即将休眠前执行代码并持久化缓存?

Cloudflare Worker内存缓存持久化到KV/Redis的可行方案

1. 正确使用workerSpinningDown终止事件

Cloudflare Worker原生提供workerSpinningDown事件,专门用于Worker实例即将终止前的清理或持久化操作。注意你原代码的拼写错误(wokerSpinningDown应为workerSpinningDown),且事件绑定需传递函数引用而非直接调用函数,同时要用waitUntil确保异步持久化操作完成后再终止Worker。

示例代码:

const validationCache = new Map<string, { counter: number }>();

// 持久化逻辑
async function saveCache() {
  // 将Map转换为可序列化对象
  const cacheData = Object.fromEntries(validationCache);
  // 写入KV
  await MY_KV_NAMESPACE.put('validation-cache', JSON.stringify(cacheData));
  // 若用Redis,替换为Redis客户端的set操作
  // await redisClient.set('validation-cache', JSON.stringify(cacheData));
}

// 正确绑定终止事件
addEventListener('workerSpinningDown', (event) => {
  event.waitUntil(saveCache());
});

export async function somemiddleware(c: Context, next: Next) {
  // 示例:操作内存缓存
  const key = 'sample-key';
  if (!validationCache.has(key)) {
    validationCache.set(key, { counter: 0 });
  }
  validationCache.get(key)!.counter++;

  await next();
  return c.response;
}

2. 定期批量持久化

依赖终止事件存在极端场景(如Worker意外崩溃)无法触发的风险,因此可以结合请求触发的定期持久化:每处理一定数量的请求,就将内存缓存同步到持久化存储,用waitUntil确保操作不阻塞响应。

示例代码:

const validationCache = new Map<string, { counter: number }>();
const BATCH_LIMIT = 100; // 每处理100个请求触发一次持久化
let requestCounter = 0;

async function saveCache() {
  const cacheData = Object.fromEntries(validationCache);
  await MY_KV_NAMESPACE.put('validation-cache', JSON.stringify(cacheData));
}

export async function somemiddleware(c: Context, next: Next) {
  // 操作内存缓存逻辑
  const key = 'sample-key';
  validationCache.has(key) ? validationCache.get(key)!.counter++ : validationCache.set(key, { counter: 1 });

  requestCounter++;
  // 达到阈值时触发持久化
  if (requestCounter >= BATCH_LIMIT) {
    c.waitUntil(saveCache());
    requestCounter = 0;
  }

  await next();
  return c.response;
}

3. 使用Durable Objects托管缓存

Durable Objects是Cloudflare提供的有状态服务,每个实例拥有独立的内存状态,且Cloudflare会自动管理实例的持久化和生命周期。你可以将缓存逻辑放在Durable Object内部,利用其state.storage实现自动持久化,或结合waitUntil手动同步。

第一步:定义Durable Object类

export class ValidationCacheStore {
  state: DurableObjectState;
  cache: Map<string, { counter: number }>;

  constructor(state: DurableObjectState) {
    this.state = state;
    // 从持久化存储加载初始缓存
    this.cache = new Map(JSON.parse(await this.state.storage.get('cache') || '[]'));
  }

  async fetch(request: Request) {
    const url = new URL(request.url);
    const key = url.searchParams.get('key');
    if (!key) return new Response('Missing key', { status: 400 });

    // 操作缓存
    if (!this.cache.has(key)) {
      this.cache.set(key, { counter: 0 });
    }
    this.cache.get(key)!.counter++;

    // 异步持久化,不阻塞响应
    this.state.waitUntil(
      this.state.storage.put('cache', JSON.stringify(Array.from(this.cache)))
    );

    return new Response(JSON.stringify({ counter: this.cache.get(key)!.counter }));
  }
}

第二步:在Worker中调用Durable Object

export interface Env {
  VALIDATION_CACHE_STORE: DurableObjectNamespace;
}

export async function somemiddleware(c: Context, next: Next) {
  // 获取Durable Object实例
  const cacheId = c.env.VALIDATION_CACHE_STORE.idFromName('global-validation-cache');
  const cacheStore = c.env.VALIDATION_CACHE_STORE.get(cacheId);

  // 调用实例方法操作缓存
  const cacheResp = await cacheStore.fetch(new Request(`http://localhost?key=sample-key`));
  const cacheData = await cacheResp.json();

  await next();
  return c.response;
}

方案对比

  • workerSpinningDown事件:原生支持终止前操作,适合最终同步,但极端场景可能失效,建议搭配定期持久化。
  • 定期批量持久化:可靠性高,避免意外数据丢失,通过调整阈值平衡性能与数据一致性。
  • Durable Objects:自带持久化与状态管理,适合高可靠性场景,但存在额外的计费与调度成本。

内容的提问来源于stack exchange,提问作者Om Srivastava

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.13 00:23:19