美文网首页前端杂记
HTTP缓存技术详解

HTTP缓存技术详解

作者: 会飞小超人 | 来源:发表于2018-05-25 18:08 被阅读144次

    title: HTTP缓存技术详解
    date: 2018-05-21 14:20:06
    tags:

    • HTTP
    • 缓存
      categories: 深入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指令流程图

    图片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,否则会返回新的资源实体。

    缓存流程图

    图片61.png

    相关文章

      网友评论

        本文标题:HTTP缓存技术详解

        本文链接:https://www.haomeiwen.com/subject/bkmujftx.html