美文网首页
浏览器缓存

浏览器缓存

作者: 达文西_Huong | 来源:发表于2020-07-21 23:43 被阅读0次

    浏览器的缓存机制

    浏览器的缓存机制实际上就是HTTP缓存机制,其实就是根据请求报文中的缓存标识符进行识别然后进一步进行操作的。

    前言

    在细说浏览器的缓存之前我们有必要先介绍一些必备的知识:

    HTTP请求报文

    HTTP请求报文的格式为:

    1. 请求行
    2. HTTP头(通用信息头,请求头,实体头)
    3. 请求报文主体(当请求为POST请求才有)

    下面附上一张图

    image image
    HTTP响应报文

    HTTP响应报文的格式为

    1. 状态行
    2. HTTP头(通用信息头,响应头,实体头)
    3. 响应报文主体
    image image

    通用信息头指的是请求和响应报文都支持的头域包括Cache-control,Connection,Date,Pragma,Transfer-Encoding,Upgrade,Via;
    实体头 则是实体信息的实体头域,分别为Allow、Content-Base、Content-Encoding、Content-Language、Content-Length、Content-Location、Content-MD5、Content-Range、Content-Type、Etag、Expires、Last-Modified、extension-header

    本篇文章为了方便讲解就都把他们合起来称为HTTP头。

    缓存过程的分析

    在浏览器与服务器之间的通讯方式是一种应答模式的通讯方式。即浏览器发起HTTP请求,服务器收到后响应请求,而浏览器的缓存机制,就是通过在浏览器第一次和服务器请求的时候,携带的缓存标识符去执行相应的缓存操作。

    为了更好的理解我们上图:


    image

    现在我们知道,每次浏览器发起的第一次请求的时候会执行两个步骤

    1. 先向浏览器的缓存中核查是否有该请求的资源以及缓存标识符
    1. 把接收到的新得资源和缓存标识符缓存到浏览器缓存中

    能看懂这个图其实已经算是理解了浏览器缓存机制的一半了。因为它确保了每个请求的缓存存入与取出,而之后的缓存策略都是建立在这个的基础上进行的。

    在浏览器的缓存机制中,一共分为两种类型的缓存:一种是强缓存另一种是协商缓存。下面我们一步一步来讲解,这两种缓存之间的区别和他们各自在执行时候浏览器和服务器之间的行为是如何进行的。

    强缓存

    首先我们先来看看强缓存,其实强缓存就是浏览器向服务器发起请求,并且根据浏览器缓存的缓存规则进行判断资源是否可用以及是否需要重新请求的一种流程

    强缓存存在三种不同的情况:

    1. 不存在该缓存资源和缓存标识,标识强缓存失效,需要向服务器发起请求(即第一次请求)
    image
    1. 存在该缓存资源和标识,但是结果已经失效了,需要重新请求。这个时候需要触发协商缓存这里先不表,下面会细说
    image
    1. 存在缓存资源和标识,并且结果没有失效,直接返回该资源给浏览器(即强缓存生效)
    image

    看完上面的图,想必你对强缓存已经有了更深入的了解,但是还没完。上面所讲的只是强缓存的表面现象,我们还需要再了解得更深入一些。

    这个时候你可能会有疑问
    Q: 图中的缓存规则究竟是什么呢
    A: 当浏览器向服务器发送请求之后,服务器会把缓存规则返回给浏览器,让浏览器把它缓存起来,而这个规则是携带在HTTP响应报文的头中的。这两个字段分别是(Expires和Cache-Control

    其中Cache-Control的优先级大于Expires

    Expires

    Expires 是HTTP/1.0控制网页缓存的字段,其值为服务器返回请求结果的到期时间,一旦下一次浏览器再向服务器发送请求的时候,携带过来的时间值 > Expires的值的时候,说明缓存已经失效服务器再返回新的资源

    但是这种方式有一个十分致命的缺点,那就是一旦服务器与浏览器之间因为地区不同或者其他原因导致时间存在时差的时候,就很容易发生误判,导致强缓存会直接失效。

    而且现在浏览器默认支持的是HTTP/1.1。而在1.1中使用的是Cache-control

    Cache-control

    Cache-control 是HTTP/1.1支持的缓存规则。它有几个可选值

    作用
    public 所有内容都将被缓存(客户端和代理服务器都可以缓存
    private 所有内容只允许客户端缓存 默认值
    no-cache 客户端缓存内容,但是是否使用缓存根据协商验证决定(执行协商缓存的取值
    no-store 所有内容都不会被缓存,即使用强缓存也不适用协商缓存
    max-age=xxx(number) 缓存将在xxx秒之后失效

    接下来我们直接看一个例子


    image

    从上图我们可以得出:

    1. max-age 的值是一个相对固定的值
    2. 而expires 的值是一个绝对值,而且也确实证实了根据时区不同会容易产生时差的。

    我们再来看一下下面的图:


    image

    这个图中的请求,我们看到size中的值分别有两种,一种是from memory cachefrom disk cache

    Q: 什么是 from memory cache 啊
    A: from memory cache 的意思就是资源来自于内存缓存中

    Q: 什么是 from disk cache
    A:from disk cache 的意思就是资源来自于硬盘中的缓存。

    而浏览器一般读取资源的顺序是先从memory 再到 disk的。
    一般memory 存储的都是一些图片或者js的资源,而CSS文件一般是存储在memory中

    memory cache(内存缓存)的特点
    快速:内存缓存会将编译后的文件,直接存入到进程的内存中,占据进程的一定内存资源,以便下次读取,所以速度会快
    时效性: 而正因为是保存在内存中,所以每次关闭浏览器之后(即杀死进程)。该进程中的内存就会被清空,从而缓存也会清空掉。

    disk cache(硬盘缓存)的特点
    与memory就刚好相反。因为在缓存在磁盘中,读取缓存还需要对文件进行相应的I/O操作所以自然会比较慢一些。同时也因为是直接缓存在硬盘中,即使页面关闭了进程的内存被清空,而磁盘中的缓存也仍然会存在。

    协商缓存

    协商缓存就是当强缓存时效之后,浏览器携带着标识符向服务器发起请求,服务器根据发送过来的协商缓存标识判断是否使用缓存的过程

    协商缓存存在两种情况

    1. 协商缓存生效,返回304


      image
    2. 协商缓存不生效,返回200和请求的结果


      image

    和强缓存相似,协商缓存也会将缓存标识符的字段携带在报文的请求头中,返回给服务器/浏览器。

    控制协商缓存的字段分别有Last-Modified/If-Modified-SinceEtag/If-None-Match

    Last-Modified/If-Modified-Since

    Last-Modified 是服务器响应请求时,返回该资源文件在服务器最后被修改的时间,在响应报文中的字段表达是

        last-modified: Web, 20 Mar 2020 10:37:56 GMT
    

    if-Modified-Since 是客户端再次发起请求的时候,携带上上次服务器响应报文中的 Last-Modified 的值。返回给服务器。服务器发现请求头含有 If-Modified-Since 后会与该资源在服务器的最后更新时间作对比,如果更新时间大于If-Modified-Since 说明资源有更新,则返回响应码200,并且返回新的资源。反之就是304,提示资源无更新。

        if-Modified-Since : Web, 20 Mar 2020 11:37:56 GMT
    
    Etag / If-None-Match
    1. Etag 是服务响应请求的时候,返回当前资源文件的唯一标识符,在报文中的显示
        etag:W/"175737-15221592677000"
    
    1. If-None-Match 是客户端再次发起请求时,携带上之前服务器返回的Etag唯一标识符的值,然后服务器收到后发现报文中有If-None-Match这个值,并且把这个值拿出来与资源文件在服务器中得Etag的值作对比,如果一致则说明资源没有更新返回304,否则就返回200,并且返回最新的资源文件
        If-None-Match: W/"175737-1521592677000"
    

    Etag / If-None-Match优先级高于Last-Modified / If-Modified-Since,同时存在则只有Etag / If-None-Match生效。

    小tips:

    Last-Modified/If-Modified-Since是存在的缺点:因为也是根据时间来判断资源是否更新了,而且判断的时间单位是秒级别的,而假设资源再这一秒以内进行了更新,而这个1s内服务器会容易存在误判导致意味资源并没有更新。

    那是不是说Etag / If-None-Match 就是最完美的呢? 其实也不是

    Etag / If-None-Match的缺点:就是每次计算文件并且生成对应的标识是需要花费一些性能了,而相比较于?Last-Modified/If-Modified-Since会消耗更多的性能。

    所以其实并没有完美的方案,有得只是更适合的方案罢了。

    总结

    优先级:强缓存 > 协商缓存。一旦强缓存执行成功,就不会再执行协商缓存了,反之则会执行协商缓存
    强缓存中的优先级: Cache-Control > Expires
    协商缓存中的优先级: Etag / If-None-Match > Last-Modified / If-Modified-Since

    最后附上浏览器缓存机制的流程图:

    image

    感谢您的阅读,如有错误和言辞不当的地方还请您多多包涵

    参考链接:https://www.cnblogs.com/chengxs/p/10396066.html (文中部分图片的出处)

    以上

    相关文章

      网友评论

          本文标题:浏览器缓存

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