HTTP缓存技术详解

通过网络获取内容既缓慢,成本又高:大的响应需要在客户端和服务器之间进行多次往返通信,这拖延了浏览器可以使用和处理内容的时间,同时也增加了访问者的数据成本。因此,缓存和重用以前获取的资源的能力成为优化性能很关键的一个方面。

与缓存相关的HTTP头部字段

http1.0时期的缓存方案

头部名称 说明
Pragma 控制缓存行为,如果设置为no-cache,表示禁用缓存。和http1.1中的Cache-Control头部功能相似
Expires 过期时间,用的是服务器的时间,如果客户端和服务器时间不一致,则会存在缓存时间误差。http1.1可以用Cache-Control来实现相似的功能。

如果使用了Pragma: 'no-cache'的话,再设置Expires或者Cache-Control,就没有用了,说明Pragma的权值比后两者高。

如果设置了Expires之后,客户端在需要请求数据的时候,首先会对比当前系统时间和这个Expires时间,如果没有过那个时间,则直接读取本地磁盘中的缓存数据,不发送请求。

http1.1的缓存方案

通用头部字段,即请求和响应都可以包含

头部名称 说明
Cache-Control 控制缓存行为
Pragma http1.0的字段,作用和Cache-Control大体相同

 

  • Cache-Control作为请求头部
指令 参数 说明
no-cache 强制向源服务器再次验证
no-store 不缓存请求或相应的任何内容
max-age=[秒] 必需 相应的最大Age值
max-stale=(=[秒]) 可省略 接收已过期的响应
min-fresh=[秒] 必需 期望在指定时间内的响应仍有效
no-transform 代理不可更改媒体类型
only-if-cached 从缓存获取资源
cache-extension - 新指令标记(token)

Cache-Control: no-cache

使用 no-cache 指令的目的是为了防止从缓存中返回过期的资源。 客户端发送的请求中如果包含 no-cache 指令,则表示客户端将不会接 收缓存过的响应。于是,“中间”的缓存服务器必须把客户端请求转发 给源服务器。

Cache-Control: max-age=604800(单位:秒)

当客户端发送的请求中包含 max-age 指令时,如果判定缓存资源的缓 存时间数值比指定时间的数值更小,那么服务端就直接返回304,客户端会使用自己本地缓存的资源。 另外,当指定 max-age 值为 0,那么服务器就会使用ETag和modefied-time验证,来决定返回304还是200。

应用 HTTP/1.1 版本的缓存服务器遇到同时存在 Expires 首部字段的情 况时,会优先处理 max-age 指令,而忽略掉 Expires 首部字段。而 HTTP/1.0 版本的缓存服务器的情况却相反,max-age 指令会被忽略。

  • Cache-Control作为响应头部
指令 参数 说明
public 可向任意方提供响应的缓存
private 可省略 仅向特定用户返回响应
no-cache 可省略 缓存前必需先确认其有效性
no-store 不缓存请求或相应的任何内容
no-transform 代理不可更改媒体类型
must-revalidate 可缓存但必须再向源服务器进行确认
proxy-revalidate 要求中间缓存服务器对缓存的响应有效性再进行确认
max-age=[秒] 必需 响应的最大Age值
s-maxage=[秒] 必需 公共缓存服务器响应的最大Age值
cache-extension - 新指令标记(token)

Cache-Control: public

当指定使用 public 指令时,则明确表明其他用户也可利用缓存。

Cache-Control: private

当指定 private 指令后,响应只以特定的用户作为对象,这与 public 指令的行为相反。 缓存服务器会对该特定用户提供资源缓存的服务,对于其他用户发送 过来的请求,代理服务器则不会返回缓存。

Cache-Control: no-cache

如果服务器返回的响应中包含 no-cache 指令,那么缓存服务器不能对 资源进行缓存。源服务器以后也将不再对缓存服务器请求中提出的资 源有效性进行确认,且禁止其对响应资源进行缓存操作。

Cache-Control: no-cache=Location

由服务器返回的响应中,若报文首部字段 Cache-Control 中对 no-cache 字段名具体指定参数值,那么客户端在接收到这个被指定参数值的首 部字段对应的响应报文后,就不能使用缓存。换言之,无参数值的首 部字段可以使用缓存。只能在响应指令中指定该参数。

Cache-Control: no-store

当使用 no-store 指令时,暗示请求(和对应的响应)或响应中包含机密信息。

注:从字面意思上很容易把 no-cache 误解成为不缓存,但事实上 no-cache 代表不缓 存过期的资源,缓存会向源服务器进行有效期确认后处理资源,也许称为 do-notserve-from-cache-without-revalidation 更合适。no-store 才是真正地不进行缓存。

因此,该指令规定缓存不能在本地存储请求或响应的任一部分。

Cache-Control: max-age=604800(单位:秒)

当客户端发送的请求中包含 max-age 指令时,如果判定缓存资源的缓 存时间数值比指定时间的数值更小,那么客户端就不会发起请求,而是直接使用自己本地缓存的资源。 另外,当指定 max-age 值为 0,那么客户端一定会发起一个请求给服务端,服务端会进行资源的校验,决定返回304还是200。

应用 HTTP/1.1 版本的缓存服务器遇到同时存在 Expires 首部字段的情 况时,会优先处理 max-age 指令,而忽略掉 Expires 首部字段。而 HTTP/1.0 版本的缓存服务器的情况却相反,max-age 指令会被忽略。

Cache-Control: s-maxage=604800(单位 :秒)

s-maxage 指令的功能和 max-age 指令的相同,它们的不同点是 smaxage 指令只适用于供多位用户使用的公共缓存服务器 ,如CDN缓存。也就是 说,对于向同一用户重复返回响应的服务器来说,这个指令没有任何 作用。

另外,当使用 s-maxage 指令后,则直接忽略对 Expires 首部字段及 max-age 指令的处理。

cache-control指令流程图

HTTP缓存技术详解_第1张图片

图片51.png


请求头部字段

头部名称 说明
If-Match 比较ETag是否一致,和响应的ETag字段相对应
If-None-Match 比较ETag是否不一致,和响应的ETag字段相对应
If-Modified-Since 比较资源最后更新时间是否一致,和响应的Last-Modified字段相对应
If-Unmodified-Since 比较资源最后更新时间是否不一致,和响应的Last-Modified字段相对应

响应头部字段

头部名称 说明
Etag 资源匹配信息

响应实体头部字段

头部名称 说明
Expires http1.0的缓存过期时间字段
Last-Modified 资源最后一次修改时间

缓存校验字段

ETag

首部字段 ETag 能告知客户端实体标识。它是一种可将资源以字符串 形式做唯一性标识的方式。服务器会为每份资源分配对应的 ETag 值。

另外,当资源更新时,ETag 值也需要更新。生成 ETag 值时,并没有 统一的算法规则,而仅仅是由服务器来分配。

资源被缓存时,就会被分配唯一性标识。例如,当使用中文版的浏览 器访问 http://www.google.com/ 时,就会返回中文版对应的资源,而 使用英文版的浏览器访问时,则会返回英文版对应的资源。两者的 URI 是相同的,所以仅凭 URI 指定缓存的资源是相当困难的。若在下 载过程中出现连接中断、再连接的情况,都会依照 ETag 值来指定资 源。

强 ETag 值和弱 Tag 值

ETag 中有强 ETag 值和弱 ETag 值之分。

强 ETag 值,不论实体发生多么细微的变化都会改变其值。

ETag: "usagi-1234"

弱 ETag 值只用于提示资源是否相同。只有资源发生了根本改变,产 生差异时才会改变 ETag 值。这时,会在字段值最开始处附加 W/。

ETag: W/"usagi-1234"

If-Match

形如 If-xxx 这种样式的请求首部字段,都可称为条件请求。服务器接 收到附带条件的请求后,只有判断指定条件为真时,才会执行请求。

首部字段 If-Match,属附带条件之一,它会告知服务器匹配资源所用 的实体标记(ETag)值。这时的服务器无法使用弱 ETag 值。(请参 照本章有关首部字段 ETag 的说明) 服务器会比对 If-Match 的字段值和资源的 ETag 值,仅当两者一致 时,才会执行请求。反之,则返回状态码 412 Precondition Failed 的响 应。

可以理解为客户端校验当前本地缓存是否在服务器端可用。

还可以使用星号(*)指定 If-Match 的字段值。针对这种情况,服务 器将会忽略 ETag 的值,只要资源存在就处理请求。可以理解为客户端强制请求服务器当前的资源实体。

这个值默认是上一次该资源响应头部的ETag字段值。

If-None-Match

首部字段 If-None-Match 属于附带条件之一。它和首部字段 If-Match 作用相反。用于指定 If-None-Match 字段值的实体标记(ETag)值与 请求资源的 ETag 不一致时,它就告知服务器处理该请求。如果一致,就返回304,表示告知客户端使用自己本地的缓存。

在 GET 或 HEAD 方法中使用首部字段 If-None-Match 可获取最新的资 源。因此,这与使用首部字段 If-Modified-Since 时有些类似。

这个值默认是上一次该资源响应头部的ETag字段值。

Last-modified

Last-Modified: Wed, 23 May 2012 09:59:55 GMT

首部字段 Last-Modified 指明资源最终修改的时间。一般来说,这个 值就是 Request-URI 指定资源被修改的时间。

If-Modified-Since

If-Modified-Since: Thu, 15 Apr 2004 00:00:00 GMT

首部字段 If-Modified-Since,属附带条件之一,它会告知服务器若 If-Modified-Since 字段值早于资源的更新时间,则希望能处理该请求。 而在指定 If-Modified-Since 字段值的日期时间之后,如果请求的资源 都没有过更新,则返回状态码 304 Not Modified 的响应。

这个值默认是上一次该资源响应实体头部的Last-Modified字段值。

If-Unmodified-Since

If-Unmodified-Since: Thu, 03 Jul 2012 00:00:00 GMT

首部字段 If-Unmodified-Since 和首部字段 If-Modified-Since 的作用相 反。它的作用的是告知服务器,指定的请求资源只有在字段值内指定 的日期时间之后,未发生更新的情况下,才能处理请求。如果在指定 日期时间后发生了更新,则以状态码 412 Precondition Failed 作为响应 返回。

可以理解为客户端校验当前本地缓存是否在服务器端可用。

这个值默认是上一次该资源响应实体头部的Last-Modified字段值。

缓存分类

强缓存

强缓存在客户端和服务器端都会存在。

客户端:客户端在请求资源前,会检查上一次该资源响应头的Cache-Control字段,如果该字段的值为max-age=time(大于0的毫秒数),如果该资源缓存的时间没有过这个时间值,则直接使用本地的缓存,而不像服务器发请求。

服务器端:服务器端在接收到一个请求后,如果该请求的头部Cache-Control字段的值为max-age=time(大于0的毫秒数),如果距离上一次返回资源的时间小于这个毫秒数,那么服务器不会读取新的资源,而是直接返回304,告知客户端使用自己本地上次缓存的资源即可。

:这两种情况,其实归根结底最后都是使用的客户端本地的资源,服务器没有返回资源实体。这样的好处是节省请求次数或者请求流量,但缺点是,如果在max-age时间内服务器资源有更新,客户端无法得到最新的服务器资源。此时可以通过Ctrl+F5强制刷新(其实就是设置一个Cache-Control:no-cache的请求头),获得最新的服务器资源。

协商缓存(对比缓存)

对比缓存值存在于服务器端。

在没有走强缓存逻辑的情况下,服务器端会进行Last-Modified和Etag的校验,如果校验发现资源未更新,则会返回304,否则会返回新的资源实体。

缓存流程图

HTTP缓存技术详解_第2张图片

图片61.png



作者:会飞小超人
链接:https://www.jianshu.com/p/4f07740d68e4
来源:简书
简书著作权归作者所有,任何形式的转载都请联系作者获得授权并注明出处。

你可能感兴趣的:(网络协议)