浏览器缓存机制
前言:
每当我们第二次打开同一个网页的时候,
size部分的form memory cache即为从缓存中读取,
我们可以发现有很多内容都是直接从缓存中读取到的。
1、浏览器缓存的优缺点
优点:
- 加快页面打开速度
- 降低服务器压力
- 减少网络损耗
缺点:
- 缓存没有清理机制,这些缓存的文件会永久地保存在机器上
- 给开发带来困扰,更新了开发内容,但是浏览器还是读取的原来缓存的内容,新的开发内容无法体现在浏览器上
2、web缓存的分类
web缓存存在于服务器和客户端之间
a.数据库数据缓存
Web应用,特别是社交网络服务类型的应用,往往关系比较复杂,数据库表繁多,如果频繁进行数据库查询,很容易导致数据库不堪重荷。为了提供查询的性能,会将查询后的数据放到内存中进行缓存,下次查询时,直接从内存缓存直接返回,提供响应效率。比如常用的缓存方案有memcached,redis等。
b.服务器端缓存
代理服务器缓存
代理服务器是浏览器和源服务器之间的中间服务器,浏览器先向这个中间服务器发起Web请求,经过处理后(比如权限验证,缓存匹配等),再将请求转发到源服务器。代理服务器缓存的运作原理跟浏览器的运作原理差不多,只是规模更大。可以把它理解为一个共享缓存,不只为一个用户服务,一般为大量用户提供服务,因此在减少相应时间和带宽使用方面很有效,同一个副本会被重用多次。常见代理服务器缓存解决方案有Squid,Nginx,Apache等。
CDN缓存
CDN(Content delivery networks)缓存,也叫网关缓存、反向代理缓存。CDN缓存一般是由网站管理员自己部署,为了让他们的网站更容易扩展并获得更好的性能。浏览器先向CDN网关发起Web请求,网关服务器后面对应着一台或多台负载均衡源服务器,会根据它们的负载请求,动态将请求转发到合适的源服务器上。虽然这种架构负载均衡源服务器之间的缓存没法共享,但却拥有更好的处扩展性。从浏览器角度来看,整个CDN就是一个源服务器,浏览器和服务器之间的缓存机制,在这种架构下同样适用。
c.浏览器端缓存
浏览器缓存根据一套与服务器约定的规则进行工作,在同一个会话过程中会检查一次并确定缓存的副本足够新。如果你浏览过程中,比如前进或后退,访问到同一个图片,这些图片可以从浏览器缓存中调出而即时显现。
d.Web应用层缓存
应用层缓存指的是从代码层面上,通过代码逻辑和缓存策略,实现对数据,页面,图片等资源的缓存,可以根据实际情况选择将数据存在文件系统或者内存中,减少数据库查询或者读写瓶颈,提高响应效率。
3、浏览器缓存控制方法
a、meta标签控制
<META HTTP-EQUIV="Pragma" CONTENT="no-cache">
上述代码作用为告诉浏览器当前页面不需要被缓存,每次请求页面都需要去服务器请求资源。
b、http头信息控制
浏览器每次在向服务器发起 HTTP 请求获得请求结果(包含 HTTP 头信息各种字段)后,会根据响应报文中 HTTP 头的缓存标识字段(后面我们会知道这个字段就是 Expires 和 Cache-Control),来决定是否将请求结果存入浏览器缓存中。
浏览器每次在向服务器发起 HTTP 请求时,都会查找浏览器缓存中是否存在其相应的请求结果,然后根据缓存标识字段来决定其是直接使用之前缓存的副本还是再次向服务器发出 HTTP 请求。
对于每次浏览器第一次 HTTP 请求来说,浏览器缓存中并不存在其请求资源相应的副本,这时浏览器便会直接向服务器发出 HTTP 请求来获得相应的请求结果,并根据缓存标识字段,来决定是否将请求结果作为副本存入浏览器缓存中。
HTTP 保持已缓存数据与服务器数据之间充分一致的机制称为文档过期和服务器再验证。而从浏览器缓存分类来看,也有将其分为强制缓存和协商缓存。
下面我就文档过期和服务器再验证的机制做详细的介绍,下面表述的过程都是指浏览器缓存中已经存在其相应资源副本的情况。
当浏览器发起 HTTP 请求时,会根据浏览器缓存中的缓存标识字段来验证文档(资源副本)是否过期。
上述说的缓存标识字段便是 Expires 和 Cache-Control。
Expires 是服务器端在响应请求时用来规定资源的失效时间。
Cache-Control 是服务器端在响应请求时用来规定资源是否需要被浏览器缓存以及缓存的有效时间等。
Cache-Control 主要取值如下:
- public:所有内容都将被缓存(客户端和代理服务器都可缓存)
- private:内容只缓存到私有缓存中(仅客户端可以缓存,代理服务器不可缓存)
- no-cache:必须先与服务器确认返回的响应是否被更改,然后才能使用该响应来满足后续对同一个网址的请求。因此,如果存在合适的验证令牌(ETag),no-cache 会发起往返通信来验证缓存的响应,如果资源未被更改,可以避免下载
- no-store:所有内容都不会被缓存或 Internet 临时文件中
- must-revalidation/proxy-revalidation:如果缓存的内容失效,请求必须发送到服务器/代理以进行重新验证
- max-age=xxx:缓存的内容将在 xxx 秒后失效
这里需要注意的是,no-cache 的作用是指跳过文档过期的验证而直接进行服务器再验证,而 no-store 是指资源禁止被缓存。
Expires 是 HTTP 1.0 的字段,而 Cache-Control 是 HTTP 1.1 的字段,当 Expires 与 Cache-Control 同时存在时,Cache-Control 的优先级要高于 Expires。
在浏览器缓存中根据 Expires 和 Cache-Control 的值来验证文档(资源副本)是否过期的过程,称为 HTTP 的文档过期验证机制。若是文档没有过期,则浏览器会直接使用缓存中的文档作为返回结果,若是文档已经过期了,则需要进行服务器再验证。
服务器再验证
在浏览器缓存中,还保存了其它关于资源副本的描述字段,这些字段都是服务器返回信息头带过来的,如 Last-Modified 和 Etag。
Last-Modified 是服务器端在响应请求时用来说明资源的最后修改时间。与之对应的是 If-Modified-Since 字段,在服务器再验证过程中,浏览器发送的 HTTP 请求的请求头中会带上 If-Modified-Since 字段,值为该资源 Last-Modified 属性的值。
当服务器端接收到带有 If-Modified-Since 属性的请求时,则会将 If-Modified-Since 属性的值与被请求资源的最后修改时间做对比。如果相同,说明资源没有新的修改,则响应 HTTP 304,浏览器会继续使用原先保存的该资源的副本;如果最后修改时间比较新,则说明资源被修改过,则响应 HTTP 200,并且返回最新的资源。
Etag 是服务器端在响应请求时用来说明资源在服务器端的唯一标识。与之对应的是 If-None-Match 字段,在服务器再验证过程中,浏览器发送的 HTTP 请求的请求头中会带上 If-Modified-Since 字段,值为该资源 Etag 属性的值。
当服务器端接收到带有 If-None-Match 属性的请求时,则会将 If-None-Match 属性的值与被请求资源的唯一标识做对比。如果相同,说明资源没有新的修改,则响应 HTTP 304,浏览器会继续使用原先保存的该资源的副本;如果不同,则说明资源被修改过,则响应 HTTP 200,并且返回最新的资源。
那么当 Last-Modified / If-Modified-Since 和 Etag / If-None-Match 同时存在是什么情况呢?
事实上,当两者同时存在时,Etag / If-None-Match 的优先级要高于 Last-Modified / If-Modified-Since,HTTP 1.1 中 Etag 的出现主要是为了解决几个 Last-Modified 比较难解决的问题:
- Last-Modified 标注的最后修改只能精确到秒级,如果某些文件在1秒钟以内被修改多次的话,它将不能准确标注文件的修改时间;
- 如果某些文件会被定期生成,但有时内容并没有任何变化,但 Last-Modified 却改变了,导致文件没法使用缓存;
- 有可能存在服务器没有准确获取文件修改时间,或者与代理服务器时间不一致等情形;
下面用一张流程图来完整说明当浏览器发起 HTTP 请求时缓存机制的过程:
以上。