BetterLink Logo 比邻
切换语言
切换主题

Workers免费额度不够用?7个优化技巧让10万次撑一个月

Cloudflare Workers优化指南

引言

上个月我用 Workers 搭了个图床,结合 R2 存储,感觉挺完美。结果没到3天,就收到 Cloudflare 的邮件:你的免费额度快用完了。 我一脸懵:不是说每天10万次吗?我这小破图床能有多少流量?点开 Analytics 一看,日均12万次请求。这怎么可能?我明明才上传了几十张图片。 后来花了两天研究文档、翻社区讨论,才搞明白 Workers 的计费有多少坑。什么子请求、KV读取、缓存命中,每个都在”偷偷”消耗你的额度。 不过好消息是,搞清楚规则后,我用了几个优化技巧,把日请求量从12万降到3万。现在每月免费额度不仅够用,还能剩30%。今天就把这些实战经验分享给你,希望能帮你省下每月5美元的付费计划费用。

别被骗了!Workers的”10万次”不是你想的那样

说实话,Cloudflare 文档上写的”10万次请求/天”,很容易让人误解。我刚开始以为是:我的 Worker 被访问10万次就到顶了。其实不是这么算的。 真相1:子请求不单独计费,但有数量限制 Worker 里用 fetch() 去调用其他 API、读取 R2、查询 KV,这些都叫子请求。好消息是:子请求不单独算钱。坏消息是:免费计划每个请求只能发50个子请求,付费才能到1000个。 打个比方:用户访问你的图床网址(1次计费请求),Worker 里要查 KV 验证权限(1个子请求),再从 R2 拉图片(1个子请求)。虽然有2个子请求,但只算1次计费。 如果你做个聚合服务,一次请求要调10个 API,那就是10个子请求。免费计划50个的限制,听起来挺多,实际项目里很容易碰到天花板。 真相2:10万是账号级别限制,不是单个 Worker 这点挺坑的。我一开始以为可以搞多个 Worker 分散流量,后来发现10万次是整个账号的限制。你注册10个 Worker,加起来还是只有10万次。 想靠多 Worker 规避限额?不行的。社区里有人试过,Cloudflare 的限制是按账号来的。要突破只能付费,或者优化请求次数。 真相3:KV读写、Cache API操作都算请求 这个最容易被忽略。Worker 每次 KV.get() 读取数据,虽然不算子请求限制,但会消耗请求次数。如果你的 Worker 每次都要读 KV 验证权限,那等于每个用户访问都要多消耗1次 KV 操作。 Cache API 也一样。虽然用 Cache 能减少对源站的请求,但 Cache 的 match()put() 操作本身也有成本。 最容易踩的3个坑 我当时就是踩了这几个坑,才导致请求次数爆炸:

  1. 坑1:反向代理每次都发子请求,没用缓存 我做了个 API 中转服务,每次都 fetch() 原始 API。没想到缓存,结果每个用户请求都要发子请求。后来加了 Cache API,命中率80%,请求次数直接砍一半。
  2. 坑2:KV读取频繁,不知道 cacheTtl 参数 图床项目里,每张图片都要 KV.get() 查权限。我不知道可以设 cacheTtl 参数,让 KV 在边缘节点缓存数据。改成 cacheTtl: 600(10分钟)后,KV 读取减少了70%。
  3. 坑3:重定向链每个跳转都计数 我之前做短链服务,用 Worker 返回 302 重定向。后来发现,如果重定向链有3次跳转(A→B→C→目标),每次跳转都算1个子请求。改成直接返回最终地址,省了2次计数。 这些坑加起来,就是我从10万超到12万的原因。如果你也遇到额度不够用,先自查是不是踩了这些坑。

7个优化技巧,让免费额度多撑一个月

搞清楚计费规则后,我试了很多优化方案。这7个技巧是经过实战验证的,效果最明显、实现也不复杂。 技巧1:用好缓存,减少80%的重复请求 这是我试下来见效最快的方法。很多 Worker 项目其实不需要每次都实时计算,完全可以缓存结果。 我的图床项目优化前,每次访问图片都要走一遍完整流程:验证→读 R2→返回。优化后加了 Cache API:

const cache = caches.default;
const cacheKey = new Request(request.url, request);
// 先查缓存
let response = await cache.match(cacheKey);
if (response) {
  return response; // 缓存命中,直接返回
}
// 缓存未命中,处理请求
response = await handleRequest(request);
// 设置缓存(静态图片缓存1天)
response = new Response(response.body, {
  ...response,
  headers: {
    ...response.headers,
    'Cache-Control': 'public, max-age=86400',
  },
});
await cache.put(cacheKey, response.clone());
return response;

改完后,缓存命中率85%。原来日均12万次请求,现在只有1.8万次真正走 Worker 逻辑,省了10.2万次。 技巧2:KV优化三板斧 KV 是 Workers 里最常用的存储,但也是请求次数的大头。我总结了3个优化点:

  1. 增加 cacheTtl 参数 KV 默认在边缘节点缓存60秒。如果你的数据更新不频繁,可以加大这个值:
    // 优化前
    const value = await KV.get('key');
    // 优化后(缓存10分钟)
    const value = await KV.get('key', { cacheTtl: 600 });
    我的权限验证数据半小时才更新一次,设成 cacheTtl: 1800,KV 读取直接减少70%。
  2. 用 Cache API 缓存 KV 结果 如果数据更新更慢(比如配置文件、黑名单),可以在 Worker 层再加一层缓存:
    const cacheKey = `kv-cache:${key}`;
    let cached = await caches.default.match(cacheKey);
    if (!cached) {
      const value = await KV.get(key);
      cached = new Response(value);
      await caches.default.put(cacheKey, cached.clone());
    }
    return cached.text();
  3. 用 waitUntil 做非阻塞写入 如果要写 KV 但不需要等结果,用 waitUntil 可以不阻塞响应:
    // 不等 KV 写入完成就返回响应
    event.waitUntil(KV.put('key', 'value'));
    return new Response('OK');

这三招组合,让我的 KV 操作从日均3万次降到8000次。 技巧3:减少不必要的子请求 很多时候,子请求是可以优化掉的。 我之前做个聚合服务,要调5个外部 API,然后合并结果返回。每次请求 = 5个子请求。后来我改成:

  • 高频 API 的结果缓存5分钟
  • 低频 API 的结果用 KV 存24小时
  • 如果可以,直接把数据预处理好存 R2 优化后,80%的请求不需要发任何子请求,直接从缓存返回。 技巧4:善用 Request.cache 控制缓存行为 Cloudflare 在2024年11月新增了 Request.cache 属性,可以更精细地控制缓存:
// 跳过缓存(适合敏感数据)
const response = await fetch(url, { cache: 'no-store' });
// 使用默认缓存策略
const response = await fetch(url, { cache: 'default' });

我在处理用户私密图片时,用 cache: 'no-store' 确保不会被 CDN 缓存。公开图片用 default,让 Cloudflare 自动优化。 技巧5:优化重定向链 如果你的 Worker 会返回重定向(302/301),注意重定向链中的每次跳转都算子请求。 我的短链服务优化前:

// 优化前:返回302重定向
return Response.redirect(targetUrl, 302);

优化后:

// 优化后:缓存目标地址,减少重定向
const cached = await cache.match(shortUrl);
if (cached) {
  return cached; // 直接返回缓存的最终地址
}

对于会多次跳转的链接(比如 bit.ly → t.co → 最终网址),直接存储最终地址,避免每次都走重定向链。 技巧6:监控请求分布,找出”吞金兽” Cloudflare 的 Analytics 是免费的,一定要用起来。 我发现一个规律:80%的请求量往往来自20%的路径。在 Workers Analytics 里,可以看到:

  • 哪些路径请求最多
  • 哪些路径缓存命中率低
  • 哪些路径耗时最长 找出请求量最大的几个路径,针对性优化。我当时发现 /api/status 这个健康检查接口,被监控服务每分钟调100次,占了日请求量的15%。后来给这个接口加了60秒缓存,立省1.5万次/天。 技巧7:分时段处理非紧急任务 Workers 支持 Cron Triggers,可以定时执行任务。如果有些任务不是实时的(比如统计、清理、预热缓存),可以放到低峰期。 我的图床有个功能:每小时统计访问量。之前是每次访问都写 KV 计数器,后来改成:
  • 访问时只在内存计数(不写 KV)
  • 用 Cron Trigger 每小时汇总一次 这样把频繁的 KV 写入,变成每小时1次批量操作。日均 KV 写入从2万次降到24次。

实战案例:图床项目从日均12万→3万次

前面讲了这么多技巧,你可能会想:组合起来效果到底怎么样?我就拿自己的图床项目举例,完整复盘一遍优化过程。 项目背景 这是个简单的图床服务,技术栈:

  • Cloudflare Workers 处理请求
  • R2 存储图片文件
  • KV 存储图片元数据和权限
  • 日均约2000张图片访问(真实用户流量) 上线第3天,收到 Cloudflare 提醒:日均12万次请求,接近免费额度上限。 问题诊断 我花了半天时间,用 Analytics 和代码审查找出了3个主要问题:
  1. 每次图片请求都查 KV 每张图片访问,Worker 都要 KV.get() 查元数据(文件名、大小、上传者)。2000张图片访问 = 2000次 KV 读取。但这些元数据基本不变,根本不需要每次都查。
  2. 没有浏览器缓存 我的响应头里没设 Cache-Control,导致用户刷新页面,浏览器都要重新请求。同一张图片被同一个用户请求10次,Worker 就被调用10次。
  3. 缩略图实时生成 图片列表页显示缩略图,我用 Worker 实时裁剪生成。一个列表页30张图 = 30次图片处理请求。用户翻几页,请求次数就爆了。 这三个问题,导致实际2000次有效访问,变成12万次 Worker 调用。 优化方案 针对这3个问题,我按优先级做了优化: 第1步:KV 缓存优化(见效最快) 给 KV 读取加 cacheTtl 参数:
// 优化前
const metadata = await IMAGE_KV.get(imageId);
// 优化后
const metadata = await IMAGE_KV.get(imageId, {
  cacheTtl: 600  // 缓存10分钟
});

效果:KV 读取从2000次/天降到约300次/天(-85%) 第2步:添加浏览器缓存 给图片响应添加缓存头:

return new Response(imageData, {
  headers: {
    'Content-Type': 'image/jpeg',
    'Cache-Control': 'public, max-age=86400',  // 缓存1天
    'CDN-Cache-Control': 'public, max-age=2592000'  // CDN缓存30天
  }
});

效果:重复访问减少60%,请求从12万降到4.8万 第3步:缩略图预生成 不再实时生成,改为上传时预生成,存到 R2 的 thumbnails/ 目录:

// 上传时生成缩略图
const thumbnail = await generateThumbnail(image);
await R2.put(`thumbnails/${imageId}`, thumbnail);
// 访问时直接读取
const thumbnail = await R2.get(`thumbnails/${imageId}`);

效果:缩略图请求不再触发 Worker 处理逻辑,请求从4.8万降到3.2万 第4步:Worker 缓存层 最后给整个响应加 Cache API:

const cache = caches.default;
let response = await cache.match(request);
if (response) return response;
// 处理请求...
await cache.put(request, response.clone());
return response;

效果:缓存命中率78%,最终稳定在日均3万次左右 优化结果

指标优化前优化后变化
日请求量12万次3.2万次-73%
KV 读取2000次300次-85%
缓存命中率0%78%+78%
费用超额20%富余70%省60美元/年
现在这个图床稳定运行了2个月,日均请求3-4万次,免费额度完全够用。按付费计划5美元/月算,一年省下60美元。
经验总结
回头看这次优化,我总结了几个关键点:
  1. 先找瓶颈,再优化:不要盲目优化,用 Analytics 找出真正的问题
  2. 缓存是王道:80%的优化效果来自缓存(浏览器缓存、CDN缓存、Worker缓存)
  3. KV 要谨慎用:能缓存的一定要设 cacheTtl,能预计算的不要实时查
  4. 增量优化:我是分4步优化的,每步都能看到明显效果,而不是一次改太多

付费还是优化?算笔经济账

看到这里你可能会想:我是花时间优化,还是直接付费升级?这个问题我也纠结过,后来算了笔账就清楚了。 免费计划 vs 付费计划对比

项目免费计划付费计划(5美元/月)
日请求量10万次~33万次(1000万/月)
每分钟限制1000次无明确限制
子请求数50次/请求1000次/请求
KV 读取10万次/天1000万次/月
CPU 时间10ms50ms
年费用0元60美元
从数据看,付费计划确实香:日请求量翻3倍,子请求限制放宽20倍。但关键是,你真的需要吗?
什么情况该升级付费?
我总结了3种场景,建议直接付费:
  1. 日请求稳定超10万 注意是”稳定”超。如果只是偶尔流量高峰超一点,可以通过优化解决。但如果连续一周都超,说明业务量确实上来了,付费更省心。
  2. 需要大量子请求 如果你做爬虫、聚合服务、API网关,一次请求要调10+个外部 API,免费50次的限制肯定不够。这种情况优化空间有限,付费计划1000次的限制更合理。
  3. 商业项目,稳定性>成本 如果是给客户做的项目,或者自己的商业产品,别在免费额度上省这点钱。付费计划的 SLA 更有保障,出问题可以开工单。5美元换来的稳定性,远比省这点钱重要。 优化的边界在哪里? 反过来说,有些情况优化就是浪费时间:
  4. 过度优化导致代码复杂 为了省请求,写了一堆缓存逻辑、预计算脚本、定时任务,代码变得很难维护。这时候,你的时间成本可能远超5美元。
  5. 优化已经到极限 如果该加的缓存都加了,该优化的都优化了,还是不够用,那就是业务量的问题了。别硬扛,该付费付费。
  6. 时间成本 vs 5美元 算一下你的时薪。如果优化要花3小时,你的时薪超过20块,那直接付费更划算。 我的建议是:
  • 个人项目、学习项目:优先优化,当省钱也当学习
  • 小团队、初期产品:先优化到极限,再考虑付费
  • 商业项目、客户项目:直接付费,别在这上面省钱 付费之后还要优化吗? 要。虽然付费计划额度高,但计费规则是一样的。如果不优化,1000万次的额度也能给你用完。 而且付费计划超额后,按每百万请求0.50美元计费。如果你日均100万次请求,一个月就是15美元超额费用,加上基础5美元 = 20美元/月。这时候优化的价值就体现出来了。

结论

说了这么多,核心就是一句话:搞清楚 Workers 怎么计费,然后用对方法优化。 Workers 的10万次免费额度,乍一看挺多,实际用起来很容易超。但大部分情况,不是业务量太大,而是没优化好。 我的图床项目就是例子:真实流量只有2000次访问,却触发了12万次请求。通过缓存、KV 优化、预计算,最终降到3万次,不仅够用还有富余。 如果你也遇到额度不够用,建议按这个步骤来:

  1. 打开 Workers Analytics,看看是哪些路径在”吃”额度
  2. 从缓存和 KV 入手,这两个优化见效最快
  3. 检查有没有踩本文提到的3个坑(子请求、KV cacheTtl、重定向链)
  4. 把前面7个技巧都试一遍,组合起来效果更好
  5. 如果优化到极限还不够,再考虑付费 最后提醒一句:Cloudflare 毕竟是商业公司,免费额度要合理使用。过度”薅羊毛”可能被限速,甚至封号。优化的目的是更高效利用资源,不是钻空子。 如果这篇文章帮你省下了5美元,不妨点个赞或者分享给也在用 Workers 的朋友。大家一起把免费额度用到极致。

发布于: 2025年12月1日 · 修改于: 2025年12月4日

相关文章