Cache缓存机制

2,130 阅读6分钟
原文链接: hiybm.github.io

Attention:The following is totally personal view, correct if wrong, PLEASE.Take a deep breath ! ok, that’s better, keep coding.

论,如何定义一个前端工程师。前天看了篇文章,作者把前端攻城狮称作是所有攻城狮角色中最具有也最需要‘工匠精神’的攻城狮。从最直观的角度来讲就是视觉方面,不仅要百分百还原设计稿(静态以及动态交互),还要考虑代码是否工整、冗余、复用、性能等方面问题,而且说得更博大一些还要培养点产品和设计的思维(培养个P啊,这是开发和他们的鸿沟,纯属扯淡。)正儿八经的对于前端不只是会JavaScript就行了,要学的东西真是太多了,作为一名初生牛犊的我,还是相当有必要扩展下一个web开发要掌握的知识面,比如今天要总结的缓存机制。

一、缓存的概念:

Web缓存是指一个Web资源(如html页面,图片,js等)存在于Web服务器和客户端(浏览器)之间的副本。缓存会根据进来的请求保存输出内容的副本;当下一个请求来到的时候,如果是相同的URL,缓存会根据缓存机制决定是直接使用副本响应访问请求,还是向源服务器再次发送请求。比较常见的就是浏览器会缓存访问过网站的网页,当再次访问这个URL地址的时候,如果网页没有更新,就不会再次下载网页,而是直接使用本地缓存的网页。只有当网站明确标识资源已经更新,浏览器才会再次下载网页。

二、缓存的作用(简述):
  • 减少网络带宽消耗无论对于网站运营者或者用户,带宽都代表着金钱,过多的带宽消耗,只会便宜了网络运营商。当Web缓存副本被使用时,只会产生极小的网络流量,可以有效的降低运营成本。

  • 降低服务器压力给网络资源设定有效期之后,用户可以重复使用本地的缓存,减少对源服务器的请求,间接降低服务器的压力。同时,搜索引擎的爬虫机器人也能根据过期机制降低爬取的频率,也能有效降低服务器的压力。

  • 减少网络延迟,提升页面渲染速度带宽对于个人网站运营者来说是十分重要,缓存的使用能够明显加快页面打开速度,达到更好的体验。

三、缓存的类型(手打星号):
  • 数据库数据缓存:为了提供查询数据库表的性能,一般会将查询后的数据放到内存中进行缓存,以便下次使用时直接从内存返回,提高响应效率

  • 服务器端缓存:a.代理服务器缓存-浏览器端和源服务器之间的一个中间服务器,共享缓存,同一个副本会被重用多次,为大多用户提供服务;b. CDN缓存Content Delivery Network, 顾名思义,内容分发网络),CDN和CDN缓存是两个概念,切勿混淆,本篇文章谈缓存。举个例子,如果你要更新CDN上的资源,然后你把资源直接放到了CDN替换上边的旧资源,文件名未修改(路经以及代码未改),这时就很有可能造成页面读取旧缓存的情况出现,而这时倘若出现在线上……[泪奔-.-!!],so ! 切记替换CDN资源时加个时间戳或是设置好请求报头里的参数,避免飞来横锅。

  • 浏览器缓存:这个就是常见在浏览器端的缓存,常用清除方法:控制台-Application-Clear storage-选中Cache-Clear site data;Ctrl+F5(强制刷新);鼠标按住页面刷新按钮不放或按住滑动,会出现刷新选项(截不了图sad)选项包括:正常重新加载 Ctrl + R || 硬性重新加载 Ctrl + shift + R || 清空缓存并硬性重新加载 ;不过我发现并不是所有的网站都可以,原因可能是部分站点设置的缓存不同(有待研究)。

  • web应用层缓存:这种缓存指的是代码层面上,通过代码逻辑和缓存策略实现对数据、页面、图片等资源的缓存。

四、生成缓存

本文要介绍的是浏览器缓存,其实就是指服务器和客户端(浏览器)之间的一个副本(static sources like html/css/js)。一个完整的网络请求大概是这样的;第一次请求: 客户端发送请求 -> 本地无缓存 -> 向服务器发送请求 -> 返回静态资源 -> 呈现(并缓存到本地)

第二次请求:如下图一所示:

第二次请求流程

这里要先说下缓存中相关的消息报头参数,具体如图二(标红处重点理解 ):

消息报头参数

除了图中标红的参数,这里再点明一下有必要了解的几项:

  • no-cache: 使用no-cache 指令的目的是为了防止从缓存中返回过期的资源,客户端发送的请求中如果包含no-cache指令,则表示客户端将不会接收缓存过的响应。从字面意思上很容易把no-cache误解成为不缓存,但事实上no-cache代表不缓存过期的资源,缓存会向源服务器进行有效期确认后处理资源,也许称为do-not-serve-from-cache-without-revalidate更合适。no-cache 才是真正地不进行缓存,请读者注意区别理解。
  • must-revalidate: 可缓存但必须再向源服务器进行确认。
  • no-store: 暗示请求(和对应的响应)或响应中包含机密信息,该指令规定缓存不能在本地存储请求或响应的任一部分。

现在讲图一中发生的第二次请求,此次请求会读取本地的缓存副本,但首先读取的时候浏览器会判断缓存的过期时间(假如设置的话),倘若没有过期就会读取缓存。倘若过期就会和服务器校对ETag(Entity tag用于缓存验证)如果ETag非空,浏览器就会把ETag的值给If-None-Match进行对比,同时,也会对比Last-ModifiedIf-Modified-Since的值,如果相同则证明服务器没有修改内容,就会返回304 Not-Modified读取本地缓存,HTTP304状态码是指该本地缓存资源与服务端资源相比没有被修改过所以会直接读取本地缓存内容,反之重新向服务器发出请求并返回。此时Last-ModifiedETag的值都会被重置。

以上所述如有错误之处还请指正。