Workers Cache:把缓存放到 Worker 入口前面

2026-07-06 34 预计阅读时间: 1 分钟
来源: blog.cloudflare.com AI 摘要 Original link

Disclaimer: This article is an AI-assisted summary. Read it together with the original source when precision matters. The summary may omit context, version differences, or edge cases and is not official documentation.

预计阅读时间:8 分钟

Cloudflare 新推出的 Workers Cache,把一个按区域分层的缓存层直接放在 Worker entrypoint 前面。关键变化不是“又多了一个缓存 API”,而是请求在进入 Worker 代码之前就有机会命中缓存,而且配置方式回到开发者熟悉的 HTTP 头:Cache-ControlVaryETag 这类协议级信号。

这对 Worker 应用的影响很直接:热点响应可以少进运行时,边缘函数可以少做重复计算,后端 API 也能少挨打。更重要的是,它保留了 Worker 的组合能力,缓存策略可以和路由、鉴权、重写、上游请求一起设计。

缓存在 Worker 前面,意味着什么

传统 Worker 场景里,请求通常先进入 Worker,再由代码决定是否查 caches.default、是否访问源站、是否拼响应。Workers Cache 的位置更靠前:它坐在 Worker entrypoint 前面,因此一次命中可以直接跳过 Worker 执行路径。

这类设计适合三种常见负载:

  • 可公开缓存的 API 响应,例如产品列表、配置 JSON、文档索引。
  • 计算成本高但结果短时间稳定的页面片段,例如聚合页、排行榜、搜索建议。
  • 由 Worker 代理出来的静态或半静态资源,例如图片变体、manifest、RSS。

边界也要说清楚:如果响应依赖用户身份、Cookie、Authorization 头,或者包含账户级私密数据,就不能粗暴设置为公共缓存。前置缓存越早命中,错误缓存的影响面也越大。

标准 HTTP 头重新变成控制面

来源摘要里最值得注意的一句是“configured via standard HTTP headers”。这意味着缓存策略不是藏在某个专用 SDK 调用里,而是体现在响应语义上。

可以这样理解常用头的职责:

  • Cache-Control: public, s-maxage=60:告诉共享缓存这个响应可以缓存 60 秒。
  • stale-while-revalidate=300:允许缓存先返回旧内容,再异步更新,适合允许短暂陈旧的数据。
  • Vary: Accept-Encoding 或业务相关头:声明哪些请求头会影响响应版本。
  • ETag:给再验证提供稳定标识,减少完整响应传输。

这让缓存策略更容易被 review。你不必在一堆分支逻辑里猜“这个响应到底会不会被缓存”,看响应头就能判断大半。

可以这样实践:给公开 API 加前置缓存语义

下面是一个可改造的 Worker 示例。它没有假设某个专有配置接口,只演示如何通过标准 HTTP 头表达“这个响应适合共享缓存”。把 https://api.example.com/products 换成你的真实上游地址即可。

export default {
  async fetch(request) {
    const url = new URL(request.url);

    if (url.pathname !== "/products") {
      return new Response("Not found", { status: 404 });
    }

    const upstream = await fetch("https://api.example.com/products", {
      headers: {
        "Accept": "application/json"
      }
    });

    if (!upstream.ok) {
      return new Response("Upstream error", { status: 502 });
    }

    const body = await upstream.text();

    return new Response(body, {
      status: 200,
      headers: {
        "Content-Type": "application/json; charset=utf-8",
        "Cache-Control": "public, s-maxage=60, stale-while-revalidate=300",
        "Vary": "Accept-Encoding"
      }
    });
  }
};

本地项目可以用最小结构启动:

mkdir workers-cache-demo
cd workers-cache-demo
npm init -y
npm install --save-dev wrangler
cat > wrangler.toml <<'EOF'
name = "workers-cache-demo"
main = "src/index.js"
compatibility_date = "2025-01-01"
EOF
mkdir -p src
# 将上面的 Worker 代码保存到 src/index.js
npx wrangler dev

再用 curl 看响应头是否符合预期:

curl -i http://localhost:8787/products

你要重点检查这些行:

HTTP/1.1 200 OK
Content-Type: application/json; charset=utf-8
Cache-Control: public, s-maxage=60, stale-while-revalidate=300
Vary: Accept-Encoding

上线前还可以为不同路径设定不同策略。例如列表页短缓存,详情页稍长缓存,用户相关接口完全禁止公共缓存:

function cacheHeadersFor(pathname) {
  if (pathname.startsWith("/account")) {
    return {
      "Cache-Control": "private, no-store"
    };
  }

  if (pathname.startsWith("/products/")) {
    return {
      "Cache-Control": "public, s-maxage=300, stale-while-revalidate=600",
      "Vary": "Accept-Encoding"
    };
  }

  return {
    "Cache-Control": "public, s-maxage=60, stale-while-revalidate=300",
    "Vary": "Accept-Encoding"
  };
}

组合能力的真正价值

“Infinitely composable”听起来像宣传词,但放在 Worker 体系里有实际含义。Worker 通常已经承担路由、A/B 实验、请求归一化、后端代理、响应改写等职责。前置缓存如果只支持一刀切规则,价值会被限制;如果它能跟 HTTP 头和 Worker 响应自然组合,工程团队就能把缓存策略写进应用边界。

一个实用做法是先做请求归一化,再让缓存看到稳定的响应语义。例如:

  • 删除不影响响应的 query 参数,避免缓存碎片。
  • 对会影响内容的参数保留顺序和格式,避免错误合并。
  • 只对 GETHEAD 返回公共缓存头。
  • 对带 Authorization 或敏感 Cookie 的请求返回 no-store

可以这样实践一个防误缓存的判断函数:

function isPublicCacheCandidate(request) {
  if (request.method !== "GET" && request.method !== "HEAD") {
    return false;
  }

  const headers = request.headers;
  if (headers.has("Authorization")) {
    return false;
  }

  const cookie = headers.get("Cookie") || "";
  if (cookie.includes("session=") || cookie.includes("auth=")) {
    return false;
  }

  return true;
}

上线前的检查清单

采用 Workers Cache 时,不要从“缓存一切”开始。更稳的路径是挑一个公开、读多写少、错误成本可控的入口,先把响应头设计清楚。

上线前建议检查:

  • 是否只缓存公开数据,用户态响应是否明确 privateno-store
  • s-maxage 是否符合业务更新频率,而不是拍脑袋给一个很长时间。
  • 是否需要 stale-while-revalidate 来降低尾延迟。
  • Vary 是否足够小,避免缓存版本爆炸。
  • 是否有观测手段确认命中率、源站流量和错误缓存。

Workers Cache 的价值在于把缓存从“代码里的一段逻辑”提升到 Worker 入口前的协议层能力。用得好,它能减少运行时执行和源站压力;用得粗糙,它也会把错误响应更快、更稳定地分发出去。把缓存头当作接口契约来设计,是采用它时最重要的工程纪律。


相关推荐