详解 web 缓存
为什么要缓存
- 请求更快:通过将内容缓存在本地或距离最近的缓存服务器(CDN),大大加快网站加载速度。
- 节省带宽:对于已缓存的文件,可以减少请求带宽甚至无需请求网络。
- 降低服务器压力:在大量用户并发的情况下,服务器的性能受到限制,此时将一些静态资源放在网络的多个节点,可以起到负载均衡的作用,降低服务器压力。
缓存分类
- 服务端缓存(CDN)
- 客户端缓存(浏览器)
客户端浏览器的缓存类型
强缓存,返回状态码 200,不会发送HTTP请求
协商缓存,返回状态码 304,会发送HTTP请求
如何设置缓存
如何让浏览器缓存我们的静态资源,这也是一个需要由服务器与浏览器共同协作完成的事情。
协商缓存
在普通的 GET 请求报文中,附带 If-Modified-Since
字段,它将询问服务器端是否有更新的版本,本地文件的最后修改时间。如果服务器端没有新的版本,只需响应一个304状态码,客户端就使用本地版本。如果服务器端有新的版本,就将新的内容发送给客户端,客户端放弃本地版本。
服务端设置响应头
last-modified: Tue, 23 Apr 2019 10:09:21 GMT
客户端下次请求头会携带
if-modified-since: Tue, 23 Apr 2019 10:09:21 GMT
这里的条件请求采用时间戳的方式实现,但是时间戳有一些缺陷存在。文件的时间戳改动但内容并不一定改动。时间戳只能精确到秒级别,更新频繁的内容将无法生效。
为此 HTTP 1.1 中引入了 ETag 来解决这个问题。ETag 的全称是 Entity Tag,由服务器端生成,服务器端可以决定它的生成规则。通常根据文件内容生成散列值。
服务端设置响应头
etag: "5cbee451-7818"
客户端下次请求头会携带
if-none-match: "5cbee451-7818"
强缓存
尽管条件请求可以在文件内容没有修改的情况下节省带宽,但是它依然会发起一个 HTTP 请求,使得客户端依然会花一定时间来等待响应。可见最好的方案就是连条件请求都不用发起。
在响应里设置 Expires 或 Cache-Control 头,浏览器将根据该值进行缓存。
服务端设置响应头
expires: Tue, 31 Dec 2019 08:16:58 GMT
但是 Expires 的缺陷在于浏览器与服务器之间的时间可能不一致,这可能会带来一些问题,比如文件提前过期,或者到期后并没有被删除。在这种情况下,Cache-Control 以更丰富的形式,实现相同的功能
服务端设置响应头
cache-control: max-age=300
清除缓存
虽然我们知晓了如何设置缓存,以达到节省网络带宽的目的,但是缓存一旦设定,当服务器端意外更新内容时,却无法通知客户端更新。这使得我们在使用缓存时也要为其设定版本号,所幸浏览器是根据 URL 进行缓存,那么一旦内容有所更新时,我们就让浏览器发起新的 URL 请求,使得新内容能够被客户端更新。一般的更新机制有如下两种。
- 每次发布,路径中跟随 Web 应用的版本号:http://url.com/?v=20130501。
- 每次发布,路径中跟随该文件内容的hash值:http://url.com/?hash=afadfadwe。
CDN缓存
通过上图,我们可以了解到,使用了 CDN 缓存后的网站的访问过程为:
- 用户向浏览器提供要访问的域名;
- 浏览器调用域名解析库对域名进行解析,由于 CDN 对域名解析过程进行了调整,所以解析函数库一般得到的是该域名对应的 CNAME 记录,为了得到实际IP地址,浏览器需要再次对获得的 CNAME 域名进行解析以得到实际的IP地址;在此过程中,使用的全局负载均衡 DNS 解析,如根据地理位置信 息解析对应的IP地址,使得用户能就近访问。
- 此次解析得到 CDN 缓存服务器的IP地址,浏览器在得到实际的IP地址以后,向缓存服务器发出访问请求;
- 若请求文件并未修改,返回 304(充当服务器的角色)。若当前文件已过期,则缓存服务器根据浏览器提供的要访问的域名,通过 Cache 内部专用 DNS 解析得到此域名的实际 IP 地址,再由缓存服务器向此实际IP地址提交访问请求;
- 缓存服务器从实际IP地址得得到内容以后,一方面在本地进行保存,以备以后使用,二方面把获取的数据返回给客户端,完成数据服务过程;
- 客户端得到由缓存服务器返回的数据以后显示出来并完成整个浏览的数据请求过程。
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论