web性能之缓存

为了减少网络延迟以及降低服务器压力,web 开发中用了大量的缓存机制。 缓存的目的就是把需要花费昂贵开销的计算结果保存起来,在以后需要的时候直接取出,进而避免重复计算。

web 缓存有以下几种:

  • 客户端缓存
  • 代理服务器缓存
  • CDN 缓存
  • 数据库查询缓存
  • 应用计算缓存

客户端缓存

客户端(浏览器)缓存机制,其实主要就是 HTTP 协议定义的缓存机制, 通过以下 HTTP 协议头字段来控制 html 页面缓存:

规则 消息头 类型 作用
新鲜度 Expires Sun, 16 Oct 2016 05:43:02 GMT 响应 告诉浏览器在过期时间前可以使用副本(有可能存在时间不一致问题)
Pragma no-cache 响应 告诉浏览器忽略资源的缓存副本
Cache-Control no-cache 响应 告诉浏览器忽略资源的缓存副本,强制每次请求直接发送给源服务器
no-store 响应 强制缓存在任何情况下都不要保留任何副本
max-age=[秒] 响应 指明缓存副本的有效时长,从请求时间开始到过期时间之间的秒数
public 响应 任何途径的缓存者(本地缓存、代理服务器),可以无条件的缓存该资源
private 响应 只针对单个用户或实体(不同用户、窗口)缓存资源
Last-Modified Sun, 16 Oct 2016 05:43:02 GMT 响应 告诉浏览器当前资源的最后修改时间
If-Modified-Since Sun, 16 Oct 2016 05:43:02 GMT 请求 如果浏览器第一次请求时响应中 Last-Modified 非空,第二次请求同一资源时,会把它作为该项的值发给服务器
校验值 ETag 50b1c1d4f775c61:df3 请求 告知浏览器当前资源在服务器的唯一标识符(生成规则由服务器决定)
If-None-Match 50b1c1d4f775c61:df3 请求 如果浏览器第一次请求时响应中 ETag 非空,第二次请求同一资源时,会把它作为该项发给服务器
辅助 Vary Accept-Encoding 响应 辅助从多个缓存副本中筛选合适的版本(不同压缩算法产生的副本)

其中 Cache-Control 的缓存控制方式比较多,如下图:

http CacheControl

客户端和服务端对这些 HTTP 协议头字段的处理如下图:

browser http cache headers

用户在使用浏览器时各种操作对缓存的影响如下:

用户操作 Expires/Cache-Control Last-Modified/Etag
地址栏回车 有效 有效
页面链接跳转 有效 有效
新开窗口 有效 有效
前进、后退 有效 有效
F5 刷新 无效 有效
Ctrl+F5 刷新 无效 无效

代理服务器缓存

Web 代理服务器使用与客户端同样的缓存原理,只是规模更大。 代理服务器群为成百上千用户服务使用同样的机制, 大公司和 ISP 经常在他们的防火墙上架设代理缓存或者单独的缓存设备。

由于代理服务器缓存并非客户端或者源服务器的一部分,而是位于原网络之外,请求必须路由到它们才能起作用。

  • 手工设置你的浏览器:告诉浏览器使用哪个代理
  • 通过中间服务器:用户不必配置代理,所有的 web 请求均发送到中间服务器,其后将请求转发到后台网络

代理服务器缓存是一个共享缓存,不只为一个用户服务,经常为大量用户使用,因此在减少相应时间和带宽使用方面很有效。

CDN 缓存

由于网络通信的传播速度是存在物理极限的, 既然不能改变传播速度,那我们就可以缩短用户与服务的距离, 于是就引入了 CDN(Content Delivery Network,内容分发网络)。

CDN 缓存属于 Cache 服务器的一种, 其目的是通过在现有的 Internet 中增加一层新的网络架构, 将网站的内容发布到最接近用户的网络“边缘”,使用户可以就近取得所需的内容, 从而解决 Internet 网络拥塞状况,提高用户访问网站的响应速度。

数据库查询缓存

大多服务端的性能瓶颈是数据库查询,因为应用关系较复杂,数据表格繁多,频繁进行数据库查询又涉及到大量的磁盘 IO 和计算, 所以服务端引入了专门的缓存服务(redis、memcached 或应用自建缓存服务)以保存查询结果, 以便于下次查询时,直接从内存缓存直接返回,提供响应效率。

应用计算缓存

有些 Web 应用会有一些大量的 CPU 密集型的计算,这些计算结果也有可能保存在缓存服务内以便后用。

这些应用计算不仅可以在服务端,而且可以在客户端。

服务端缓存服务大多由 redis 或 memcached 提供,而客户端缓存服务可以由浏览器的 LocalStorage 或 SessionStorage API 提供。