zoukankan      html  css  js  c++  java
  • 浏览器缓存机制介绍之http缓存-强缓存-协商缓存

    前言

    缓存的基本策略是拿空间换时间.意思就是我们将数据存储起来,牺牲空间,在下次使用的时候直接拿存储的,减少请求时间.

    浏览器缓存机制有四个方面,它们按照获取资源时请求的优先级依次排列如下:

    memory cache>service worker cache>http cache>push cache

    为了防止篇幅过长,影响阅读体验,我对每一种缓存都会单独写一篇文章,本文主要是讲我们最常用的http缓存.

    缓存是服务器端来设置的,前端无法设置!

    http缓存

    页面通过http获取资源,如果每次资源都通过http去获取,无疑是很消耗性能的,用户的体验并不好.所以我们在完成一次http通讯后,可以将部分资源缓存起来,等到再次使用的时候,直接从缓存中拿,不需要在从服务器中获取了,大大提高了性能.

    http缓存有2种:强缓存和协商缓存

    强缓存

    请求发出时,浏览器回去判断是否命中Expires和Cache-Control两个字段中设置的强缓存,如果命中,那么会直接从缓存中拿取资源,不会与服务器发生通信

    Expires

    express是http1.0中关于强缓存的设置项,值是缓存过期时间.如下图是在network中截取的强缓存样子.

    在第一次请求完毕后,当再次请求时,浏览器就会先对比本地时间和 expires 的时间戳,如果本地时间小于 expires 设定的过期时间,那么就直接去缓存中取这个资源。

    expires设置强缓存对本地时间的依赖导致缓存在某些情况下会出现bug

    cache-control

    cache-control是http1.1中关于缓存的设置项,值有no-cache、no-store、public、private、max-age

    相比于expires,cache-control可以用max-age更精准的设置强缓存的过期时间,因为max-age的值是秒,表示在上一次请求后的多少秒内,强制缓存生效.解决了expires时间戳带来的bug

    cache-control可以看作是expires的完全替代方案,在请求中国呢expires存在的唯一作用就是为了兼容http1.0.

    cache-control的优先级也比expires高,当同时存在时,我们以cache-control为标准

    Response Headers中max-age的样式

    cache-control: max-age=360000

    cache-control其他设置项的功能:

    no-cache:绕开浏览器换取,请求去询问服务器缓存是否更新,走协商缓存的路线

    no-store:绕开浏览器缓存和服务器缓存,每次请求都会重新下载完整的资源

    public:资源可以被所有的用户缓存,包括终端用户和CDN等中间代理服务器

    private:资源只能被当前客户端缓存,不能被代理服务器缓存 

    private是我们默认的设置,但是通常如果我们设置了max-age就会自动开启public模式

    协商缓存

    协商缓存是每次请求时,都回去服务器询问资源是否更新,如果资源没有更新,会返回304状态码让浏览器读取本地缓存;如果服务器资源更新了就会返回更新后的资源

    判断再次请求时服务端资源是否更新是协商缓存的重点,这涉及到几个字段:Etag搭配If-None-Match、Last-Modified搭配If-Modified-Since

    Last-Modified搭配If-Modified-Since

    last-modified值是第一次请求发生时的时间戳,它会随着响应头返回,再次请求的时候请求头会携带上If-Modified-Since,该字段的值是上一次请求的last-modified的值.目的是让服务器知道上一次请求的时间,对比该资源在服务器上最后一次修改的时间,判断在这段时间内资源是否发生了改变

    Last-Modified: Fri, 27 Oct 2017 06:35:57 GMT
    If-Modified-Since: Fri, 27 Oct 2017 06:35:57 GMT

    使用last-modified有一些缺点:

    • 我们编辑了文件,但文件的内容没有改变。服务端并不清楚我们是否真正改变了文件,它仍然通过最后编辑时间进行判断。因此这个资源在再次被请求时,会被当做新资源,进而引发一次完整的响应——不该重新请求的时候,也会重新请求。

    • 当我们修改文件的速度过快时(比如花了 100ms 完成了改动),由于 If-Modified-Since 只能检查到以秒为最小计量单位的时间差,所以它是感知不到这个改动的——该重新请求的时候,反而没有重新请求了。

    为了解决这些缺点etag应运而生.

     Etag搭配If-None-Match

    etag的算法和资源内容有关.服务端会根据资源的内容生成一个唯一的etage.当我们修改资源时,资源内容改变会重新生成etag.

    当我们请求一次资源后,浏览器会通过响应头返回一个etag值.再次请求资源时,http的请求头会携带一个if-None-Match字段,该字段的值就是etag的值.目的是为了给服务器做对比

     为什么要有etag?

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

     总结

    以上就是http缓存的全部内容了,使用强缓存还是协商缓存依据情况而定.

  • 相关阅读:
    滑块破解
    数据结构与算法
    图形验证码 tesserocr pillow
    drf版本控制 和django缓存,跨域问题,
    Django-DRF-图书增删改查 !!!
    Django 序列化-token
    Python- redis缓存 可达到瞬间并发量10W+
    GIT 版本管理-github&码云
    Python 三种过滤去重方法
    LINUX-MYSQL
  • 原文地址:https://www.cnblogs.com/liuXiaoDi/p/13052696.html
Copyright © 2011-2022 走看看