上一篇 下一篇 分享链接 返回 返回顶部

把账单打下来:Cloudflare 降本实战与 Workers 源码示例

发布人:慈云数据-客服中心 发布时间:2小时前 阅读量:3

Cloudflare 如何降低成本|附源码

在互联网业务中,“成本”通常不是单一维度的问题。很多团队一开始只关注服务器价格,比如一台云服务器每月多少钱、数据库套餐多少钱、对象存储多少钱。但随着业务增长,真正让成本快速上升的,往往是这些部分:

  • CDN 流量费用;
  • 对象存储外网流出费用;
  • 动态接口访问压力;
  • 源站带宽;
  • Web 安全防护成本;
  • 全球访问加速成本;
  • 运维人力成本;
  • 灰度发布、证书管理、DNS 管理等隐性成本。

Cloudflare 的价值并不仅仅是“套一层 CDN”,而是通过其全球边缘网络,把很多原本需要源站、CDN、安全产品、负载均衡、对象存储、边缘计算共同完成的事情,整合到一个平台中完成。

本文将从实际业务角度,系统说明 Cloudflare 如何帮助网站、SaaS、API 服务、静态站点、图片服务以及中小型创业团队降低成本,并附上一份可直接使用的 Cloudflare Workers 源码示例,用于实现边缘缓存、反向代理、接口加速和简单防盗刷。


一、为什么 Cloudflare 能降低成本?

Cloudflare 的核心优势在于它拥有遍布全球的边缘节点。用户访问网站时,请求可以优先在离用户最近的 Cloudflare 节点处理,而不是每次都回源到你的服务器。

这意味着:

  1. 静态资源可以直接从 Cloudflare 节点返回;
  2. 热门页面可以缓存到边缘;
  3. 恶意流量可以在到达源站之前被拦截;
  4. TLS 证书可以由 Cloudflare 自动管理;
  5. DNS 解析可以使用 Cloudflare 的 Anycast 网络;
  6. 部分业务逻辑可以用 Workers 在边缘运行;
  7. 对象存储可以使用 R2 避免高额流量流出费用。

传统架构中,你可能需要购买:

  • 云服务器;
  • CDN 服务;
  • WAF 服务;
  • 负载均衡;
  • 对象存储;
  • 云函数;
  • DDoS 防护;
  • SSL 证书;
  • 日志服务;
  • 全球加速服务。

而使用 Cloudflare 后,很多基础能力可以集中在一个平台中解决。对于中小团队来说,这种整合可以明显降低基础设施复杂度和成本。


二、通过 CDN 缓存降低源站带宽成本

最直接的成本优化方式就是缓存静态资源。

常见的静态资源包括:

  • 图片;
  • CSS;
  • JavaScript;
  • 字体文件;
  • 视频封面;
  • 下载文件;
  • 静态 HTML 页面;
  • 文档页面;
  • 前端构建产物。

如果这些资源每次都由源站返回,那么源站需要承担大量带宽和请求压力。假设一个网站每天有 100 万次图片请求,每张图片平均 200KB,那么每天流量大约是:

1000000 × 200KB = 200000000KB ≈ 190GB

如果全部由源站云服务器或者对象存储外网流出,成本会随着访问量快速上涨。

使用 Cloudflare 后,首次请求会回源,后续请求如果命中缓存,就可以直接由 Cloudflare 边缘节点返回,不再消耗源站带宽。

推荐配置

在 Cloudflare Dashboard 中可以配置:

Caching -> Cache Rules

针对静态资源设置缓存规则,例如:

URL Path contains .jpg
URL Path contains .png
URL Path contains .webp
URL Path contains .css
URL Path contains .js
URL Path contains .woff2

缓存时间可以设置为:

Edge TTL: 1 month
Browser TTL: 1 day 或 7 days

如果你的文件名带有 hash,例如:

app.8f3a1c.js
style.9d21b.css
logo.13ac.webp

可以放心设置更长缓存时间,比如 30 天甚至 1 年,因为文件内容变化时文件名也会变化。


三、通过 Cache Everything 降低动态页面成本

很多人以为 Cloudflare 只能缓存静态资源。实际上,如果你的页面适合缓存,也可以通过规则让 Cloudflare 缓存 HTML 页面。

比如:

  • 博客文章页面;
  • 文档页面;
  • 商品详情页;
  • 新闻页面;
  • 营销活动页;
  • 帮助中心页面。

这些页面虽然是 HTML,但内容并不需要每次都实时生成。通过缓存 HTML,可以大幅减少源站压力。

示例场景

一个博客网站每篇文章由后端动态渲染。如果热门文章被频繁访问,源站需要不断查询数据库、渲染模板、返回 HTML。

开启 Cloudflare HTML 缓存后:

  1. 第一次访问时回源;
  2. Cloudflare 缓存 HTML;
  3. 后续访问直接从边缘节点返回;
  4. 源站 CPU、数据库查询、带宽都下降。

注意事项

不要缓存用户个性化页面,例如:

  • 用户后台;
  • 订单页面;
  • 购物车页面;
  • 登录后的个人中心;
  • 带有用户隐私信息的接口。

如果页面根据 Cookie 或登录状态返回不同内容,需要谨慎处理缓存规则,否则可能出现隐私泄露。


四、使用 Cloudflare Pages 降低前端部署成本

对于静态网站、前端项目、博客、文档站点来说,Cloudflare Pages 是一个非常适合降低成本的方案。

它适用于:

  • Vue 项目;
  • React 项目;
  • Next.js 静态导出;
  • Astro;
  • Hugo;
  • Hexo;
  • VitePress;
  • Docusaurus;
  • 纯 HTML 项目。

Cloudflare Pages 的优点:

  • 免费额度友好;
  • 自动 HTTPS;
  • 自动全球 CDN;
  • 支持 Git 自动部署;
  • 支持预览环境;
  • 不需要单独购买服务器;
  • 不需要自己配置 Nginx;
  • 不需要手动续签证书。

传统部署方式可能是:

GitHub -> CI/CD -> 云服务器 -> Nginx -> SSL -> CDN

使用 Cloudflare Pages 后可以变成:

GitHub -> Cloudflare Pages -> 全球边缘网络

这不仅降低费用,也减少了运维复杂度。


五、使用 Cloudflare Workers 替代部分后端服务

Cloudflare Workers 是运行在 Cloudflare 边缘节点上的 Serverless 运行环境。它适合处理一些轻量级逻辑,例如:

  • API 反向代理;
  • 边缘缓存;
  • A/B 测试;
  • Header 改写;
  • 鉴权校验;
  • 短链接跳转;
  • 图片代理;
  • 简单接口聚合;
  • 防盗链;
  • 请求限流;
  • 地区判断;
  • 灰度发布。

传统情况下,你可能需要为这些逻辑准备一台服务器,安装 Node.js、Nginx、PM2、证书、日志系统等。而 Workers 可以直接在边缘执行,省掉了服务器和运维成本。

当然,Workers 不适合替代所有后端服务。它更适合“轻逻辑、低延迟、强边缘”的场景。如果业务涉及复杂事务、长时间任务、大型数据库操作,仍然建议放在传统后端或专门的云服务中。


六、使用 R2 降低对象存储流量成本

对象存储的成本通常包括:

  • 存储容量费用;
  • 请求次数费用;
  • 外网流出费用。

很多云厂商的对象存储在“存储容量”上看起来很便宜,但外网流量费用不低。比如图片站、下载站、文档站点,如果大量文件从对象存储流出,费用会非常明显。

Cloudflare R2 的一个核心卖点是:

无出口流量费用

这对以下业务非常有吸引力:

  • 图片资源存储;
  • 软件安装包;
  • 文档文件;
  • 用户上传附件;
  • 静态资源包;
  • 视频片段;
  • 模型文件;
  • 前端构建产物。

如果再结合 Cloudflare CDN 缓存,就可以进一步减少 R2 请求次数,提高访问速度。

推荐架构

用户
  ↓
Cloudflare CDN / Worker
  ↓
Cloudflare R2

这样用户访问资源时,热门文件优先由边缘缓存返回,冷门文件再从 R2 获取。


七、使用 WAF 和 Bot 防护降低安全成本

安全成本往往容易被低估。

如果没有防护,恶意请求可能导致:

  • 源站 CPU 被打满;
  • 数据库被拖垮;
  • 登录接口被撞库;
  • 接口被刷;
  • 带宽被消耗;
  • 账单异常增加;
  • 服务不可用。

Cloudflare 提供了基础 WAF、防火墙规则、速率限制、Bot Fight Mode 等能力,可以在请求到达源站前进行过滤。

例如你可以配置:

1. 阻止特定国家或地区访问;
2. 阻止恶意 User-Agent;
3. 对登录接口启用更严格的校验;
4. 对 API 接口配置速率限制;
5. 对异常访问触发 Managed Challenge;
6. 对后台路径只允许固定 IP 访问。

这样可以减少源站面对的恶意流量,从而降低服务器资源消耗和安全产品成本。


八、使用 DNS 降低管理和可用性成本

Cloudflare DNS 是很多人最早接触 Cloudflare 的功能。它的特点是:

  • 解析速度快;
  • Anycast 全球网络;
  • 免费;
  • 管理体验好;
  • 支持代理模式;
  • 方便配置安全规则;
  • 自动 HTTPS;
  • 易于迁移服务。

DNS 本身看似不是大成本项,但它关系到可用性。一旦 DNS 服务不稳定,整个业务都可能无法访问。

使用 Cloudflare DNS 可以减少:

  • 自建 DNS 运维成本;
  • 不可靠 DNS 服务带来的故障风险;
  • 多区域解析配置复杂度;
  • 证书和代理配置成本。

九、通过图片优化降低流量成本

图片通常是网站流量成本的大头。

Cloudflare 可以通过以下方式优化图片成本:

  1. 缓存图片;
  2. 使用 Polish 压缩图片;
  3. 使用 WebP/AVIF;
  4. 使用 Image Resizing;
  5. 使用 Workers 实现图片代理和参数过滤;
  6. 对图片设置长缓存。

例如,将一张 500KB 的 JPG 转为 WebP 后可能只剩 150KB。如果每天有几十万次图片访问,流量节省非常明显。

即便不使用 Cloudflare 的付费图片产品,也可以通过以下方式降低成本:

  • 上传前压缩图片;
  • 使用 WebP;
  • 控制最大图片宽度;
  • 给图片 URL 加版本号;
  • 设置长缓存;
  • 避免原图直接外链。

十、通过 Zero Trust 降低内部访问成本

对于公司内部系统,例如:

  • 管理后台;
  • 数据看板;
  • 测试环境;
  • 内部文档;
  • 运维面板;
  • Grafana;
  • Jenkins;
  • GitLab;
  • Admin API。

传统方式通常需要:

  • VPN;
  • 堡垒机;
  • 固定公网 IP;
  • 安全组;
  • 证书;
  • 防火墙;
  • 访问日志。

Cloudflare Zero Trust 可以通过身份认证、访问策略和隧道能力,将内部系统安全地暴露给授权用户,而不一定需要传统 VPN。

这可以减少 VPN 服务器、安全运维和公网暴露风险带来的成本。


十一、成本优化实战架构

下面给出一个适合中小团队的低成本架构:

前端页面:Cloudflare Pages
静态资源:Cloudflare CDN
对象存储:Cloudflare R2
轻量接口:Cloudflare Workers
核心业务:云服务器 / 后端服务
数据库:云数据库 / 自建数据库
安全防护:Cloudflare WAF
内部访问:Cloudflare Zero Trust
DNS:Cloudflare DNS

访问流程:

用户请求
  ↓
Cloudflare DNS
  ↓
Cloudflare CDN / WAF
  ↓
命中缓存:直接返回
  ↓
未命中缓存:Workers 处理
  ↓
需要业务数据:回源后端
  ↓
响应结果写入边缘缓存
  ↓
返回用户

这种架构的目标不是完全不用服务器,而是把大量重复、低价值、高频访问的请求放到 Cloudflare 边缘处理,让源站只处理真正需要动态计算的业务。


十二、附源码:Cloudflare Workers 边缘缓存反向代理

下面是一份 Cloudflare Workers 示例源码。它可以实现:

  • API 反向代理;
  • 静态资源缓存;
  • HTML 页面缓存;
  • 自定义缓存时间;
  • 防止部分恶意 User-Agent;
  • 简单鉴权;
  • 回源 Header 改写;
  • 缓存命中标记;
  • OPTIONS 跨域处理。

说明:此代码适合学习和中小型业务改造使用。生产环境需要根据自己的业务路径、登录状态、Cookie、隐私数据进行更严格的缓存控制。


1. worker.js

/**
 * Cloudflare Workers 边缘缓存反向代理示例
 *
 * 功能:
 * 1. 将请求代理到源站;
 * 2. 对静态资源和部分 HTML 页面进行边缘缓存;
 * 3. 对 API 请求设置较短缓存或不缓存;
 * 4. 拦截常见恶意 User-Agent;
 * 5. 支持简单 Token 鉴权;
 * 6. 添加缓存命中 Header;
 * 7. 支持 CORS 预检请求。
 */

const CONFIG = {
  // 源站地址,不要以 / 结尾
  ORIGIN: "https://origin.example.com",

  // 是否开启简单 Token 鉴权
  ENABLE_TOKEN_AUTH: false,

  // 鉴权 Token,建议放到环境变量中,不要硬编码
  API_TOKEN: "change-me",

  // 允许跨域的来源,生产环境建议改为具体域名
  ALLOW_ORIGIN: "*",

  // 默认缓存时间,单位:秒
  DEFAULT_CACHE_TTL: 300,

  // 静态资源缓存时间,单位:秒
  STATIC_CACHE_TTL: 60 * 60 * 24 * 30,

  // HTML 页面缓存时间,单位:秒
  HTML_CACHE_TTL: 60 * 10,

  // API 缓存时间,单位:秒
  API_CACHE_TTL: 30
};

const BLOCKED_UA_KEYWORDS = [
  "sqlmap",
  "nikto",
  "acunetix",
  "masscan",
  "zgrab",
  "python-requests",
  "curl/7.58"
];

const STATIC_EXTENSIONS = [
  ".jpg",
  ".jpeg",
  ".png",
  ".gif",
  ".webp",
  ".avif",
  ".svg",
  ".css",
  ".js",
  ".mjs",
  ".woff",
  ".woff2",
  ".ttf",
  ".eot",
  ".ico",
  ".mp4",
  ".webm",
  ".pdf",
  ".zip"
];

export default {
  async fetch(request, env, ctx) {
    try {
      return await handleRequest(request, env, ctx);
    } catch (error) {
      return new Response(
        JSON.stringify({
          error: "Internal Error",
          message: error.message
        }),
        {
          status: 500,
          headers: {
            "Content-Type": "application/json;charset=UTF-8"
          }
        }
      );
    }
  }
};

async function handleRequest(request, env, ctx) {
  const url = new URL(request.url);

  // 处理 CORS 预检请求
  if (request.method === "OPTIONS") {
    return handleOptions();
  }

  // 只允许常见 HTTP 方法
  if (!["GET", "HEAD", "POST", "PUT", "PATCH", "DELETE"].includes(request.method)) {
    return new Response("Method Not Allowed", { status: 405 });
  }

  // 拦截恶意 User-Agent
  if (isBlockedUserAgent(request)) {
    return new Response("Forbidden", { status: 403 });
  }

  // 简单 Token 鉴权示例
  if (CONFIG.ENABLE_TOKEN_AUTH && isProtectedPath(url.pathname)) {
    const ok = checkToken(request);
    if (!ok) {
      return new Response("Unauthorized", { status: 401 });
    }
  }

  // 对非 GET/HEAD 请求不做缓存,直接代理
  if (request.method !== "GET" && request.method !== "HEAD") {
    return proxyToOrigin(request, {
      cacheTtl: 0,
      cacheEnabled: false
    });
  }

  const cachePolicy = getCachePolicy(url.pathname, request);

  if (!cachePolicy.cacheEnabled) {
    return proxyToOrigin(request, cachePolicy);
  }

  const cache = caches.default;
  const cacheKey = buildCacheKey(request);
  const cachedResponse = await cache.match(cacheKey);

  if (cachedResponse) {
    return addResponseHeaders(cachedResponse, {
      cacheStatus: "HIT",
      ttl: cachePolicy.cacheTtl
    });
  }

  const originResponse = await proxyToOrigin(request, cachePolicy);

  // 只缓存成功响应
  if (originResponse.status >= 200 && originResponse.status < 300) {
    const responseToCache = originResponse.clone();

    ctx.waitUntil(cache.put(cacheKey, responseToCache));
  }

  return addResponseHeaders(originResponse, {
    cacheStatus: "MISS",
    ttl: cachePolicy.cacheTtl
  });
}

function handleOptions() {
  return new Response(null, {
    status: 204,
    headers: {
      "Access-Control-Allow-Origin": CONFIG.ALLOW_ORIGIN,
      "Access-Control-Allow-Methods": "GET,HEAD,POST,PUT,PATCH,DELETE,OPTIONS",
      "Access-Control-Allow-Headers": "Content-Type,Authorization,X-API-Token",
      "Access-Control-Max-Age": "86400"
    }
  });
}

function isBlockedUserAgent(request) {
  const ua = request.headers.get("User-Agent") || "";
  const lowerUA = ua.toLowerCase();

  return BLOCKED_UA_KEYWORDS.some(keyword => lowerUA.includes(keyword));
}

function isProtectedPath(pathname) {
  return pathname.startsWith("/api/private") || pathname.startsWith("/admin-api");
}

function checkToken(request) {
  const tokenFromHeader = request.headers.get("X-API-Token");
  const authHeader = request.headers.get("Authorization");

  if (tokenFromHeader === CONFIG.API_TOKEN) {
    return true;
  }

  if (authHeader === `Bearer ${CONFIG.API_TOKEN}`) {
    return true;
  }

  return false;
}

function getCachePolicy(pathname, request) {
  const lowerPath = pathname.toLowerCase();

  // 登录、用户中心、订单、购物车等页面不要缓存
  const noCachePrefixes = [
    "/login",
    "/logout",
    "/user",
    "/account",
    "/cart",
    "/checkout",
    "/order",
    "/admin"
  ];

  if (noCachePrefixes.some(prefix => lowerPath.startsWith(prefix))) {
    return {
      cacheEnabled: false,
      cacheTtl: 0
    };
  }

  // 如果请求中带有明显的登录 Cookie,不缓存
  const cookie = request.headers.get("Cookie") || "";
  if (cookie.includes("session") || cookie.includes("token") || cookie.includes("auth")) {
    return {
      cacheEnabled: false,
      cacheTtl: 0
    };
  }

  // 静态资源长缓存
  if (STATIC_EXTENSIONS.some(ext => lowerPath.endsWith(ext))) {
    return {
      cacheEnabled: true,
      cacheTtl: CONFIG.STATIC_CACHE_TTL
    };
  }

  // 部分公开 API 短缓存
  if (lowerPath.startsWith("/api/public")) {
    return {
      cacheEnabled: true,
      cacheTtl: CONFIG.API_CACHE_TTL
    };
  }

  // 文章、文档、商品详情页等可以缓存 HTML
  if (
    lowerPath.startsWith("/blog") ||
    lowerPath.startsWith("/docs") ||
    lowerPath.startsWith("/product")
  ) {
    return {
      cacheEnabled: true,
      cacheTtl: CONFIG.HTML_CACHE_TTL
    };
  }

  // 默认短缓存
  return {
    cacheEnabled: true,
    cacheTtl: CONFIG.DEFAULT_CACHE_TTL
  };
}

function buildCacheKey(request) {
  const url = new URL(request.url);

  // 删除无意义的追踪参数,提升缓存命中率
  const ignoredParams = [
    "utm_source",
    "utm_medium",
    "utm_campaign",
    "utm_term",
    "utm_content",
    "fbclid",
    "gclid"
  ];

  for (const param of ignoredParams) {
    url.searchParams.delete(param);
  }

  // 可以按需保留影响内容的参数,例如 page、id、category
  return new Request(url.toString(), {
    method: "GET"
  });
}

async function proxyToOrigin(request, cachePolicy) {
  const incomingUrl = new URL(request.url);
  const originUrl = new URL(CONFIG.ORIGIN);

  originUrl.pathname = incomingUrl.pathname;
  originUrl.search = incomingUrl.search;

  const headers = new Headers(request.headers);

  // 改写 Host,避免源站校验 Host 失败
  headers.set("Host", originUrl.hostname);

  // 传递真实客户端信息
  const cfConnectingIp = request.headers.get("CF-Connecting-IP");
  if (cfConnectingIp) {
    headers.set("X-Real-IP", cfConnectingIp);
    headers.set("X-Forwarded-For", cfConnectingIp);
  }

  headers.set("X-Forwarded-Proto", "https");

  const fetchOptions = {
    method: request.method,
    headers,
    redirect: "follow"
  };

  if (!["GET", "HEAD"].includes(request.method)) {
    fetchOptions.body = request.body;
  }

  if (cachePolicy.cacheEnabled && cachePolicy.cacheTtl > 0) {
    fetchOptions.cf = {
      cacheEverything: true,
      cacheTtl: cachePolicy.cacheTtl
    };
  } else {
    fetchOptions.cf = {
      cacheTtl: 0
    };
  }

  const response = await fetch(originUrl.toString(), fetchOptions);

  return rewriteResponse(response, cachePolicy);
}

function rewriteResponse(response, cachePolicy) {
  const newHeaders = new Headers(response.headers);

  newHeaders.set("Access-Control-Allow-Origin", CONFIG.ALLOW_ORIGIN);
  newHeaders.set("Access-Control-Allow-Methods", "GET,HEAD,POST,PUT,PATCH,DELETE,OPTIONS");
  newHeaders.set("Access-Control-Allow-Headers", "Content-Type,Authorization,X-API-Token");

  // 移除可能影响缓存的源站头
  newHeaders.delete("Set-Cookie");

  if (cachePolicy.cacheEnabled && cachePolicy.cacheTtl > 0) {
    newHeaders.set("Cache-Control", `public, max-age=${cachePolicy.cacheTtl}`);
  } else {
    newHeaders.set("Cache-Control", "no-store");
  }

  return new Response(response.body, {
    status: response.status,
    statusText: response.statusText,
    headers: newHeaders
  });
}

function addResponseHeaders(response, options) {
  const headers = new Headers(response.headers);

  headers.set("X-Edge-Cache", options.cacheStatus);
  headers.set("X-Cache-TTL", String(options.ttl));
  headers.set("Powered-By", "Cloudflare Workers");

  return new Response(response.body, {
    status: response.status,
    statusText: response.statusText,
    headers
  });
}

2. wrangler.toml 示例

如果你使用 Wrangler 部署,可以创建 wrangler.toml

name = "edge-cache-proxy"
main = "worker.js"
compatibility_date = "2024-11-01"

routes = [
  { pattern = "example.com/*", zone_name = "example.com" }
]

[vars]
ENVIRONMENT = "production"

如果你希望把源站地址和 Token 放到环境变量中,可以在 Worker 里改为读取:

const ORIGIN = env.ORIGIN;
const API_TOKEN = env.API_TOKEN;

然后通过 Wrangler 设置密钥:

wrangler secret put API_TOKEN

3. 部署命令

安装 Wrangler:

npm install -g wrangler

登录 Cloudflare:

wrangler login

部署 Worker:

wrangler deploy

部署完成后,可以通过下面的命令测试:

curl -I https://example.com/blog/test

如果看到类似 Header:

X-Edge-Cache: MISS

再次访问:

curl -I https://example.com/blog/test

如果变成:

X-Edge-Cache: HIT

说明边缘缓存已经生效。


十三、进一步降低成本的配置建议

1. 提高缓存命中率

缓存命中率越高,源站成本越低。

可以通过以下方式提高命中率:

  • 删除无意义 URL 参数;
  • 静态资源文件名加 hash;
  • 图片使用固定尺寸;
  • 减少随机参数;
  • 对公开页面设置合理缓存;
  • 对 API 做短时间缓存;
  • 避免源站频繁返回 Set-Cookie
  • 合理设置 Cache-Control

2. 不要缓存用户隐私内容

降低成本不能以安全为代价。

以下内容不要缓存:

  • 登录后页面;
  • 用户资料;
  • 订单详情;
  • 支付页面;
  • 后台管理页面;
  • 私有 API;
  • 带有用户身份 Cookie 的响应。

如果不确定某个页面是否可以缓存,默认不要缓存。


3. 对接口做分级缓存

不是所有 API 都应该完全不缓存。

可以分为三类:

公开配置类 API:缓存 1 分钟到 10 分钟
列表类 API:缓存 10 秒到 60 秒
用户相关 API:不缓存

例如:

/api/public/config       缓存 300 秒
/api/public/articles     缓存 60 秒
/api/user/profile        不缓存
/api/order/list          不缓存

短缓存对高并发场景很有用。即便只缓存 10 秒,也能显著降低瞬时峰值压力。


4. 对静态资源设置长缓存

推荐静态资源使用带 hash 的文件名,例如:

main.3f9a2d.js
vendor.91ac0.css
banner.1af92.webp

然后设置:

Cache-Control: public, max-age=31536000, immutable

这样浏览器和 Cloudflare 都可以长期缓存,极大减少重复请求。


5. 控制源站回源路径

如果源站暴露在公网,攻击者可能绕过 Cloudflare 直接访问源站 IP,导致防护失效。

建议:

  • 源站防火墙只允许 Cloudflare IP 访问;
  • 后台管理路径限制 IP;
  • 源站不要直接暴露真实域名;
  • 使用 Cloudflare Tunnel 隐藏源站;
  • 关闭不必要端口。

这样才能确保流量真正经过 Cloudflare,安全和成本优化才有效。


十四、Cloudflare 降本适合哪些业务?

Cloudflare 尤其适合以下场景:

1. 内容型网站

例如:

  • 博客;
  • 新闻;
  • 文档;
  • 教程;
  • 知识库。

这些页面可缓存比例高,使用 Cloudflare 后源站压力会明显下降。

2. 图片流量较大的网站

例如:

  • 图床;
  • 电商;
  • 社区;
  • CMS;
  • 作品集;
  • 用户头像系统。

通过图片缓存和格式优化,可以明显降低流量成本。

3. SaaS 官网和文档站

官网、帮助中心、API 文档、更新日志等内容大多可以静态化,适合 Cloudflare Pages + CDN。

4. 海外访问业务

Cloudflare 的全球节点对跨区域访问有明显帮助。对于面向全球用户的网站,可以减少自建全球加速的成本。

5. 中小团队和创业项目

中小团队最需要降低的不只是账单,还有运维成本。Cloudflare 把 DNS、证书、缓存、安全、边缘逻辑整合起来,可以让团队把精力放在产品上。


十五、Cloudflare 降本不适合哪些情况?

Cloudflare 不是万能的。以下情况需要谨慎:

  1. 强实时动态业务,几乎无法缓存;
  2. 大量长连接或特殊协议服务;
  3. 对数据驻留地区有严格合规要求;
  4. 需要复杂后端计算;
  5. 对 Workers CPU 时间要求很高;
  6. 所有请求都必须访问中心数据库;
  7. 缓存策略无法区分用户状态。

如果你的业务 90% 请求都是个性化动态请求,那么 Cloudflare 仍然可以提供安全和网络层优化,但降本效果可能不如静态内容明显。


十六、一个实际成本优化思路

假设你有一个内容网站:

日访问量:50 万 PV
图片请求:300 万次/天
API 请求:100 万次/天
源站服务器:4 核 8G
对象存储流量:每天 500GB

优化前:

  • 图片全部从对象存储流出;
  • HTML 每次都由后端渲染;
  • API 没有缓存;
  • 恶意爬虫直接打到源站;
  • 源站带宽经常跑满。

优化后:

  • 图片走 Cloudflare CDN 缓存;
  • 热门 HTML 页面缓存 10 分钟;
  • 公开 API 缓存 30 秒;
  • 登录接口启用 WAF 和 Challenge;
  • 静态前端迁移到 Cloudflare Pages;
  • 文件迁移到 R2;
  • 源站只允许 Cloudflare IP 访问。

结果可能是:

源站请求下降 60% ~ 90%
源站带宽下降 70% 以上
数据库压力明显降低
服务器规格可以下调
对象存储外网流量成本下降
安全攻击导致的异常账单减少
运维复杂度降低

具体节省多少取决于业务结构,但对于静态内容占比较高的网站,Cloudflare 的降本效果通常非常明显。


十七、总结

Cloudflare 降低成本的关键,不是简单地“把域名接入 Cloudflare”,而是充分利用它的边缘网络能力,把重复请求、静态资源、安全拦截和轻量逻辑尽量前置到边缘。

核心思路可以总结为:

能缓存的就缓存;
能静态化的就静态化;
能在边缘处理的就不要回源;
能用规则拦截的就不要让请求打到服务器;
能用 Pages/R2/Workers 解决的,就减少传统服务器依赖。

具体落地时,可以从以下步骤开始:

  1. 使用 Cloudflare DNS 接管域名;
  2. 开启 CDN 代理;
  3. 为静态资源设置长缓存;
  4. 对公开 HTML 页面启用缓存;
  5. 对公开 API 做短缓存;
  6. 使用 Workers 处理边缘逻辑;
  7. 使用 R2 承载大文件和图片;
  8. 用 WAF 拦截恶意流量;
  9. 用 Pages 部署前端项目;
  10. 限制源站只接受 Cloudflare 回源请求。

对于中小型网站、内容平台、SaaS 官网、文档站和图片服务来说,Cloudflare 是一套非常实用的降本工具链。它不一定能替代全部云基础设施,但可以把大量高频、重复、低价值的请求从源站剥离出去,让服务器、数据库和带宽只服务真正重要的业务逻辑。

目录结构
全文