struggleForLife

Sometimes your whole life boils down to one insane move.

导航

浏览器缓存原理以及本地存储

说白了就是利用本地存储,把一部分数据保存在客户端,减少对服务器的请求,降低服务器压力,提升网页加载速度,

作为一名前端工作人员,前端的缓存知识是必须掌握的,因为一个网站打开网页的速度直接关系到用户体验,用户粘度,而提高网页的打开速度有很多方面需要优化,其中比较重要的一点就是利用好缓存,缓存文件可以重复利用,还可以减少带宽,降低网络负荷。

1 缓存

缓存从宏观上分为私有缓存和共享缓存,共享缓存就是那些能被各级代理缓存的缓存。私有缓存就是用户专享的,各级代理不能缓存的缓存
缓存从微观上可以分为以下几类:
  • 浏览器缓存
  • 代理服务器缓存
  • CDN缓存
  • 数据库缓存
  • 应用层缓存
这里主要对浏览器的缓存进行说明:
 

2 http缓存

2.1 强缓存

  • 不会向服务器发送请求,直接从缓存中读取资源
  • 请求返回200的状态码
  • 在chrome控制台的network选项中可以看到size显示from disk cache或from memory cache。
from memory cache代表使用内存中的缓存,from disk cache则代表使用的是硬盘中的缓存,浏览器读取缓存的顺序为memory –> disk。在浏览器中,浏览器会在js和图片等文件解析执行后直接存入内存缓存中,那么当刷新页面时只需直接从内存缓存中读取(from memory cache);而css文件则会存入硬盘文件中,所以每次渲染页面都需要从硬盘读取缓存(from disk cache)。
 
Expires和Cache-Control两者对比:其实这两者差别不大,区别就在于 Expires 是http1.0的产物,Cache-Control是http1.1的产物,两者同时存在的话,Cache-Control优先级高于Expires
 

2.2 协商缓存

协商缓存就是强制缓存失效后,浏览器携带缓存标识向服务器发起请求,由服务器根据缓存标识决定是否使用缓存的过程

2.2.1 Last-Modified和If-Modified-Since

浏览器在第一次访问资源时,服务器返回资源的同时,在response header中添加 Last-Modified的header,值是这个资源在服务器上的最后修改时间,浏览器接收后缓存文件和header;
浏览器下一次请求这个资源,浏览器检测到有 Last-Modified这个header,于是添加If-Modified-Since这个header,值就是Last-Modified中的值;服务器再次收到这个资源请求,会根据 If-Modified-Since 中的值与服务器中这个资源的最后修改时间对比,如果没有变化,返回304和空的响应体,直接从缓存读取,如果If-Modified-Since的时间小于服务器中这个资源的最后修改时间,说明文件有更新,于是返回新的资源文件和200
 
缺点:1、某些服务端不能获取精确的修改时间 2、文件修改时间改了,但文件内容却没有变
 

2.2.2 ETag和If-None-Match

Etag是上一次加载资源时,服务器返回的response header,是对该资源的一种唯一标识,只要资源有变化,Etag就会重新生成。浏览器在下一次加载资源向服务器发送请求时,会将上一次返回的Etag值放到request header里的If-None-Match里,服务器只需要比较客户端传来的If-None-Match跟自己服务器上该资源的ETag是否一致,就能很好地判断资源相对客户端而言是否被修改过了。如果服务器发现ETag匹配不上,那么直接以常规GET 200回包形式将新的资源(当然也包括了新的ETag)发给客户端;如果ETag是一致的,则直接返回304知会客户端直接使用本地缓存即可。
     

2.2.3 协商缓存两种方式的对比

  1. 首先在精确度上,Etag要优于Last-Modified,Last-Modified的时间单位是秒,如果某个文件在1秒内改变了多次,那么他们的Last-Modified其实并没有体现出来修改,但是Etag每次都会改变确保了精度;如果是负载均衡的服务器,各个服务器生成的Last-Modified也有可能不一致。
  2. 性能上,Etag要逊于Last-Modified,毕竟Last-Modified只需要记录时间,而Etag需要服务器通过算法来计算出一个hash值。
  3. 优先级上,服务器校验优先考虑Etag

3 缓存机制

appcache优先于强缓存,强制缓存优先于协商缓存进行,若强制缓存(Expires和Cache-Control)生效则直接使用缓存,若不生效则进行协商缓存(Last-Modified / If-Modified-Since和Etag / If-None-Match),协商缓存由服务器决定是否使用缓存,若协商缓存失效,那么代表该请求的缓存失效,返回200,重新返回资源和缓存标识,再存入浏览器缓存中;生效则返回304,继续使用缓存。具体流程看下图:
不管是浏览器缓存,还是代理服务器缓存,CDN缓存都遵循客户端与服务端之间的缓存机制

4、本地存储

本地存储主要有以下几种,localStorage,sessionStorage和cookie,WebSql和IndexDB主要用在前端有大容量存储需求的页面上,例如,在线编辑浏览器或者网页邮箱。他们都可以将数据存储在浏览器,应该根据不同的场景进行使用。

4.1 Cookie

Cookie主要是由服务器生成,且前端也可以设置,保存在客户端本地的一个文件,通过response响应头的set-Cookie字段进行设置,且Cookie的内容自动在请求的时候被传递给服务器。在客户端和服务器之间来回传递,耗性能,如下:
Cookie包含的信息:
它可以记录你的用户ID、密码、浏览过的网页、停留的时间等信息。当你再次来到该网站时,网站通过读取Cookies,得知你的相关信息,就可以做出相应的动作,如在页面显示欢迎你的标语,或者让你不用输入ID、密码就直接登录等等。一个网站只能读取它自己放置的信息,不能读取其他网站的Cookie文件。因此,Cookie文件还保存了host属性,即网站的域名或ip。 
这些属性以名值对的方式进行保存,为了安全,它的内容大多进行了加密处理。Cookie文件的命名格式是:用户名@网站地址[数字].txt
Cookie的优点:
  • 给用户更人性化的使用体验,如记住“密码功能”、老用户登录欢迎语
  • 弥补了HTTP无连接特性
  • 站点统计访问人数的一个依据
Cookie的缺点:
  • 它无法解决多人共用一台电脑的问题,带来了不安全因素
  • Cookie文件容易被误删除
  • 一人使用多台电脑
  • Cookies欺骗。修改host文件,可以非法访问目标站点的Cookie
  • 容量有限制,不能超过4kb
  • 在请求头上带着数据安全性差
  •  
 

4.2 localStorage

localStorage主要是前端开发人员,在前端设置,一旦数据保存在本地后,就可以避免再向服务器请求数据,因此减少不必要的数据请求,减少数据在浏览器和服务器间不必要地来回传递。

 

可以长期存储数据,没有时间限制,一天,一年,两年甚至更长,数据都可以使用。 
localStorage中一般浏览器支持的是5M大小,这个在不同的浏览器中localStorage会有所不同
优点:
  • localStorage拓展了cookie的4k限制
  • localStorage可以将第一次请求的5M大小数据直接存储到本地,相比于cookie可以节约带宽
  • localStorage的使用也是遵循同源策略的,所以不同的网站直接是不能共用相同的localStorage
缺点:
  • 需要手动删除,否则长期存在
  • 浏览器大小不一,版本的支持也不一样
  • localStorage只支持string类型的存储,JSON对象需要转换
  • localStorage本质上是对字符串的读取,如果存储内容多的话会消耗内存空间,会导致页面变卡

4.3 sessionStorage

sessionStorage主要是前端开发人员,在前端设置,sessionStorage(会话存储),只有在浏览器被关闭之前使用,创建另一个页面时同时可以使用,关闭浏览器之后数据就会消失
存储上限限制:不同的浏览器存储的上限也不一样,但大多数浏览器把上限限制在5MB以下
 

4.4 websql

Web SQL 是在浏览器上模拟数据库,可以使用JS来操作SQL完成对数据的读写。它使用 SQL 来操纵客户端数据库的 API,这些 API 是异步的,规范中使用的方言是SQLlite。数据库还是在服务端,不建议使用,已废弃

4.5 indexDB

随着浏览器的功能不断增强,越来越多的网站开始考虑,将大量数据储存在客户端,这样可以减少从服务器获取数据,直接从本地获取数据。
现有的浏览器数据储存方案,都不适合储存大量数据:Cookie 的大小不超过4KB,且每次请求都会发送回服务器;LocalStorage 在 2.5MB 到 10MB 之间(各家浏览器不同),而且不提供搜索功能,不能建立自定义的索引。所以,需要一种新的解决方案,这就是 IndexedDB 诞生的背景。
通俗地说,IndexedDB 就是浏览器提供的本地数据库,它可以被网页脚本创建和操作。IndexedDB 允许储存大量数据,提供查找接口,还能建立索引。这些都是 LocalStorage 所不具备的。就数据库类型而言,IndexedDB 不属于关系型数据库(不支持 SQL 查询语句),更接近 NoSQL 数据库。
 

5.CDN的定义

CDN:Content Delivery Network/Content Ddistribute Network,即内容分发网络
客户端访问网站的过程:
没有CDN:
1、用户在浏览器访问栏中输入要访问的域名;
2、浏览器向DNS服务器请求对该域名的解析;
3、DNS服务器返回该域名的IP地址给浏览器
4、浏览器使用该IP地址向服务器请求内容。
5、服务器将用户请求的内容返回给浏览器。
使用了CDN:
1、用户在浏览器中输入要访问的域名。
2、浏览器向DNS服务器请求对域名进行解析。由于CDN对域名解析进行了调整,DNS服务器会最终将域名的解析权交给CNAME指向的CDN专用DNS服务器。
3、CDN的DNS服务器将CDN的负载均衡设备IP地址返回给用户。
4、用户向CDN的负载均衡设备发起内容URL访问请求。
5、CDN负载均衡设备会为用户选择一台合适的缓存服务器提供服务。
选择的依据包括:根据用户IP地址,判断哪一台服务器距离用户最近;根据用户所请求的URL中携带的内容名称,判断哪一台服务器上有用户所需内容;查询各个服务器的负载情况,判断哪一台服务器的负载较小。
基于以上这些依据的综合分析之后,负载均衡设置会把缓存服务器的IP地址返回给用户。
6、用户向缓存服务器发出请求。
7、缓存服务器响应用户请求,将用户所需内容传送到用户。
如果这台缓存服务器上并没有用户想要的内容,而负载均衡设备依然将它分配给了用户,那么这台服务器就要向它的上一级缓存服务器请求内容,直至追溯到网站的源服务器将内容拉取到本地。
 

二、关于缓存

没有CDN:浏览器缓存
使用了CDN:浏览器缓存+CDN缓存
在用户第一次访问网站后,网站的一些静态资源如图片等就会被下载到本地,作为缓存,当用户第二次访问该网站的时候,浏览器就会从缓存中加载资源,不用向服务器请求资源,从而提高了网站的访问速度,而若使用了CDN,当浏览器本地缓存的资源过期之后,浏览器不是直接向源站点请求资源,而是向CDN边缘节点请求资源,CDN边缘节点中也存在缓存,若CDN中的缓存也过期,那就由CDN边缘节点向源站点发出回源请求来获取最新资源。
 
浏览器缓存以及CDN缓存都有一套判断文件是否需要更新的机制:
浏览器在加载资源时,先根据这个资源的一些http header判断它是否命中强缓存,如果命中,浏览器直接从自己的缓存中读取资源,不会发请求到服务器,当强缓存没有命中的时候,浏览器一定会发送一个请求到服务器,服务器端依据资源的另外一些http header验证这个资源是否命中协商缓存,如果命中,服务器会将这个请求返回,但是不会返回这个资源的数据,而是告诉客户端可以直接从缓存中加载这个资源,于是浏览器还是从自己的缓存中加载资源,当协商缓存也没有命中的时候,浏览器直接从服务器加载资源数据。
CDN节点缓存机制在不同服务商中是不同的,但一般都遵循HTTP协议,通过http响应头中的Cache-Control:max-age的字段来设置CDN节点文件缓存时间。当客户端向CDN节点请求数据时,CDN会判断缓存数据是否过期,若没有过期,则直接将缓存数据返回给客户端,否则就向源站点发出请求,从源站点拉取最新数据,更新本地缓存,并将最新数据返回给客户端。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会显示from 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是服务器返回的一个绝对时间,在服务器时间与客户端时间相差较大时,缓存管理容易出现问题,比如随意修改下客户端时间,就能影响缓存命中的结果,所以在http1.1的时候,提出了一个新的header,也就是Cache-Control,这是一个相对时间,在进行缓存命中的时候,都是利用客户端时间进行判断,因此更有效安全一些,在配置缓存的时候,以秒为单位,用数值表示:如:Cache-Control:max-age=315360000,它的缓存过程是:
1、浏览器第一次跟服务器请求一个资源,服务器在返回这个资源的同时,在response的header加上Cache-Control的header
2、浏览器在接收到这个资源的时候,会把这个资源连同所有response header一起缓存下来
3、浏览器再次请求这个资源的时候,先从缓存中寻找,找到这个资源之后,再拿这个过期时间跟当前的请求时间比较,如果请求时间在过期时间之前,就能命中缓存,否则就不行。
4、如果缓存没有命中,浏览器直接从服务器加载资源时,Cache-Control在重新加载的时候会被更新
这两个header可以只用一个,也可以同时用两个,同时存在时,Cache-Control优先级高于Expires
1.2 强缓存的管理
两种方式来设置是否启用强缓存:
1、通过代码的方式,在web服务器返回的响应中添加Expires和Cache-Control Header
2、通过配置web服务器的方式,让web服务器在响应资源的时候统一添加Expires和Cache-Control Header
1.3 强缓存的应用
强缓存是前端性能优化最有力的工具,对于有大量静态资源的网页,一定要利用强缓存,提高响应速度,通常是为这些静态资源全部配置一个超时时间超长的Expires或Cache-Control,这样用户只会在第一次访问网站时加载静态资源,其他时间只要缓存没有失效并且用户没有强制刷新的条件下都会从缓存中加载。
然而这种缓存配置方式会带来一个问题,就是当资源更新时,客户端由于有缓存不会向服务器请求最新的资源,这个问题已有解决方案:
通过更新页面中引用的资源路径,让浏览器主动放弃缓存,加载新资源。
但要实现有更新的文件才需要浏览器重新加载,因此必须让url的修改与文件内容相关联,利用数据摘要算法对文件求摘要信息,摘要信息与文件内容一一对应,这一点许多前端构建工具都做到了,如webpack
1.4 浏览器默认缓存使开发环境下常因为资源没有及时更新而看不到效果
解决方法:
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始终被设置为不缓存
1.5 发布问题
发布问题:若页面和它引用的资源路径同时更新了,不管是先部署页面还是先部署资源都会带来各种问题,这是由于资源是覆盖式发布的,即用待发布资源覆盖已发布资源。
解决办法就是实现非覆盖式发布:把有修改的资源文件作为一个新的文件发布,不对已有的资源文件进行覆盖,这样用户还可以请求旧的资源文件,不至于发生页面错乱的问题,这样先部署静态资源,再覆盖式部署页面,等到用户访问新页面的时候,新的资源文件也已发布,就可以正确请求,即可解决问题。
2.1 协商缓存
如果命中协商缓存,请求响应返回的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】会同时启用,协商缓存需要配合强缓存使用
 
 
 

什么是DNS?

Domain Name System,域名系统作用是将用户输入的域名解析为IP地址所对应得网站资源,使得用户可以访问到网站。 它是由解析器和域名服务器组成的。域名服务器是指保存有该网络中所有主机的域名和对应IP地址,并具有将域名转换为IP地址功能的服务器。其中域名必须对应一个IP地址,而IP地址不一定有域名。
 DNS本质是用于TCP/IP应用程序的数据库,该数据库中记录了域名和IP的对应关系。  DNS类似 “翻译官”
DNS就是把域名和IP地址联系在一起的服务,有了DNS服务器,你就不用输入IP地址来访问一个网站,可以通过输入网址访问。
DNS 是域名系统 (Domain Name System) 的缩写,是因特网的一项核心服务,它作为可以将域名和IP地址相互映射的一个分布式数据库,能够使人更方便的访问互联网,而不用去记住能够被机器直接读取的IP数串。这也是DNS的官方说法。
DNS的作用:在互联网中,其实没有类似于www.xxx.com这种域名方式,而替代的是以IP地址,如222.222.222.222,那我们在IE地址栏中应当输入222.222.222.222才能打开网站www.xxx.com
但我们细想一下,互联网上的网站成千上万,如果每个网站登陆都需要记住一大串数字,那是不是特别不方便,对于记忆力不强的人,根本无法记住这么烦琐的数字。这个时候DNS就出现了,它的作用就是将222.222.222.222解析为www.xxx.com,那么我们登陆的时候就直接输入域名就可以了。  每个ip对应的就是资源所在的位置
二:DNS重要知识点
 
        首先了解域名的组成,域名由好几部分组成,首先是根 . 根是一个点,写在com等顶级域名后边,现在一般省略。
 
        域名构成如下:
 
        一级域名:.com  .org  .cn  .edu等。顶级域名一般有含义,如学校、国家、政府机构等。
 
        二级域名:baidu  qq  csdn等。一般可以自己进行申请。
 
        三级域名:可行定制。如www  blog等。
 
        例子:www.alita99.com解析:一、前边DNS服务器均没有该域名信息,会来到根服务器,根服务器发现你一级域名是com,就会给一个专门解析com的DNS服务器地址,然后来到该DNS服务器,然后该服务器就会给你alita99.com对应的域的ip地址,你电脑拿到ip地址去访问该域名下的www这台主机(可能配置有其他三级域名主机,www只是一个常用的)。二、DNS服务器一般会先到缓存中去查询域名,若缓存中没有才会去上一级DNS服务器请求,且拿到新的域名ip后会保存在缓存中,在一定时间内其他主机访问该域名可以快速给出ip地址。
 
域名解析完整过程:
 
        1:用户向localDNS发起请求查询输入域名对应的IP地址(若有缓存直接返回,否则去rootDNS查询);
        2:localDNS迭代向rootDNS查询,逐级迭代,rootDNS=>顶级DNS=>次级DNS;
        3:获得次级DNS后,localDNS向次级DNS发起域名解析请求;
        4:次级DNS通常会将域名CNAME【如果有有CNAME则解析CNAME对应的CDN服务,否则的话默认为普通请求,直接返回解析到的IP】到另一个域名,这个域名最终会被指向CDN网络中的智能DNS负载均衡系统;
        5:DNS负载均衡系统通过一些智能算法,将最合适的CDN节点IP地址返回给localDNS;
        6:localDNS将获得的IP地址返回给用户;
        7:用户得到节点的IP地址后,向该节点发起访问请求;
        8:CDN节点返回请求文件,如果该节点中请求的文件不存在,就会再回到源站获取这个文件,然后返回给用户。
 
   DNS查询方式
 
        DNS查询方式主要有迭代和递归,递归是主机等待,其他DNS服务器进行询问。迭代是DNS每次将结果给主机,让主机自己起询问下一级DNS服务器。主要有几个区分方式:
 
        1.递归就是:问问问问问----答答答答答       迭代就是:问答问答问答问答问答
 
        2.递归是问的人一直在变化,迭代就是问的人不变。 
 
 

posted on 2019-08-02 14:35  struggleForLife  阅读(5310)  评论(3编辑  收藏  举报