问小白 wenxiaobai
资讯
历史
科技
环境与自然
成长
游戏
财经
文学与艺术
美食
健康
家居
文化
情感
汽车
三农
军事
旅行
运动
教育
生活
星座命理

HTTP缓存详解:强制缓存与协商缓存的工作原理

创作时间:
作者:
@小白创作中心

HTTP缓存详解:强制缓存与协商缓存的工作原理

引用
CSDN
1.
https://m.blog.csdn.net/qq_62097431/article/details/144407956

HTTP缓存是提升Web应用性能的关键技术之一。通过合理利用缓存机制,可以显著减少网络请求,降低服务器负载,提升用户访问速度。本文将详细介绍HTTP缓存的基本概念、实现方式以及具体的工作原理。

HTTP缓存概述

简单理解,对于一些具有重复性的HTTP请求,比如每次请求得到的数据都一样的,我们可以把这对「请求-响应」的数据都缓存在本地,那么下次就直接读取本地的数据,不必再通过网络获取服务器的响应。这样的话,HTTP/1.1的性能会得到显著提升。

为了避免发送HTTP请求,HTTP设计者早在协议中就加入了缓存技术的支持。HTTP协议的头部包含了许多针对缓存的字段。HTTP缓存主要有两种实现方式:强制缓存和协商缓存

强制缓存的核心在于浏览器判断缓存是否过期,如果未过期则直接使用本地缓存,决策权在浏览器端。而协商缓存则需要客户端和服务端进行交互,由服务端决定是否使用缓存。

HTTP缓存的概念与重要性

  • 概念:HTTP缓存是一种用于存储HTTP请求响应的机制,目的是减少相同请求的重复网络传输,从而提高性能和减少带宽消耗。当客户端(如浏览器)请求一个资源时,它可以首先检查本地缓存中是否已经存在该资源的有效副本。如果存在,就可以直接使用缓存副本,而无需再次向服务器发送请求。

  • 重要性:在现代网络应用中,HTTP缓存能够显著提升用户体验。例如,在浏览网页时,浏览器可以缓存网页中的图片、脚本文件、样式表等静态资源。当用户再次访问同一网页或者浏览相关网页(使用相同的资源)时,浏览器可以快速从缓存中获取这些资源,大大缩短了页面加载时间。同时,对于服务器来说,缓存机制可以减轻服务器的负载,因为减少了对相同资源的重复请求处理。

缓存的位置与类型

  • 浏览器缓存:这是最常见的缓存位置,位于客户端浏览器中。浏览器会根据一定的规则将之前获取的资源存储在本地缓存中。不同的浏览器有不同的缓存存储方式和容量限制,但一般都会缓存如HTML文件、图片(JPEG、PNG等)、CSS样式表、JavaScript脚本等资源。

  • 代理缓存:位于客户端和服务器之间的代理服务器可以缓存资源。当多个客户端通过同一个代理服务器访问相同的资源时,代理服务器可以直接提供缓存的资源副本,而无需每次都向服务器请求。这种缓存方式在企业网络或互联网服务提供商(ISP)网络中较为常见,它可以进一步减少网络流量和服务器负载。

缓存控制策略

强制缓存(Cache-Control 和 Expires)

  • Cache-Control:这是HTTP/1.1中用于控制缓存的主要头信息。它有多个指令,如max-age指令用于指定资源在缓存中的最大有效时间(以秒为单位)。例如:

    Cache-Control: max-age=3600
    

    表示资源在缓存中可以保存1小时,在这1小时内,浏览器可以直接使用缓存副本,无需向服务器发送请求。

  • Expires:这是HTTP/1.0中的缓存控制头信息,它指定了资源过期的具体日期和时间。不过,Expires头信息是基于服务器时间的,如果客户端和服务器时间不一致,可能会导致缓存失效问题。现代浏览器通常更倾向于使用Cache-Control头信息。

协商缓存(Last-Modified/If-Modified-Since 和 ETag/If-ETag-Match)

  • Last-Modified/If-Modified-Since:服务器在响应资源时,可以在响应头中添加Last-Modified头信息,其中包含资源最后修改的日期和时间。当客户端再次请求该资源时,会在请求头中添加If-Modified-Since头信息,其值为上次服务器返回的Last-Modified的值。服务器收到请求后,会比较资源的实际最后修改时间和If-Modified-Since的值。如果资源没有修改,服务器会返回304 Not Modified状态码,告知客户端可以继续使用缓存副本;如果资源已经修改,服务器会返回新的资源内容。

  • ETag/If-ETag-MatchETag(实体标签)是服务器为资源生成的一个唯一标识符,它可以基于资源的内容、版本等信息生成。在响应头中,服务器会添加ETag头信息。当客户端再次请求资源时,会在请求头中添加If-ETag-Match头信息,其值为上次服务器返回的ETag的值。服务器收到请求后,会比较当前资源的ETagIf-ETag-Match的值。如果相等,说明资源没有变化,返回304状态码;如果不相等,返回新的资源内容。与Last-Modified/If-Modified-Since相比,ETag机制更加准确,因为它可以考虑到资源内容不变但修改时间改变的情况。

缓存的更新与失效

  • 自动更新(基于缓存控制策略):如前面提到的强缓存和协商缓存策略,当缓存的资源过期或者服务器上的资源发生变化时,缓存会根据服务器返回的信息进行更新。例如,当Cache-Control指定的max-age时间到达后,下一次请求该资源时,浏览器会向服务器发送请求,获取新的资源或者验证资源是否更新。

  • 手动清除(用户或开发者操作):用户可以通过浏览器的设置选项手动清除缓存。例如,在浏览器的隐私或历史记录设置中,可以选择清除缓存数据。开发者在开发过程中,也可以通过浏览器的开发者工具手动清除缓存,以便测试服务器端的最新更改。此外,在一些特殊情况下,如网站进行了重大更新或者资源的URL发生变化,旧的缓存可能会失效,需要用户或开发者手动干预来清除缓存并重新获取最新的资源。

强制缓存与协商缓存详解

什么是强制缓存?

强制缓存指的是只要浏览器判断缓存没有过期,则直接使用浏览器的本地缓存,决定是否使用缓存的主动性在于浏览器这边。如下图中,返回的是200状态码,但在size项中标识的是from disk cache,就是使用了强制缓存。

强制缓存是利用下面这两个HTTP响应头部(Response Header)字段实现的,它们都用来表示资源在客户端缓存的有效期:

  • Cache-Control,是一个相对时间;
  • Expires,是一个绝对时间;

如果HTTP响应头部同时有Cache-ControlExpires字段的话,Cache-Control的优先级高于ExpiresCache-Control选项更多一些,设置更加精细,所以建议使用Cache-Control来实现强缓存。具体的实现流程如下:

  1. 当浏览器第一次请求访问服务器资源时,服务器会在返回这个资源的同时,在Response头部加上Cache-ControlCache-Control中设置了过期时间大小;
  2. 浏览器再次请求访问服务器中的该资源时,会先通过请求资源的时间与Cache-Control中设置的过期时间大小,来计算出该资源是否过期,如果没有,则使用该缓存,否则重新请求服务器;
  3. 服务器再次收到请求后,会再次更新Response头部的Cache-Control

什么是协商缓存?

当我们在浏览器使用开发者工具的时候,你可能会看到过某些请求的响应码是304,这个是告诉浏览器可以使用本地缓存的资源,通常这种通过服务端告知客户端是否可以使用缓存的方式被称为协商缓存。上图就是一个协商缓存的过程,所以协商缓存就是与服务端协商之后,通过协商结果来判断是否使用本地缓存

协商缓存可以基于两种头部来实现。

第一种:请求头部中的If-Modified-Since字段与响应头部中的Last-Modified字段实现,这两个字段的意思是:

  • 响应头部中的Last-Modified:标示这个响应资源的最后修改时间;
  • 请求头部中的If-Modified-Since:当资源过期了,发现响应头中具有Last-Modified声明,则再次发起请求的时候带上Last-Modified的时间,服务器收到请求后发现有If-Modified-Since则与被请求资源的最后修改时间进行对比(Last-Modified),如果最后修改时间较新(大),说明资源又被改过,则返回最新资源,HTTP 200 OK;如果最后修改时间较旧(小),说明资源无新修改,响应HTTP 304走缓存。

第二种:请求头部中的If-None-Match字段与响应头部中的ETag字段,这两个字段的意思是:

  • 响应头部中Etag:唯一标识响应资源;
  • 请求头部中的If-None-Match:当资源过期时,浏览器发现响应头里有Etag,则再次向服务器发起请求时,会将请求头If-None-Match值设置为Etag的值。服务器收到请求后进行比对,如果资源没有变化返回304,如果资源变化了返回200。

第一种实现方式是基于时间实现的,第二种实现方式是基于一个唯一标识实现的,相对来说后者可以更加准确地判断文件内容是否被修改,避免由于时间篡改导致的不可靠问题。

如果在第一次请求资源的时候,服务端返回的HTTP响应头部同时有EtagLast-Modified字段,那么客户端再下一次请求的时候,如果带上了ETagLast-Modified字段信息给服务端,这时ETag的优先级更高,也就是服务端先会判断ETag是否变化了,如果ETag有变化就不用在判断Last-Modified了,如果ETag没有变化,然后再看Last-Modified

**为什么ETag的优先级更高?**这是因为ETag主要能解决Last-Modified几个比较难以解决的问题:

  1. 在没有修改文件内容情况下文件的最后修改时间可能也会改变,这会导致客户端认为这文件被改动了,从而重新请求;
  2. 可能有些文件是在秒级以内修改的,If-Modified-Since能检查到的粒度是秒级的,使用ETag就能够保证这种需求下客户端在1秒内能刷新多次;
  3. 有些服务器不能精确获取文件的最后修改时间。

注意,协商缓存这两个字段都需要配合强制缓存中Cache-Control字段来使用,只有在未能命中强制缓存的时候,才能发起带有协商缓存字段的请求

下图是强制缓存和协商缓存的工作流程:

当使用ETag字段实现的协商缓存的过程:

  1. 当浏览器第一次请求访问服务器资源时,服务器会在返回这个资源的同时,在Response头部加上ETag唯一标识,这个唯一标识的值是根据当前请求的资源生成的;
  2. 当浏览器再次请求访问服务器中的该资源时,首先会先检查强制缓存是否过期:
  • 如果没有过期,则直接使用本地缓存;
  • 如果缓存过期了,会在Request头部加上If-None-Match字段,该字段的值就是ETag唯一标识;
  1. 服务器再次收到请求后,会根据请求中的If-None-Match值与当前请求的资源生成的唯一标识进行比较
  • 如果值相等,则返回304 Not Modified,不会返回资源
  • 如果不相等,则返回200状态码和返回资源,并在Response头部加上新的ETag唯一标识;
  1. 如果浏览器收到304的请求响应状态码,则会从本地缓存中加载资源,否则更新资源。
© 2023 北京元石科技有限公司 ◎ 京公网安备 11010802042949号