美文网首页服务器知识
详解Http缓存策略

详解Http缓存策略

作者: LK2917 | 来源:发表于2019-06-04 16:00 被阅读0次

    什么是缓存

    缓存 是应用程序中很重要的一个概念,在有大量数据交换的应用程序中,我们会采取一些方式将那些实时性要求不高的数据生成副本并存储在某个相对来说可快速到达、访问、获取的仓库,这样在需要这些数据的时候我们直接从这个仓库中获取数据。

    缓存的目的主要有两点:

    1. 提升数据交换的性能(速度)
    2. 缓解服务器或数据库的压力

    http缓存概述

    当用户开始访问一个网站时,浏览器会从目标服务器获取一些资源用以构建最终的web页面,比如css、js、html等静态文件。假设我们不采取任何措施,则用户每次访问这个网站都要发起一系列http请求,试想,如果这个网站的pv达到上百万甚至上千万,会对网站的后台服务器造成多大的压力。为了尽可能提升网站的性能,http协议给出了一个优化方案:


    image.png

    上图是当用户第一次请求一个资源时的时序图,浏览器会先询问是否有命中缓存(第一次请求肯定是没缓存啦),没有命中的缓存则浏览器再从服务器获取资源并将资源放进缓存仓库中,下次则可以从缓存中拿资源了。为方便理解,我们认为浏览器提供了缓存数据库,只要浏览器发现满足了某些缓存规则,就可以直接从缓存数据库中取出你需要的资源。

    上述是一个简单过程,但是事实上的缓存策略还要更复杂一点。简单来说,http根据是否要向服务器发送请求将缓存规则分为了两类:强缓存对比缓存(对比缓存也叫做协商缓存)。

    强缓存

    强缓存直接从缓存数据库中取出资源,无需再发送请求到服务器上:


    image.png

    http中用来判断是否命中强缓存的字段为ExpiresCache-Control,Cache-Control优先级高于Expires。

    1. Expires

    注:expires字段是HTTP 1.0 时代的产物,现在的浏览器用的全都是HTTP 1.1了,所以这个字段的作用基本可以忽略 。

    来看下某个网站的一次请求中的信息:


    image.png

    expires的值是一个绝对时间,可以看到上图中的时间点:2019年5月30号08:04:42,这代表:这个资源在这个时间点之前都可以直接从缓存中获取。

    2. Cache-Control

    仍旧是上面请求中响应头信息:


    image.png

    cache-control中定义了 public 和 max-age=7200,这是一个相对时间(单位:秒),这里代表资源的缓存在这个请求之后的2小时内都有效。

    请求头cache-control字段列表:

    • Cache-Control: max-age=<seconds>
    • Cache-Control: max-stale[=<seconds>]
    • Cache-Control: min-fresh=<seconds>
    • Cache-control: no-cache
    • Cache-control: no-store
    • Cache-control: no-transform
    • Cache-control: only-if-cached

    响应头cache-control字段列表:

    • Cache-control: must-revalidate
    • Cache-control: no-cache
    • Cache-control: no-store
    • Cache-control: no-transform
    • Cache-control: public
    • Cache-control: private
    • Cache-control: proxy-revalidate
    • Cache-control: max-age=<seconds>
    • Cache-control: s-maxage=<seconds>

    cache-control常见字段的含义:

    • public
      表明响应可以被任何对象(包括:发送请求的客户端,CDN等代理服务器,等等)缓存,即使是通常不可缓存的内容(例如,该响应没有max-age指令或Expires消息头)。
    • private
      表明响应只能被单个用户缓存,不能作为共享缓存(即代理服务器不能缓存它)。私有缓存可以缓存响应内容。
    • no-cache
      可以在本地进行缓存,但每次发请求时,都要向服务器进行验证,如果服务器允许,才能使用本地缓存(即:需要协商缓存)。
    • no-store
      禁止缓存客户端请求或服务器响应的内容,每次都须重新请求服务器拿内容
    • max-age
      设置缓存存储的最大周期,超过这个时间缓存被视为过期 (单位**:秒)

    更详细的cache-control字段含义请看 MDN

    强缓存状态码

    强缓存状态码为200,但查看chrome的network会发现状态码后面多了个注释:


    image.png

    事实上,强缓存时,这个注释会有两种情况:

    • from memory cache
    • from disk cache

    1. from memory cache:
    缓存资源在内存中,浏览器(或页面标签)关闭后内存中的缓存就会被释放,重新打开页面取不到该缓存。

    2. from disk cache
    缓存资源在硬盘中,浏览器(或页面标签)关闭后硬盘中的缓存不会消失,下次进入页面还能从硬盘中获取。

    通常的缓存策略,浏览器打开一个网页,如果该网页最近访问过,那么资源可能会出现from disk cache,从硬盘中读取缓存;:

    image.png

    如果此时刷新页面,该资源会出现from memory cache,从内存中读取缓存。众所周知,内存永远是最快的。

    如果不想从强缓存中获取资源,windows电脑可以通过ctrl + f5刷新页面,mac os 可以通过shift + command + r刷新页面,刷新后你可以看到资源不会出现 from disk(or memory) cache了。

    对比缓存

    对比缓存是需要经过服务器确认是否使用缓存的机制,其http状态码为304,意为not modified。其过程如下:

    image.png

    可以看到,虽然客户端仍然发起了http请求服务器,但是服务器只做了标志对比来确认是否使用缓存,如果确认使用缓存,就不会再返回具体的资源了。这样做虽然没有减少请求数量,但是极大减小了请求负荷,可以明显提升请求速度和减小网络带宽。

    问题是,如何对比标志来确认是否使用缓存?这里主要涉及到两种标志:

    • Last-Modified / If-Modified-Since
    • Etag / If-None-Match

    1. Last-Modified / If-Modified-Since

    当浏览器第一次访问一个资源的时候,服务器会在response header中返回一个Last-Modified,代表这个资源最后的修改时间,当浏览器再次访问这个资源的时候,会在request header中带上 If-Modified-Since,值为上次请求时服务器返回的 Last-Modified 的值,然后服务器根据资源上次修改的时间确认资源在这段期间内是否更改过,如果没有,则返回304,如果有,则返回200并返回最新的资源。


    image.png

    如上图,客户端给服务器的 If-Modified-Since 值和服务端给的Last-Modified的值相同,表示2018年6月21号02:48:50至今,这个资源都没被修改过,所以浏览器可以从缓存中获取。再看其请求负荷,为575B:

    image.png

    通过shift+command+r刷新看下其真实大小,为4.3KB:

    image.png

    2. Etag / If-None-Match
    Etag / If-None-Match 与 Last-Modified / If-Modified-Since 的机制类似,不同的是,Etag是通过一个校验码来对比资源是否更改过的,而不是通过资源的修改时间。当一个资源修改时,其校验码也会更改。当浏览器请求资源时,服务器会返回一个Etag字段,然后浏览器下一次请求时,会带上 If-None-Match ,值为上次服务器返回的Etag的值,服务器经过校验码的对比后决定返回200或304。
    看个例子:

    image.png

    上图中request header中带上了 If-None-Match,值为 5b506e03-25856,response header中返回了Etag,值也是 5b506e03-25856,证明文件没有修改过可以从缓存中获取。

    你可能注意到 If-None-Match 的值中有个 W/ 前缀,这个其实不用去关心,这个是用来提示应该采用弱比较算法(其实是画蛇添足,因为 If-None-Match 用且仅用这一算法)。

    Etag和Last-Modified优先级

    Etag可以解决 Last-Modified 不太好处理的问题,Etag能更准确地控制缓存,因此,如果http请求中若同时出现Etag和Last-Modified,Etag的优先级是高于 Last-Modified 的。具体地说,Last-Modified 有以下一些问题:

    • 一些文件也许会周期性的更改,但是他的内容并不改变(仅仅改变的修改时间),这个时候我们并不希望客户端认为这个文件被修改了,而重新GET;
    • 某些文件修改非常频繁,比如在秒以下的时间内进行修改,(比方说1s内修改了N次),If-Modified-Since能检查到的粒度是s级的,这种修改无法判断(或者说UNIX记录MTIME只能精确到秒);
    • 某些服务器不能精确的得到文件的最后修改时间。

    总结

    网上有副HTTP缓存逻辑流程图,可以很清楚地表明其缓存策略:


    image.png

    参考

    相关文章

      网友评论

        本文标题:详解Http缓存策略

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