Understanding HTTP Cache-Control Protocol and Its Applications
HTTP Cache‑Control defines how browsers, proxies, and origin servers coordinate caching through directives like public, private, max‑age, no‑store, and revalidation, enabling developers to control freshness, reduce server load, save bandwidth, and improve user experience while avoiding stale‑content issues.
缓存(Cache)是临时存储数据的地方,称为缓存池;其中存放的数据称为缓存。当用户需要数据时,首先在缓存中查找,命中则直接使用,未命中则回源到其他数据源。
缓存的本质是用空间换时间,以临时存储的数据暂时代替数据源中读取最新的数据。以喝水为例:使用水杯(缓存池)装水(缓存)虽然水会变凉(牺牲实时性),但解决了反复去水龙头的问题,减少水洒出,更优雅。对应的系统优势包括降低系统压力、节省资源消耗、优化用户体验。
在网络场景中,网络不稳定和服务器高并发易导致瓶颈,HTTP缓存技术能有效缓解这些问题。
HTTP缓存协议是客户端、代理服务器和源服务器之间遵守的规则。类似于客户端与服务器就新机型发布进行沟通:数据部分是机型内容,协议部分是约定的提问与回答方式。双方通过遵循协议实现高效交互。
HTTP请求由状态行、请求头和消息主体三部分组成;响应由状态行、响应头和响应正文组成。请求头和响应头即为我们所说的“头部信息”或“消息头”,用于传递元数据。
常见请求头字段包括: Cookie (携带cookie信息)、 User-Agent (携带UA信息)、 Referer (标识来源)、 Content-Length (标识请求数据大小)。
常见响应头字段包括: server (服务器名称)、 date (数据时间)、 Content-Length (响应数据长度)、 Location (重定向时的地址)。
HTTP缓存的核心是 Cache-Control 指令,放在消息头中进行控制。指令可分为可缓存性控制、缓存有效性控制和其他控制三类。
可缓存性控制: public (任何对象可缓存)、 private (仅单用户可缓存,代理不可缓存)、 no-cache (使用前必须向原始服务器验证)、 no-store (不存储任何内容,即不使用缓存)。
缓存有效性控制: max-age= (设置缓存最大周期,超过则过期,单位秒,相对于请求时间)、 s-maxage= (覆盖 max-age 或 Expires ,仅适用于共享缓存)、 max-stale[=] (客户端愿意接收已过期资源,可设置可选秒数上限)、 min-fresh= (客户端希望获取在指定秒数内仍保持最新的资源)、 stale-while-revalidate= (客户端接受陈旧响应并在后台异步检查新响应)、 stale-if-error= (若新检查失败则接受陈旧响应)。
其他控制: must-revalidate (资源过期前必须向原始服务器验证才能使用)、 proxy-revalidate (与 must-revalidate 作用相同,仅适用于共享缓存)、 no-transform (禁止代理对资源进行转换,如修改 Content-Encoding 、 Content-Type 等)、 only-if-cached (客户端只接受已缓存的响应,不向源服务器检查更新)。
多个指令可同时使用;若出现矛盾(如 no-store 与 max-age 同时出现),则按优先级执行, no-store 优先。
为了验证这些指令的实际效果,作者搭建了静态资源服务器(源服务器)和代理服务器,均基于 Windows + Nginx。通过修改 Cache-Control 取值并观察浏览器和代理的 ngx-cache-status (HIT/EXPIRED)等,得出以下结论:
未添加任何 Cache-Control 时,相当于默认 public ,浏览器和代理均可缓存。
添加 max-age=20 后,代理服务器会忽略自身配置的缓存时长,直接使用源服务器下发的 max-age 作为缓存时长;在20秒内持续 HIT ,20秒后变为 EXPIRED ,此时代理将请求透传给源服务器进行验证。
在Android WebView中(无刷新按钮),若未手动刷新,则在 max-age 限定时间内不会发起网络请求,直接使用本地缓存;超过时间后会发送带有 If-None-Match 和 If-Modified-Since 的请求,服务器返回 304 则继续使用缓存。
实际案例:某线上商城未配置任何 cache-control ,默认 public 导致WebView长期使用本地缓存,前端发布新版后客户端无法及时更新。开发者曾通过手动拼接时间戳强制失效,而只要在响应头中加入 no-cache 或合适的 max-age 即可解决。
服务器判断缓存是否有效依赖客户端带回的 ETag 和 Last-Modified 。若这些字段不匹配,则返回 200 和最新数据;若匹配,则返回 304 。若其中任一字段缺失,校验将存在风险。
在请求端,浏览器刷新按钮实际上在请求头中加入 Cache-Control: max-age=0 ,告知服务器验证本地缓存是否过期。其他常用请求端指令还有 no-cache (要求向源服务器发起请求)、 no-store (本地不缓存任何文件)、 max-stale (愿意接受过期资源)、 min-fresh (希望获取不久将更新的资源)、 no-transform (禁止代理转换资源)、 only-if-cached (仅使用代理已有缓存)。
总之,HTTP的 Cache-Control 协议清晰定义了客户端、代理服务器和源服务器三者之间的缓存交互逻辑。掌握这些规则有助于前端开发者在排查缓存相关问题时快速定位,并能与运维协商合适的缓存策略,从而降低服务器压力、节省流量、提升网页打开速度。
vivo Internet Technology
Sharing practical vivo Internet technology insights and salon events, plus the latest industry news and hot conferences.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.