美文网首页Java web
你真的懂HTTP的缓存机制?

你真的懂HTTP的缓存机制?

作者: 蛙哇 | 来源:发表于2019-11-06 17:46 被阅读0次

    前言

    HTTP缓存不管是在面试中,还是实际开发中都是重中之重。了解HTTP缓存不仅可以轻松自如应对面试,而且也是在实际开发中对性能优化不可或缺的手段。

    客户端缓存

    缓存不仅可以存在于缓存服务器内,还可以存在客户端浏览器中。通常把客户端缓存称为临时网络文件。浏览器缓存如果有效,就不必再向服务器请求相同的资源了,可以直接从本地磁盘内读取。另外,和缓存服务器相同的一点是,当判定缓存过期后,会向源服务器确认资源的有效性。若判断浏览器缓存失效,浏览器会再次请求新的资源。

    ps:对于前端开发来说,我们只需要关注客户端缓存即可

    浏览器第一次请求资源时,必须请求所有的资源,然后根据响应的header内容来决定,如何缓存资源。一般而言缓存可以分为强缓存和协商缓存两种。

    强缓存

    当客户端缓存所要请求的数据时,客户端直接从缓存服务器中获取数据。当客户端没有缓存所请求的数据时,客户端的才会从服务端获取数据。

    协商缓存

    又称对比缓存,客户端会先从缓存服务器中获取到一个缓存数据的标识,得到标识后请求服务端验证是否失效(新鲜),如果没有失效服务端会返回304,此时客户端直接从缓存中获取所请求的数据,如果标识失效,服务端会返回更新后的数据。

    HTTP报文组成

    首先,在了解HTTP缓存之前,我们有必要先了解HTTP报文的主要组成部分。

    1、HTTP请求报文是由方法、URL、HTTP版本、HTTP首部字段等部分构成。

    image

    2、HTTP响应报文由HTTP版本、状态码、HTTP首部组成。

    image

    在报文众多字段中,HTTP首部字段包含的信息最为丰富的,它是构成HTTP报文的要素之一。跟缓存有关的属性也包含在这里面。

    首部字段

    首先,我们的先了解首部字段有哪些?一般可以分为通用首部字段、请求首部字段、响应请求字段、实体首部字段,由于本文谈论的是缓存相关的,所以在这里只列举了中跟缓存相关的字段名。

    通用首部字段

    请求报文和响应报文都会使用的首部,主要的缓存相关字段:

    Cache-Control:控制缓存的行为。

    通过指定首部字段Cache-Control的指令,就能操作缓存的工作机制,一般可以分为缓存请求指令和缓存响应指令。

    1、缓存请求指令

    • no-cache:强制向源服务器再次验证
    • no-store:不缓存请求或者响应的任何内容
    • max-age = '秒':响应的最大Age值(缓存过期时间)
    • only-if-cached:从缓存获取资源

    2、缓存响应指令

    • public:表示缓存的版本可以被代理服务器或者其他中间服务器识别。
    • private:意味着这个文件对不同的用户是不同的。只有用户自己的浏览器能够进行缓存,公共的代理服务器不允许缓存。
    • no-cache:强制浏览器提交一个http请求到源服务器进行确认。http请求没有减少,会减少一个响应体(文件内容),这种个选项类似弱缓存。
    • max-age: 指定缓存过期的相对时间秒数,max-ag=0或者是负值,浏览器会在对应的缓存中把Expires设置为1970-01-01 08:00:00
    • no-store:不缓存请求或者响应的任何内容

    请求首部字段(Request Header

    从客户端向服务端发送请求报文时使用的首部,主要的缓存相关字段:

    • If-Match:比较实体标记(ETag
    • If-Non-Match:比较实体标记(与If-Match相反)
    • If-Modified-Since:比较资源更新时间
    • If-UnModified-Since:比较资源更新时间(与If-Modified-Since相反)

    响应首部字段(Response Header

    从服务器向客户端发送请求报文时使用的首部,主要的缓存相关字段:

    • ETag:资源的匹配信息(数据签名)

    实体首部字段

    针对请求报文和响应报文的实体部分使用的首部,用于补充内容的更新时间等与实体信息有关的内容,主要的缓存相关字段:

    • Expires:实体主体过期的日期时间
    • Last-Modified:资源最后修改日期时间

    Expires和Cache-Control

    Expires指定缓存到期GMT的绝对时间,如果设了max-agemax-age就会覆盖expires。如果expires到期需要重新请求。

    Cache-Control:这个是http 1.1中为了弥补 Expires 缺陷新加入的。

    ps:所有的首部字段都是基于HTTP/1.1的

    资源验证

    验证是否能使用缓存(协商缓存策略)主要有两种方式:

    1、Last-Modified :最后一次修改时间

    配合If-Modified-SinceIf-UnModified-Since使用
    对比上次修改时间以验证资源是否需要重新修改

    last-modified是web服务器认为文件的最后修改时间,last-modified是第一次请求文件的时候,服务器返回的一个属性。

    Last-Modified: Sat, 09 Jun 2018 08:13:56 GMT 
    

    第二次请求这个文件时,浏览器把If-Modified-Since发送给服务器,询问该时间之后文件是否被修改过。

    If-Modified-Since: Sat, 09 Jun 2018 08:13:56 GMT //  跟Last-Modified的值一样
    

    2、Etag: 数据签名

    配合If-Match或者If-Non-Match使用
    对比资源的签名判断是否使用缓存
    ETag也是首次请求的时候,服务器返回的:

    ETag: "8F759D4F67D66A7244638AD249675BE2" // 长这样
    

    If-None-Match也是浏览器发送到服务器验证,文件是否改变的:

        If-None-Match: "8F759D4F67D66A7244638AD249675BE2" // 跟ETag的值一样
    

    而这里Etag主要为了解决 Last-Modified 无法解决的一些问题:

    1、一些文件也许会周期性的更改,但是他的内容并不改变(仅仅改变的修改时间),这个时候我们并不希望客户端认为这个文件被修改了,而重新GET;

    2、某些文件修改非常频繁,比如在秒以下的时间内进行修改,(比方说1s内修改了N次),If-Modified-Since能检查到的粒度是s级的,这种修改无法判断(或者说UNIX记录MTIME只能精确到秒);

    3、某些服务器不能精确的得到文件的最后修改时间。

    缓存状态码

    • 200 OK (from cache)是浏览器没有跟服务器确认,直接用了浏览器缓存;

    • 304 Not Modified 是浏览器和服务器多确认了一次缓存有效性,再用的缓存。

    • 304 Not Modified200 OK (from cache) 慢,指的是浏览器还向服务器确认了下 If-Not-Modified,才用的缓存。

    • 412 Precondition failed (预处理错误):if-Unmodified-Since指令,如果文件被修改:则不传输,服务器返回该状态码

    浏览器中的操作对缓存的影响:

    强制刷新 – 当按下ctrl+F5来刷新页面的时候, 浏览器将绕过各种缓存(本地缓存和协商缓存), 直接让服务器返回最新的资源;

    普通刷新 – 当按下F5来刷新页面的时候,浏览器将绕过本地缓蹲来发送请求到服务器, 此时, 协商缓存是有效的

    回车或转向 – 当在地址栏上输入回车或者按下跳转按钮的时候, 所有缓存都生效

    相关文章

      网友评论

        本文标题:你真的懂HTTP的缓存机制?

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