Caching
通过重复使用先前提取的资源,可以显着提高网站和应用程序的性能。Web缓存减少了延迟和网络流量,从而减少了显示资源表示所需的时间。通过使用HTTP缓存,网站变得更加快速响应。
不同种类的缓存
缓存是一种技术,可存储给定资源的副本,并在请求时将其返回。当Web缓存在其存储中具有请求的资源时,它拦截该请求并返回其副本,而不是从原始服务器重新下载。这实现了几个目标:它减轻了不需要为所有客户端服务的服务器的负载,并且通过更接近客户端来提高性能,即,将资源传回的时间更短。对于一个网站来说,它是实现高性能的一个重要组成部分。另一方面,它必须正确配置,因为并非所有资源都永远保持一致:仅在资源缓存更改时才缓存资源,这一点非常重要。
有几种缓存:这些缓存可以分为两大类:私有缓存或共享缓存。甲共享高速缓存是由一个以上的用户存储用于重用响应的高速缓存中。一个私有缓存专用于单个用户。该页面主要讨论浏览器和代理缓存,但也有部署在Web服务器上的网关缓存,CDN,反向代理缓存和负载平衡器,以提高网站和Web应用程序的可靠性,性能和扩展性。
私人浏览器缓存
专用缓存专用于单个用户。您可能已经在浏览器的设置中看到“缓存”。浏览器缓存保存用户通过HTTP下载的所有文档。该缓存用于使访问文档可用于后退/前进导航,保存,以源代码查看等,而无需额外访问服务器。它同样改进了缓存内容的离线浏览。
共享代理缓存
共享缓存是一个缓存,用于存储将被多个用户重用的响应。例如,ISP或贵公司可能已将Web代理设置为其本地网络基础架构的一部分,以便为许多用户提供服务,从而使常用资源多次重复使用,从而减少网络流量和延迟。
缓存操作的目标
HTTP缓存是可选的,但通常需要重新使用缓存资源。但是,常见的HTTP缓存通常仅限于缓存响应GET
并可能拒绝其他方法。主缓存键由请求方法和目标URI组成(通常只有URI被使用,因为只有GET请求才是缓存目标)。常见的缓存条目形式是:
- 检索请求的成功结果:
200
对GET
包含诸如HTML文档,图像或文件等资源的请求的(确定)响应。
- 永久重定向:a
301
(永久移动)响应。
- 错误响应:一个
404
(未找到)结果页面。
- 不完整的结果:(
206
部分内容)响应。
- 除了
GET
定义适合用作缓存键的东西之外的其他响应。
如果请求是内容协商的目标,则高速缓存条目也可能由多个由辅助键区分的存储响应组成。有关更多详细信息,请参阅Vary
下面的标题信息。
控制缓存
Cache-control
头
Cache-Control
HTTP / 1.1通用头字段用于指定在请求和响应缓存机制的指令。使用这个头文件可以用它提供的各种指令来定义你的缓存策略。
根本不存在缓存存储
缓存不应该存储有关客户端请求或服务器响应的任何内容。一个请求被发送到服务器,并且每次都会下载一个完整的响应。
Cache-Control: no-store Cache-Control: no-cache, no-store, must-revalidate
没有缓存
在释放缓存副本之前,缓存会将请求发送到原始服务器进行验证。
Cache-Control: no-cache
私人和公共缓存
“public”指令表明响应可能被任何缓存缓存。如果页面具有HTTP身份验证或响应状态代码通常不可缓存的页面现在应该被缓存,这可能很有用。另一方面,“私有”表示该响应仅适用于单个用户,并且不得由共享缓存存储。在这种情况下,私人浏览器缓存可能会存储响应。
Cache-Control: privateCache-Control: public
终止
这里最重要的指令是“ max-age=<seconds>
”,这是资源被认为是最新的最大时间量。相反Expires
,这个指令是相对于请求的时间而言的。对于应用程序中不会更改的文件,通常可以添加积极的缓存。这包括静态文件,例如图像,CSS文件和JavaScript文件。
有关更多详细信息,另请参阅下面的“新鲜度”部分。
Cache-Control: max-age=31536000
验证
使用“ must-revalidate
”指令时,缓存必须在使用前验证陈旧资源的状态,不应使用过期资源。有关更多详细信息,请参阅下面的验证部分。
Cache-Control: must-revalidate
Pragma
头
Pragma
是一个HTTP / 1.0标头,它是未指定的HTTP响应,因此不为普通HTTP / 1.1的可靠替换Cache-Control
首部,虽然它不表现一样Cache-Control: no-cache
,如果Cache-Control
在请求中省略报头字段。使用Pragma
仅适用于HTTP / 1.0客户端的向后兼容性。
更新度
一旦资源存储在缓存中,理论上它可以永久存储在缓存中。缓存具有有限的存储空间,因此项目会定期从存储中删除。这个过程被称为缓存逐出。另一方面,服务器上的一些资源可能会发生变化,所以应该更新缓存。由于HTTP是客户端 - 服务器协议,因此当资源发生更改时,服务器无法联系缓存和客户端; 他们必须传达资源的到期时间。在这个到期时间之前,资源是新鲜的 ; 到期后,资源已过时。驱逐算法经常使新资源超过陈旧的资源。请注意,陈旧的资源不会被驱逐或忽略; 当缓存接收到过时资源的请求时,它会将此请求转发给a,If-None-Match
以检查它是否实际上仍然是新的。如果是这样,服务器返回304
(未修改)标题,而不发送请求资源的主体,节省一些带宽。
以下是使用共享高速缓存代理的此过程示例:
更新度使用寿命是根据多个标题计算得出的。如果Cache-control: max-age=N
指定了“ ”标题,则新鲜度生存期等于N.如果该标题不存在(通常是这种情况),则检查Expires
标题是否存在。如果Expires
存在标题,则其值减去Date
标题的值确定新鲜度生存期。最后,如果两个标题都不存在,请查找Last-Modified
标题。如果存在这个头部,则缓存的新鲜度寿命等于Date
头部的值减去头部的值Last-modified
除以10。
到期时间计算方法如下:
expirationTime = responseTime + freshnessLifetime - currentAge
responseTime
根据浏览器收到响应的时间在哪个位置?
资源已被修改
我们使用缓存资源越多,网站的响应能力和性能就越好。为了优化这一点,良好的做法建议尽可能在将来设定到期时间。对于定期更新或经常更新的资源,这是可能的,但对于很少和不经常更新的资源而言存在问题。他们是从缓存资源中受益最多的资源,但这使得它们很难更新。这是包含并链接到每个网页的技术资源的典型代表:JavaScript和CSS文件很少更改,但当它们更改时,您希望它们能够快速更新。
Web开发人员发明了一种Steve Sounders称之为改变的技术。不经常更新的文件以特定的方式命名:在他们的URL中,通常在文件名中添加修订版(或版本)号。这样,每一个这个资源的新版本都被认为是永远不会有的资源变化并且可能在将来有很长的到期时间,通常是一年甚至更长。为了获得新的版本,所有到它们的链接都必须改变,这就是这种方法的缺点:通常由Web开发人员使用的工具链来处理额外的复杂性。当不经常变化的资源发生变化时,它们会对经常变化的资源产生额外的变化。当这些被读取时,其他的新版本也被读取。
这种技术还有一个额外的好处:同时更新两个缓存资源不会导致一种资源的过时版本与另一种资源的新版本结合使用的情况。当网站具有相互依赖的CSS样式表或JS脚本时,这是非常重要的,即它们相互依赖,因为它们引用相同的HTML元素。
添加到revved资源中的修订版本不需要像1.1.3这样的经典修订字符串,或者甚至是单调增长的一组数字。它可以是防止碰撞的任何东西,比如散列或日期。
缓存验证
当用户按下重新加载按钮时,触发重新验证。如果缓存的响应包含“ Cache-control: must-revalidate
”标题,它也会在正常浏览下触发。另一个因素是首Advanced->Cache
选项面板中的缓存验证首选项。每次加载文档时都有一个强制验证的选项。
当达到缓存文档的到期时间时,它将被验证或再次提取。验证只有在服务器提供强验证器或弱验证器时才会发生。
ETags
ETag
响应报头是不透明到所述-用户代理 可以使用作为强验证值的。这意味着HTTP用户代理(如浏览器)不知道该字符串代表什么,也无法预测其价值。如果ETag
头部是资源响应的一部分,则客户端可以If-None-Match
在未来请求的头部中发出- 以验证缓存的资源。
的Last-Modified
响应报头可以被用作弱验证器。它被认为是微弱的,因为它只有1秒的分辨率。如果Last-Modified
标题出现在响应中,则客户端可以发出If-Modified-Since
请求标头来验证缓存的文档。
当发出验证请求时,服务器可以忽略验证请求并以普通方式进行响应200
OK
,也可以返回304
Not Modified
(使用空的主体)来指示浏览器使用其缓存副本。后一个响应还可以包括更新缓存文档到期时间的标题。
变化的反应
该Vary
HTTP响应头决定如何满足未来的请求头,以决定一个缓存的响应是否可以使用,而不是请求从源服务器一个新的一个。
当缓存接收到具有Vary
头字段的缓存响应可以满足的请求时,它不得使用该缓存的响应,除非头中指定的所有头字段Vary
在原始(缓存)请求和新请求中都匹配。
例如,这对于动态提供内容非常有用。使用Vary: User-Agent
标题时,缓存服务器在决定是否从缓存中提供页面时应考虑用户代理。如果您向移动用户提供不同的内容,它可以帮助您避免缓存可能会错误地将您的网站的桌面版本提供给移动用户。此外,它可以帮助Google和其他搜索引擎发现页面的移动版本,并且可能会告诉他们没有打算使用Cloaking。
Vary: User-Agent
由于User-Agent
移动和桌面客户端的标头值不同(“变化”),缓存将不会用于将移动内容错误地提供给桌面用户,反之亦然。
扩展内容
- RFC 7234:超文本传输协议(HTTP / 1.1):缓存
- 缓存教程 - 马克诺丁汉
- HTTP缓存 - Ilya Grigorik
- RedBot,一种检查与缓存相关的HTTP标头的工具。