Fastly VCL 配置入门与实战

Fastly VCL 配置指南

本文将教你如何从零写出可上线的 Fastly VCL,帮你解决”图形规则跑不通、必须写 VCL 又不知道从哪开始”的问题。如果你的业务对边缘控制的精细度要求很高,例如需要按 Cookie 分流、按地区改写 TTL、把日志实时推到 SIEM(Security Information and Event Management,安全信息与事件管理平台),那么 Fastly VCL 配置 是少有的能完全暴露底层逻辑的方案。Fastly 基于开源的 Varnish 自研,控制语言是 VCL(Varnish Configuration Language),相比图形化规则更灵活也更陡峭。整篇指南将覆盖请求改写、缓存键控制、日志推送与故障排查这四个核心场景。

一、Fastly VCL 适合什么团队

Fastly 的定价不算便宜,最低起步约每月 50 美元起,流量超出部分按 GB 计费。它的核心价值不是”最便宜的 CDN”,而是把边缘节点的请求处理过程几乎全部开放给你写代码。判断是否值得切换到 Fastly,可以参考三点:

  • 逻辑复杂度:需要在边缘做 5 条以上规则,且其中 2 条涉及 Cookie 或 Header 二次计算。
  • 可观测性需求:要求秒级日志、能按字段路由到不同接收端。
  • 回源安全要求:源站只允许 Fastly 出口 IP 直连,需要在 VCL 中做 token 校验。

如果你的源站布在跨境链路上,VCL 的 backend 配置能精确指定回源节点。回源主机的选型可参考 WordPress 香港主机选购指南云服务器选购指南 中的网络章节。Fastly 在亚太节点的覆盖较好,但仍不包含中国大陆,国内访问取决于回源主机的出口质量。

二、Service 与 VCL 文件结构

Fastly 控制台的最小工作单元是 Service。一个 Service 对应一组域名、一组 backend、若干 VCL Snippet 或一份 Custom VCL。新建 Service 时建议:先用 UI 配置基础 backend 与 domain,发布到 Staging,再逐步把规则切换成 VCL。

一份典型的 Custom VCL 骨架包含以下几个 subroutine(子例程):

sub vcl_recv {
  #FASTLY recv

  if (req.http.User-Agent ~ "(?i)bot") {
    set req.http.X-Is-Bot = "1";
  }

  if (req.url ~ "^/api/") {
    set req.backend = F_api_origin;
  } else {
    set req.backend = F_web_origin;
  }
}

sub vcl_fetch {
  #FASTLY fetch
  if (beresp.status == 200 && req.url ~ "\.(jpg|png|webp|css|js)$") {
    set beresp.ttl = 7d;
  }
}

sub vcl_deliver {
  #FASTLY deliver
  set resp.http.X-Cache = if(fastly_info.state ~ "HIT", "HIT", "MISS");
}

#FASTLY recv 这种注释非常关键:它告诉 Fastly 在该位置注入官方默认逻辑(如 PURGE 支持、Cluster 流转)。漏掉会导致集群内多节点协作异常。

三、VCL 实战:自定义缓存键与路由

边缘缓存键(cache key)决定哪些请求会被认为是”同一个对象”。默认包含 URL 与 Host,很多场景需要加入额外维度,例如在 vcl_hash 中根据 Accept-Encoding 分别给 Brotli、Gzip、未压缩三种状态加入不同后缀,确保相同 URL 在三种压缩状态下分别缓存,避免把 Brotli 内容发给不支持的旧客户端。

路由场景常见需求是把移动端请求和桌面端分流,可在 vcl_recv 中根据 User-Agent 设置 X-Device-Type,再把该 Header 加入 cache key,源站根据它返回不同模板。Fastly 还提供 client.geo.country_code 内置变量,可直接做地区分流而无需自己解析 IP。

四、日志推送与可观测性

Fastly 的实时日志(Real-Time Log Streaming)是它对比传统 CDN 的重要优势。Service → Logging 中可以添加多种接收端:S3、Azure Blob、Datadog、Splunk、Sumo Logic、HTTP endpoint 等。

日志格式用 VCL 在 vcl_log subroutine 中定义,把 timestamp、status、cache state、client ip、user agent 等字段拼成 JSON 串,再选择 HTTPS JSON 接收端,下游 SIEM 几乎可以零改造接入。需要注意:日志格式必须为合法 JSON,VCL 字符串拼接错误会导致整批日志被丢弃,但 Fastly 不会主动告警,建议先用 Logtail 等带 schema 校验的接收端验证一周再切到正式 SIEM 系统。

实际投入使用时,日志的字段设计应该围绕”事后排障最常用的几个维度”来选:故障时间窗口、问题路径、回源结果、客户端地区。把这些字段提前固化好,避免事故发生时再临时改 VCL。日志保留策略也要明确,例如 7 天热查询、30 天冷存、90 天合规归档,能在控制成本的同时保留足够的回溯能力。

五、Fiddle 与 Stage 发布

Fastly 提供 fiddle.fastly.dev 这种沙箱环境,可在浏览器里写 VCL、模拟 client 请求、观察 backend 响应。强烈建议任何超过 20 行的 VCL 改动先在 Fiddle 跑通再提交到正式 Service。

正式 Service 的 Stage 流程:

  • Clone:把当前激活版本复制为新版本。
  • Edit:在新版本上修改 VCL、backend、settings。
  • Validate:Fastly 自动检查语法,未通过不能激活。
  • Activate:激活后 5 到 10 秒生效到全球节点;如发现问题可立即 Roll Back 到上一版本。

对于 WordPress 等动态站点,VCL 调优后建议同时检查源站缓存配合,可参考 WordPress W3 Total Cache 调优实战 中关于浏览器缓存与边缘缓存的协作章节。更多 WordPress 边缘加速实战可在 WordPress 分类 下查阅相关内容。

六、常见故障排查

VCL 上线后的高频问题与排查方向:

  • TTL 总是 0 或极短:通常源站返回 Cache-Control: privateSet-Cookie,Fastly 默认不缓存带 Set-Cookie 的响应,需要在 vcl_fetch 中显式 unset beresp.http.Set-Cookie
  • PURGE 不生效:检查 Surrogate-Key 是否在源站正确设置,VCL 中 purge 命令需带正确 key 才能精确清缓存。
  • 某些节点命中率异常低:可能是 Shielding 配置缺失,开启 Origin Shielding 后会显著改善。
  • 回源 502:先用 curl -H "Host: yourdomain.com" https://origin.ip 直连源站,再用 美国 VPS 部署教程 中的 MTR 检查 Fastly POP 到源站的链路。
  • 日志条目缺失:先在 Fastly UI 的 Live Stats 看请求是否到达,再去接收端查;多半是日志格式 JSON 不合法导致下游丢弃。

七、Snippet 拆分与团队协作

实际生产中很少把所有 VCL 写成一份大文件,更常见的做法是按场景拆分 Snippet:缓存键单独一份、日志格式单独一份、地区路由单独一份。每份 Snippet 都可以在控制台单独启用或停用,问题排查时也更容易隔离影响范围。建议把每份 Snippet 同步到 Git 仓库的 vcl/snippets/ 目录,让团队既能享受 Fastly 的快速回滚,又能保留完整的变更历史。

总结与建议

Fastly VCL 配置 适合需要在边缘做深度定制的中大型团队,初学者建议先从一个 20 行以内的 Snippet 起步,例如自定义 cache key 或路径级 TTL,跑稳后再扩展到日志推送与 backend 路由。如果你需要把 Fastly 与已有源站组合,可以考虑先用 VCL 接管缓存与日志层,源站继续承担业务逻辑,迁移更可控。整体来看,VCL 的学习成本不低但回报明确,能让你的边缘策略真正按业务需要发挥作用而不是被规则模板限制。再加上 Fastly 在 Staging 与 Roll Back 上的工程友好度,让团队可以以较小的风险进行边缘逻辑实验,逐步沉淀属于自己业务的 VCL 模板库。

发表评论