013: 如何理解 HTTP 缓存及缓存代理?

关于强缓存协商缓存的内容,我已经在能不能说一说浏览器缓存做了详细分析,小结如下:

首先通过 Cache-Control 验证强缓存是否可用

  • 如果强缓存可用,直接使用
  • 否则进入协商缓存,即发送 HTTP 请求,服务器通过请求头中的If-Modified-Since或者If-None-Match这些条件请求字段检查资源是否更新
    • 若资源更新,返回资源和200状态码
    • 否则,返回304,告诉浏览器直接从缓存获取资源

这一节我们主要来说说另外一种缓存方式: 代理缓存

为什么产生代理缓存?

对于源服务器来说,它也是有缓存的,比如Redis, Memcache,但对于 HTTP 缓存来说,如果每次客户端缓存失效都要到源服务器获取,那给源服务器的压力是很大的。

由此引入了缓存代理的机制。让代理服务器接管一部分的服务端HTTP缓存,客户端缓存过期后就近到代理缓存中获取,代理缓存过期了才请求源服务器,这样流量巨大的时候能明显降低源服务器的压力。

那缓存代理究竟是如何做到的呢?

总的来说,缓存代理的控制分为两部分,一部分是源服务器端的控制,一部分是客户端的控制。

源服务器的缓存控制

private 和 public

在源服务器的响应头中,会加上Cache-Control这个字段进行缓存控制字段,那么它的值当中可以加入private或者public表示是否允许代理服务器缓存,前者禁止,后者为允许。

比如对于一些非常私密的数据,如果缓存到代理服务器,别人直接访问代理就可以拿到这些数据,是非常危险的,因此对于这些数据一般是不会允许代理服务器进行缓存的,将响应头部的Cache-Control设为private,而不是public

proxy-revalidate

must-revalidate的意思是客户端缓存过期就去源服务器获取,而proxy-revalidate则表示代理服务器的缓存过期后到源服务器获取。

s-maxage

sshare的意思,限定了缓存在代理服务器中可以存放多久,和限制客户端缓存时间的max-age并不冲突。

讲了这几个字段,我们不妨来举个小例子,源服务器在响应头中加入这样一个字段:

Cache-Control: public, max-age=1000, s-maxage=2000

相当于源服务器说: 我这个响应是允许代理服务器缓存的,客户端缓存过期了到代理中拿,并且在客户端的缓存时间为 1000 秒,在代理服务器中的缓存时间为 2000 s。

客户端的缓存控制

max-stale 和 min-fresh

在客户端的请求头中,可以加入这两个字段,来对代理服务器上的缓存进行宽容限制操作。比如:

max-stale: 5

表示客户端到代理服务器上拿缓存的时候,即使代理缓存过期了也不要紧,只要过期时间在5秒之内,还是可以从代理中获取的。

又比如:

min-fresh: 5

表示代理缓存需要一定的新鲜度,不要等到缓存刚好到期再拿,一定要在到期前 5 秒之前的时间拿,否则拿不到。

only-if-cached

这个字段加上后表示客户端只会接受代理缓存,而不会接受源服务器的响应。如果代理缓存无效,则直接返回504(Gateway Timeout)

以上便是缓存代理的内容,涉及的字段比较多,希望能好好回顾一下,加深理解。

微信公众号: 前端三元同学

获取更多资料/联系加交流群