美文网首页让前端飞Web前端之路
前端http请求细节——Cache-Control(缓存机制)

前端http请求细节——Cache-Control(缓存机制)

作者: 虚拟J | 来源:发表于2020-07-21 10:38 被阅读0次

    Cache-Control 通用消息头字段,被用于在 http 请求和响应中,通过指定指令来实现缓存机制。缓存指令是单向的,这意味着在请求中设置的指令,不一定被包含在响应中。

    请求和响应中的 Cache-Control 指令并不完全相同,具体可以查看这里,包括指令的具体意思,这里不过多赘述。(默认值:private)

    缓存

    浏览器的缓存机制是根据 HTTP 报文的缓存标识进行的,浏览器第一次向服务器发起该请求后拿到请求结果,会根据响应报文中 HTTP 头的缓存标识,决定是否缓存结果。
    浏览器缓存策略分为两种:强制缓存和协商缓存。

    • 强制缓存就是向浏览器缓存查找该请求结果,并根据该结果的缓存规则来决定是否使用该缓存结果的过程。
    • 协商缓存就是强制缓存失效后,浏览器携带缓存标识向服务器发起请求,由服务器根据缓存标识决定是否使用缓存的过程。
    强制缓存(存储位置)

    强制缓存不会向服务器发送请求,直接从缓存中读取资源,可以看到请求返回的状态码都是200,并且 Size 代表该缓存的位置。

    浏览器读取缓存的顺序为memory –> disk。

    • 内存缓存(memory cache):
      快速读取:内存缓存会将编译解析后的文件,直接存入该进程的内存中,占据该进程一定的内存资源,以方便下次运行使用时的快速读取。
      时效性:一旦该进程关闭,则该进程的内存则会清空。

    • 硬盘缓存(disk cache):
      硬盘缓存则是直接将缓存写入硬盘文件中,读取缓存需要对该缓存存放的硬盘文件进行I/O操作,然后重新解析该缓存内容,读取复杂,速度比内存缓存慢。

    三级缓存原理 (访问缓存优先级):

    1. 先在内存中查找,如果有,直接加载。
    2. 如果内存中不存在,则在硬盘中查找,如果有直接加载。
    3. 如果硬盘中也没有,那么就进行网络请求。
    4. 请求获取的资源缓存到硬盘和内存。

    在浏览器中,浏览器会在js,字体,图片等文件解析执行后直接存入内存缓存中,那么当刷新页面时只需直接从内存缓存中读取(from memory cache);而css文件则会存入硬盘文件中,所以每次渲染页面都需要从硬盘读取缓存(from disk cache)。

    为什么CSS会放在硬盘缓存中?
    因为CSS文件加载一次就可渲染出来,我们不会频繁读取它,所以它不适合缓存到内存中,但是js之类的脚本却随时可能会执行,如果脚本在磁盘当中,我们在执行脚本的时候需要从磁盘取到内存中来,这样IO开销就很大了,有可能导致浏览器失去响应。

    协商缓存(判断资源是否更新的验证机制)
    • Last-Modified / If-Modified-Since
      Last-Modified 是服务器响应请求时,返回 response header 该资源文件在服务器最后被修改的时间。
      If-Modified-Since 则是客户端再次发起该请求时,request header 携带上次请求返回的Last-Modified值,通过此字段值告诉服务器该资源上次请求返回的最后被修改时间。

    若服务器的资源最后被修改时间 > If-Modified-Since的字段值
    则重新返回资源,状态码为200;否则则返回304,代表资源无更新,可继续使用缓存文件

    • Etag / If-None-Match
      Etag 是服务器响应请求时,返回 response header 当前资源文件的一个唯一标识(由服务器生成)。
      If-None-Match是客户端再次发起该请求时,request header 携带上次请求返回的唯一标识Etag值,通过此字段值告诉服务器该资源上次请求返回的唯一标识值。

    If-None-Match 的字段值 = 该资源在服务器的Etag值
    一致则返回304,代表资源无更新,继续使用缓存文件;不一致则重新返回资源文件,状态码为200。

    ETag 和 Last-Modified 区别

    • 在方式上,Etag是对资源的一种唯一标识,而Last-Modified是该资源文件最后一次更改时间
    • 在精确度上,Etag要优于Last-Modified。Last-Modified的时间单位是秒,如果某个文件在1秒内改变了多次,那么他们的Last-Modified其实并没有体现出来修改,但是Etag每次都会改变确保了精度;如果是负载均衡的服务器,各个服务器生成的Last-Modified也有可能不一致。
    • 在性能上,Etag要逊于Last-Modified,毕竟Last-Modified只需要记录时间,而Etag需要服务器通过算法来计算出一个hash值。
    • 在优先级上,服务器校验优先考虑Etag。
    其他:
    • Pragma 是一个在 HTTP/1.0 中规定的通用首部。(Pragma 唯一指令 no-cache 与 Cache-Control: no-cache 效果一致)
      在 HTTP 响应中的行为没有确切规范且在 HTTP/1.1 协议中的 Cache-Control 出现前,所以仅作为与 http 的向后兼容而定义,建议只在需要兼容 HTTP/1.0 客户端的场合下应用 Pragma 首部。
    • Expires是HTTP/1.0控制网页缓存的字段,其值为服务器返回该请求结果缓存的到期时间,即再次发起该请求时,如果客户端的时间小于Expires的值时,直接使用缓存结果。
      到了HTTP/1.1,Expire已经被Cache-Control替代,原因在于Expires控制缓存的原理是使用客户端的时间与服务端返回的时间做对比,那么如果客户端与服务端的时间因为某些原因(例如时区不同;客户端和服务端有一方的时间不准确)发生误差,那么强制缓存则会直接失效,这样的话强制缓存的存在则毫无意义。

    参考链接:
    https://juejin.im/entry/5ad86c16f265da505a77dca4
    https://www.cnblogs.com/suihang/p/12855345.html
    https://www.jianshu.com/p/54cc04190252

    相关文章

      网友评论

        本文标题:前端http请求细节——Cache-Control(缓存机制)

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