浏览器缓存、 HTTP缓存(强制缓存、协商缓存),浏览器缓存和CDN的关系

CND的定义

CDN:Content Delivery Network/Content Ddistribute Network内容分发网络

客户端访问网站的过程:

没有CDN:

  1. 用户在浏览器访问栏中输入要访问的域名
  2. 浏览器想DNS服务器请求对该域名的解析
  3. DNS服务器返回该域名的IP地址给浏览器
  4. 浏览器使用该IP地址向服务器请求内容
  5. 服务器将用户请求的内容返回给浏览器

使用CND

  1. 用户在浏览器中输入要访问的域名
  2. 浏览器向DNS服务器请求对域名进行解析。由于CND对域名解析进行了调整,DNS服务器会最终将域名的解析权交给CNAME指向CND专用的DNS服务器
  3. CDN的DNS服务器将CDN的负载均衡设备IP地址返回给用户
  4. 用户向CND的负载均衡设备发起内容URL访问请求
  5. CND负载均衡设备会为用户选择一台合适的缓存服务器提供服务。选择的依据包括:根据用户IP地址,判断那一台服务器距离用户最近, 根据用户所请求的URL中携带的内容名称, 判断那一台服务器上有用户所需的内容;查询各个服务器的负载情况, 判断哪一台服务器负载较小
  6. 用户向缓存服务器发出请求
  7. 缓存服务器响应用户请求, 将用户所需的内容传送到用户

如果这台缓存服务器上并没有用户想要的内容, 而负载均衡设备依然将它分配给了用户, name这台服务器就要向它的上一级缓存服务器请求内容, 知道追溯到网站的源服务器将内容拉取到本地

关于缓存

没有CND:浏览器缓存

使用了CND:浏览器缓存+CND缓存

在用户第一次访问了网站后, 网站的一些静态资源如图片就会被下载到本地, 作为缓存, 当用户第二次访问该网站的时候, 浏览器就会从缓存中加载资源, 不用向服务器请求资源, 从而提高了网站的访问速度, 而若使用了CND, 当浏览器本地缓存的资源过期之后, 浏览器不是直接向原站点请求资源, 而是想CDN边缘节点请求资源, CND边缘节点中也存在缓存, 若CND中的缓存也过期, 那就由CND边缘节点向原站点发出回源请求来获取最新资源

浏览器缓存以及CND缓存都有一套潘丹文件是否需要更新的机制

浏览器在加载资源时, 先根据这个资源的一些http header判断他是否命中强缓存, 如果命中, 浏览器直接从自己的缓存中读取资源, 不会发起请求到服务器。 当强缓存没有命中的时候, 浏览器一定会发送一个请求到服务器, 服务器端依据资源的另外一些http header验证这个资源是否命中协商缓存, 如果命中服务器会将这个请求返回, 但是不会反回这个资源的数据, 而是告诉客户端可以直接从缓存中加载这个资源, 于是浏览器还是从自己的缓存中加载资源, 当协商缓存也没有命中的时候, 浏览器直接从服务器加载资源数据。

CDN节点缓存机制在不同服务商中是不同的, 但一般都遵循HTTP协议, 通过http响应头中的chche-control:max-age 的字段来设置CND节点文件的缓存时间, 当客户端向CDN节点请求数据时, CND会判断缓存数据是否过期, 若没有过期, 则直接将缓存数据返回给客户端, 否则就向原站点发起请求, 从原站点拉去最新数据, 更新本地缓存, 并将最新数据返回给客户端。 CDN服务商一般会提供文件后缀、目录多个维度来指定CDN缓存时间, 为用户提供更精细化的缓存管理。 CDN缓存时间会对会员率产生直接的影响, 若CDN缓存时间短, 则数据经常失败, 导致平凡回源, 增加源站负荷, 同时也增大了访问延时;若缓存时间长, 数据更新时间慢, 因此需要正对不同业务需求来选择特定的数据缓存管理

浏览器缓存刷新

  1. 在地址栏中输入网之后按回车或者点击转到按钮:浏览器以最少的请求来获取网页的数据, 浏览器会对所有没有过期的内容直接使用本地缓存即使用强缓存 从而减少了对服务器的请求, Expires、max-age标志只对这种方式有效
  2. 按F5或浏览器刷新按钮:浏览器会在请求中附加必要的缓存协商, 但不允许浏览器直接使用本地缓存即跳过强缓存的判断, last-modified ETag在这种时候发挥作用
  3. 按Ctrl + F5 或按Ctrl并点击刷新按钮:强制刷新, 完全不使用缓存

CDN缓存刷新

CDN节点对开发者是透明的, 可以通过CDN服务商提供的刷新缓存接口来达到清理CDN节点缓存的效果, 强制使数据过期, 从而获取到最细的数据

浏览器缓存

1.1强缓存

当浏览器对某个资源的请求命中了强缓存时, 返回的http状态码为200, 在chrome开发者工具中的network中的size会显示form cache

强缓存是利用expires或者cache-control这两个http header实现的, 都用来标识资源在客户端缓存的有效期

Expires是http1.0提出的一个header, 描述的是一个绝对时间 由服务器返回, 用GMT格式的字符串标识,如Exprires:Thu,31 Dec 2037 23:55:55 GMT

缓存过程

  1. 浏览器第一次跟服务器请求一个资源, 服务器再返回这个资源的同事,在response的header加上Expires的header
  2. 浏览器在接收到这个资源后, 会把这个资源连同所有的response header一起缓存下来, 所以缓存命中的请求返回的header并不是俩字服务器, 而是来自之前缓存的header
  3. 浏览器再请求这个资源时, 先从缓存中寻找, 找到这个资源后, 拿出Expires跟当前的请求时间比较, 如果请求时间在Expires指定的事件之前, 就能命中缓存, 否则就不行
  4. 如果缓存没有命中, 浏览器直接从服务器加载资源时, Expires Header在重新加载的时候会被更新

Expires是服务器返回的一个绝对时间, 在服务器时间与客户端时间相差较大时, 缓存管理容易出现问题, 比如随意修改下客户端时间, 就能影响缓存命中结果, 所以在http 1.1的时候提出了新的header 也就是cache-control 这是一个相对时间, 在进行缓存命中的时候, 都是利用客户端时间进行判断, 因此更有效安全一些, 在配置缓存的时候, 以秒为单位, 用树值标识, 如cache-control: max-age=3944449992它的缓存过程是:

  1. 浏览器第一次跟服务器请求一个资源, 服务器在返回这个资源的同时, 在response的header上加上cache-control的header
  2. 浏览器在接收到这个资源的时候, 会把这个资源连同所有response header一起缓存下来
  3. 浏览器再次请求这个自愿的 时候, 先从缓存中寻找, 找到这个资源后, 再拿这个过期时间跟当前的请求时间比较, 如果请求时间在过期时间之前, 就能命中缓存, 否则就不行
  4. 如果没有命中缓存, 浏览器直接从服务器加载资源, cache-control在重新加载的时候会被更新

这两个header可以只用一个, 也可以同时用两个, 同时存在时, cache-control优先级高于Expires

强缓存管理

两种方式来设置是否启用强缓存

  1. 通过代码的方式, 在web服务器返回的响应中添加Expires和Cache-control Header
  2. 通过配置web服务器的方式, 让web服务器在响应资源的时候同一添加Expires和cache-control header

强缓存的应用

强缓存是前端性能优化最有利的工具, 对于有大量静态资源的网页, 一定要利用强缓存, 提高响应速度, 通常是为这些静态资源全部配置一个超时时间超长的Expires或cache-control 这样用户只会在第一次访问网站时加载静态资源, 其他时间只要缓存没有失效并且用户没有强制刷新的条件下都会从缓存中加载

然后这种缓存配置方式会带来一个问题, 就是当资源更新时, 客户端由于有缓存不会像服务器请求最新的资源, 这个问题已有解决方案:

通过更新页面中引用的资源路径, 让浏览器主动放弃缓存, 加载信资源。

但要实现有更新的文件才需要浏览器重新加载, 因此必须让url的修改与文件内容相关联, 利用数据摘要算法对文件求摘要信息, 摘要信息与文件内容一一对应, 这一点许多前端构建工具都做到了, 如webpack

浏览器默认缓存使开发环境下常因为资源没有及时更新而看不到效果

解决方案

  1. ctrl + F5
  2. 浏览器隐私模式开发
  3. chrome开发者工具将disable cache 选项打勾, 阻止缓存
  4. 在开发阶段, 给资源加上一个动态的参数, 由于每次资源的修改都要更新引用的位置, 同时修改参数的值, 所以操作起来不是很方便, 除非是在动态页面比如jsp里开发就可以用服务器变量来解决, 或者用前端构建工具来处理这个参数修改问题
  5. 如果资源引用的页面被嵌入到了一个iframe里面, 可以在iframe的区域右键重新加载该页面
  6. 如果缓存问题出现在ajax请求中, 最有效的解决办法就是ajax的请求地址追加随机数
  7. 动态设置iframe的src时, 有可能因为缓存问题导致看不到最新效果, 在src后面添加随机数即可
  8. 通过前端开发工具, grunt gulp 等插件, 来启动一个静态服务器, 则在这个服务器下所有返回的response header 中, cache-control时钟被设置为不缓存

协商缓存

如果命中协商缓存, 请求响应返回的http状态为304以及一个not modified字符, 协商缓存利用的是 last-modified if-modified-since || Etag 、 if-none-match这两对header来管理的

Last-Modified、If-Modified-Since】:

1、浏览器第一次跟服务器请求一个资源,服务器在返回这个资源时,在response的header加上Last-Modified的header,表示这个资源在服务器上的最后修改时间

2、浏览器再次向服务器请求这个资源时,在request的header加上If-Modified-Since的header,这个header的值就是上一次请求时返回的Last-Modified的值

3、服务器再次收到资源请求时,根据浏览器传过来If-Modified-Since和资源在服务器上的最后修改时间判断资源是否有变化,如果没有变化则返回304 Not Modified,但是不会返回资源内容,如果有变化就返回资源内容,当服务器返回304 Not Modified的响应时,response header中不会再添加Last-Modified的header,因为资源没有变化,Last-Modified的值也不变

4、浏览器收到304的响应后,就会从缓存中加载资源

5、如果协商缓存没有命中,浏览器直接从服务器加载资源时,Last-Modofied header在重新加载的时候会被更新,下次请求时,If-Modified-Since会采用上一次返回的Last-Modified的值

这一对header都是根据服务器时间返回的,有时候会有服务器资源有变化,但最后修改时间却没有变化的情况,因此有了


 

【Etag、If-None-Match】:

1、浏览器第一次向服务器请求一个资源,服务器在返回这个资源的同时,在response的header加上ETag的header,这个header是服务器根据当前请求的资源生成的一个唯一标识,是一个字符串,只要资源内容发生改变,这个字符串也会改变,跟时间没有关系

2、浏览器再次请求这个资源的时候,在request的header上加上If-None-Match的header。这个header的值是上一次请求返回的ETag的值

3、服务器再次收到资源请求时,根据客户端传过来的If-None-Match和重新生成的该资源的新的ETag做比较,相同则返回304 Not Modified,不会返回资源内容,如果不同则返回资源内容,但这里即使资源没有发生变化,也会返回ETag,因为这个ETag重新生成过,即使没有ETag没有变化

4、浏览器收到304响应后,就从缓存中加载资源

2.2 协商缓存的管理

一般服务器上的【Last-Modified、If-Modified-Since】和【Etag、If-None-Match】会同时启用,协商缓存需要配合强缓存使用

参考文章: http://www.cnblogs.com/blogbyhuer/p/9335257.html

猜你喜欢

转载自blog.csdn.net/qq867263657/article/details/89318724