对于图片、JavaScript、CSS、字体、软件下载包以及视频等静态资源,一个网站的瓶颈往往并不是PHP、Node.js或者Java本身处理不过来,而是大量重复请求不断回到源站,反复消耗服务器出口带宽、CPU、磁盘I/O和连接资源。Google Cloud CDN的核心作用,就是把可以重复使用的HTTP响应缓存到Google全球边缘网络,让后续请求尽可能直接从靠近用户的缓存位置返回,从而减少回源请求和源站需要处理的数据量。Google目前的Cloud CDN通过外部Application Load Balancer或Classic Application Load Balancer提供服务,缓存内容可以来自Compute Engine、GKE、Cloud Run、Cloud Storage以及外部后端。
理解Cloud CDN,首先要改变一个容易产生误解的概念:它不是简单地在全球每个地区部署一台“Web服务器副本”。用户请求首先到达Google的全球边缘网络,外部Application Load Balancer负责前端接入和后端路由。如果对应后端启用了Cloud CDN,Google Front End会检查该请求对应的缓存。如果已经存在有效缓存对象,就可以直接从边缘返回给用户,不需要再次请求源站;如果没有命中,则需要向后端获取内容,再根据缓存规则决定是否保存。Google官方将前者称为cache hit,后者称为cache miss。
这个机制对源站压力的影响可以用一个更准确的公式理解。假设某个静态资源一天产生100万次请求,其中80万次可以直接由CDN缓存响应,只有20万次需要回源,那么从请求数量角度看,源站面对的这类请求减少了约80%。如果这些资源平均每次返回1MB,那么粗略计算,原本需要从源站发送约1TB的数据,缓存命中以后,源站实际承担的回源数据量可能降到约200GB。当然,这只是帮助理解的模型,并不是Cloud CDN保证的性能指标。实际结果还受到缓存键、TTL、请求头、Cookie、查询参数、缓存规则以及内容更新方式等因素影响。
因此,“Cloud CDN可以让源站压力降低90%”不能作为通用结论。一个拥有大量重复访问的热门图片或者软件下载文件,命中率可能非常高;一个每次URL都不同、带大量个性化参数的请求,即使响应内容看起来相同,也可能无法获得同样的缓存效果。CDN真正应该关注的不是宣传材料中的固定百分比,而是自己业务的cache hit ratio、cache fill、origin traffic以及请求量变化。
Cloud CDN的缓存行为主要由缓存模式和HTTP缓存头共同决定。Google目前提供CACHE_ALL_STATIC、USE_ORIGIN_HEADERS和FORCE_CACHE_ALL三种缓存模式。CACHE_ALL_STATIC是默认模式,会自动缓存符合静态内容条件的成功响应,同时尊重private和no-store等不可缓存指令;USE_ORIGIN_HEADERS要求源站通过有效的缓存头明确告诉CDN哪些响应可以缓存;FORCE_CACHE_ALL则会缓存所有成功内容并忽略源站的private或no-store指令,因此只能在确认后端不提供私有或用户个性化内容时使用。
对于一个普通网站,最基础的HTTP缓存控制通常可以从Cache-Control开始。例如:
Cache-Control: public, max-age=3600
这表示响应可以被公共缓存使用,并允许客户端缓存一小时。但对于Cloud CDN,还可以使用CDN-Cache-Control针对CDN单独设置缓存策略,而不必完全影响浏览器缓存行为。Google官方文档明确区分了标准Cache-Control和面向Cloud CDN的CDN-Cache-Control。
对于经常更新的新闻网站,这一点尤其重要。假设网站首页图片使用固定URL /images/home.jpg,文章更新以后又覆盖了同一个文件,那么CDN可能仍然保存旧版本。与其每次更新都等待TTL自然过期,更成熟的方法通常是给静态资源使用版本化文件名,例如app.20260908.js或者logo-v3.webp。新版本使用新的URL,自然形成新的缓存对象;旧版本则可以继续留在边缘缓存中直到过期。这通常比频繁执行大范围缓存清除更加稳定。
Cloud CDN也支持缓存失效操作。当某个对象已经进入缓存,但业务要求在正常TTL结束之前立即让它失效,可以执行cache invalidation。Google目前支持按照主机名、URL路径以及缓存标签等条件进行失效匹配。失效之后,下一次请求会重新从后端填充缓存。
不过,缓存失效并不是越频繁越好。如果网站每发布一篇文章就把整个站点的缓存全部清除,那么大量边缘节点可能在短时间内同时回源,刚刚通过CDN建立起来的源站减压效果又被抵消。大型网站更适合通过精确URL、版本化资源或者缓存标签控制失效范围,而不是动不动执行全站purge。
Google Cloud Storage是Cloud CDN非常适合的一种静态内容源。Google提供backend bucket,把Cloud Storage bucket作为Application Load Balancer的后端,再启用Cloud CDN。官方文档明确将backend bucket定位为适合图片、视频等静态内容的方案;如果后端提供的是动态HTTP服务,则通常使用backend service。
这意味着一个网站完全可以把图片、CSS、JavaScript、PDF、软件下载包等静态文件放进Cloud Storage,而动态PHP、Node.js或者其他应用服务继续运行在Compute Engine、GKE、Cloud Run甚至Google Cloud之外。外部Application Load Balancer根据URL Map决定请求应该进入哪个后端,Cloud CDN负责其中可缓存内容的边缘分发。Google当前也支持通过Internet NEG连接Google Cloud之外的外部源站,因此并不是只有迁移到Google Cloud的服务器才能使用Cloud CDN。
对于已经运行在传统服务器上的网站,这一点非常有价值。假设一个新闻网站目前有一台PHP服务器,文章HTML由PHP动态生成,图片和CSS也由同一台服务器提供。那么最简单粗暴的做法是让所有请求都回源。更合理的架构则可以把图片、CSS、JavaScript等高重复资源交给CDN,而登录、后台管理、数据库查询、个性化页面以及其他不能公开缓存的请求继续回到源站。
这时必须特别注意缓存私有数据的问题。用户资料、购物车、订单、后台页面以及包含个人身份信息的响应,不能因为“性能不好”就强制缓存。尤其是FORCE_CACHE_ALL会忽略源站的private和no-store指令,如果后端同时提供用户私有内容,就可能造成严重的数据泄露。Google官方也明确警告,这种模式可能导致缓存用户可识别的私有内容,因此只应该用于不包含私有或动态内容的后端,例如适合静态资源的Cloud Storage bucket。
Cloud CDN还需要考虑Cache Key。服务器收到两个URL并不意味着CDN一定把它们当成同一个缓存对象。查询参数、主机、路径以及其他影响响应内容的请求特征都可能影响缓存行为。如果一个网站把无意义的随机参数不断附加到静态资源URL上,就可能人为制造大量不同的缓存对象,使原本应该具有很高命中率的资源变成低命中率。
因此,缓存命中率不是CDN本身一个孤立的性能数字,而是应用URL设计和缓存策略共同产生的结果。一个优秀的静态资源系统通常会保持稳定URL或者采用内容版本化URL,避免不必要的Query String变化,同时给不同类型资源设置符合生命周期的TTL。
例如网站Logo可能几个月甚至几年才变化一次,JavaScript和CSS可以通过版本化文件名实现长期缓存,而新闻文章图片可能需要根据编辑流程设置相对短一些的TTL。软件下载包或者版本化静态资源则可能适合更长的缓存生命周期。不存在一个适合所有资源的统一max-age。
缓存穿透也是需要考虑的问题。假设攻击者不断请求不存在的/images/random-xxxxx.jpg,如果每个请求最终都必须回源,CDN并不会自动消除源站压力。对于这种情况,Cloud CDN支持negative caching,可以缓存部分404、301、302等响应,从而减少重复的无效回源请求。Google当前允许针对不同HTTP状态码设置negative caching TTL,并且最大TTL为1800秒。
不过,negative caching同样需要谨慎。例如某个新闻网站刚刚发布文章,文章图片暂时不存在,系统返回404。如果把404缓存时间设置过长,图片随后上传以后,用户仍然可能在一段时间内继续得到缓存的404。因此,负缓存应该根据资源生成流程和错误类型设置,而不是简单地把所有404缓存很久。
视频和大文件分发则是另一种场景。对于热门视频,如果大量用户请求相同的视频分片,CDN可以显著减少源站重复传输。但如果视频采用非常细碎、个性化程度高或者每个用户URL都不同的分片策略,缓存效果可能完全不同。这里仍然应该通过实际的缓存命中率和回源流量验证,而不能直接套用某个“视频可以节省90%带宽”的固定数字。
安全性也不能被CDN缓存逻辑替代。对于私有视频、下载链接或者需要用户授权才能访问的资源,可以使用Cloud CDN提供的Signed URLs或者Signed Cookies等机制,让边缘节点在提供内容之前验证访问凭证。Google也支持对Cloud Storage等后端配置私有访问,使bucket不需要直接暴露给用户,而由Cloud CDN和负载均衡链路提供访问入口。
另一个容易被忽略的问题是,CDN降低的是源站处理压力,并不意味着源站可以被完全删除。动态业务、数据库、登录认证、订单、评论、搜索以及个性化页面仍然需要后端系统提供服务。CDN只是把“重复的、可缓存的HTTP响应”从源站处理路径中拿走。对于一个新闻网站,文章HTML是否适合缓存还要看页面是否包含用户个性化内容;但图片、CSS、JavaScript、字体和其他版本化静态资源通常更容易获得稳定的缓存收益。
因此,判断Cloud CDN到底能够减少多少源站压力,最可靠的方法不是使用一个固定百分比,而是部署以后直接测量。至少应该观察CDN cache hit ratio、origin request rate、origin egress bytes、cache fill、响应延迟以及不同URL类别的缓存表现。如果一个站点原本每天有100GB静态资源回源流量,启用CDN以后只有25GB需要从源站获取,那么可以很直观地看到静态资源回源流量下降约75%。但如果总流量中只有20%属于可缓存静态资源,那么即使这些静态资源100%命中,整个网站的源站负载也不可能下降80%。
这个区别对于实际架构设计非常重要。假设一个网站每天产生1TB总流量,其中700GB是图片、CSS、JavaScript等高度可缓存内容,300GB是动态API和HTML。如果静态资源有90%的回源减少,那么整个源站总流量大约只减少630GB,剩余动态流量仍然存在。换句话说,CDN的收益应该按照“可缓存流量 × 实际缓存命中率”计算,而不是直接把CDN命中率当成整个网站的源站减压比例。
Cloud CDN真正适合解决的是大量用户重复请求相同内容的问题。它不能自动修复数据库性能,也不能解决PHP代码执行缓慢、Redis阻塞、API响应慢或者数据库连接池耗尽。如果网站的瓶颈是动态请求每次都需要查询数据库,那么把CDN打开并不会神奇地让数据库变快。相反,如果瓶颈来自几十万用户反复下载相同图片、CSS、JavaScript或者视频文件,那么CDN就可能直接改变源站的网络和请求负载结构。
对于一个典型的全球网站,可以把外部Application Load Balancer作为统一入口,把Cloud CDN放在可缓存的公共资源路径上,静态文件使用Cloud Storage或者其他适合的后端,动态业务继续进入应用服务器。通过URL Map将不同路径分配到不同后端,再根据资源生命周期设置缓存模式和TTL。这样做比简单地“整个网站开启CDN”更加容易控制,也更不容易把私有数据误缓存到公共边缘。
Cloud CDN最终解决的不是“服务器太慢”这么简单的问题,而是重复请求应该在哪里完成的问题。如果同一张图片被全球几十万用户请求,最没有效率的方式就是让几十万次请求都回到同一台源站服务器;如果内容可以在边缘安全地复用,那么第一次请求负责填充缓存,后续请求就可以直接利用已经存在的副本。源站真正减少的,是那些本来没有必要重复执行的网络传输和内容获取工作。
因此,评价Google Cloud CDN最应该看的不是“开启以后理论上能快多少”,而是三个实际数字:有多少流量可以缓存,有多少请求命中缓存,以及还有多少请求最终回到了源站。只有把这三个数字和源站CPU、网络出口、请求量以及响应时间放在一起观察,才能知道CDN究竟为网站省下了多少资源。对于静态资源占比高、访问用户分布广、热门内容重复请求明显的网站,Cloud CDN可能带来非常明显的源站减压;对于高度个性化、每次请求内容都不同的应用,它的作用则主要集中在那些真正可以缓存的公共资源上。
Google Cloud CDN 怎么使用,静态内容缓存能够减少多少源站压力
喜欢这篇报道?
使用下面的功能,方便以后继续阅读和分享 MNewsTV
关于文章收藏
收藏不需要注册帐号,收藏信息仅保存在当前浏览器中。
删除收藏请进入「我的收藏」进行管理。
捐助(Paypal): https://www.paypal.me/observeccp 订阅中国观察电报 Telegram : https://t.me/s/ObserveCCP