浏览器缓存验证机制:Last-Modified 和 ETag
在 HTTP 协议中,缓存验证是提高 Web 性能的重要机制。Last-Modified 和 ETag 是两种主要的缓存验证器,它们帮助服务器和客户端确定资源是否需要重新传输。本文将深入探讨这两种机制的工作原理、优缺点以及它们的协同使用。
Last-Modified 工作原理
Last-Modified 是一个 HTTP 响应头,由服务器发送,表示资源在服务器上最后被修改的时间。
工作流程
第一次请求
- 客户端请求一个资源
- 服务器响应,并在响应头中包含
Last-Modified: <最后修改时间戳> - 浏览器将资源和
Last-Modified时间戳一同缓存
再次请求
- 客户端再次请求该资源时,会在请求头中携带
If-Modified-Since字段,其值为之前缓存的Last-Modified时间戳 - 服务器接收到请求后,会比较这个时间戳和资源当前的最后修改时间
- 如果两者相同:说明资源未被修改,服务器返回
304 Not Modified状态码,不含响应体,浏览器直接从缓存中加载资源 - 如果时间戳不同:说明资源已被修改,服务器返回
200 OK状态码,并发送新的资源内容
ETag 工作原理
ETag(Entity Tag) 是一个 HTTP 响应头,由服务器发送,是一个表示资源特定版本的唯一标识符。这个标识符通常是根据资源内容的哈希值生成的。
工作流程
第一次请求
- 客户端请求一个资源
- 服务器响应,并在响应头中包含
ETag: "<唯一标识符>" - 浏览器将资源和
ETag标识符一同缓存
再次请求
- 客户端再次请求该资源时,会在请求头中携带
If-None-Match字段,其值为之前缓存的ETag标识符 - 服务器接收到请求后,会比较这个标识符和资源当前版本生成的标识符
- 如果两者相同:说明资源未被修改,服务器返回
304 Not Modified状态码 - 如果标识符不同:说明资源已被修改,服务器返回
200 OK状态码,并发送新的资源内容
ETag 相比 Last-Modified 的优势
ETag 可以解决 Last-Modified 的几个重要局限性:
1. 时间精度问题
Last-Modified只能精确到秒:如果资源在短时间内(例如一秒内)被修改了多次,Last-Modified无法识别,会错误地认为资源没有变化ETag基于内容:无论修改频率如何,只要内容发生变化就能准确识别
2. 时间戳变化但内容不变
Last-Modified的问题:有时资源内容虽然没有变化,但因为某些原因(如重新部署、服务器处理)导致时间戳被修改,Last-Modified就会失效,强制客户端重新下载资源ETag的解决方案:由于基于内容生成,内容不变则标识符不变
3. 分布式系统同步问题
Last-Modified的挑战:在负载均衡的服务器集群中,一台服务器上资源的修改时间可能与另一台服务器不同步,导致缓存验证失败ETag的优势:基于内容的哈希值在所有服务器上都是一致的
Last-Modified 和 ETag 的协同使用
虽然 ETag 更精确,但它需要服务器额外计算资源的哈希值,这会带来一定的性能开销。因此,服务器通常会同时发送这两个验证器。
验证优先级机制
当客户端再次请求资源时,它会同时发送
If-Modified-Since和If-None-Match服务器优先使用
ETag进行验证:这是因为ETag提供了更强的验证,如果ETag匹配成功,服务器会直接返回304Last-Modified作为备用方案:只有在以下两种情况下,服务器才会退回到Last-Modified验证:- 客户端只发送了
If-Modified-Since字段(旧版浏览器或特殊情况) ETag验证失败,但服务器想使用Last-Modified作为备用方案
- 客户端只发送了
兼容性与健壮性
在大多数现代浏览器和服务器的实现中,If-None-Match(ETag) 字段的优先级高于 If-Modified-Since(Last-Modified)。这种机制确保了在保证验证精确性的同时,提供一个兼容性更强的后备方案,使得缓存策略更加健壮。
总结
Last-Modified 和 ETag 都是重要的 HTTP 缓存验证机制:
Last-Modified:简单高效,但存在时间精度和同步问题ETag:更精确可靠,但需要额外的计算开销- 协同使用:结合两者优势,提供既精确又兼容的缓存验证方案
合理使用这些缓存验证机制,能够显著提高 Web 应用的性能,减少不必要的网络传输,提升用户体验。