HTTP缓存策略

HTTP浏览器缓存解析及Nginx实战

Posted by wang chong on March 16, 2019

缓存的定义

缓存就是数据交换的缓冲区(称作Cache),这个概念最初是来自于内存和CPU。当某一硬件要读取数据时,会首先从缓存中查找需要的数据,如果找到了则直接执行,找不到的话则从内存中找。由于缓存的运行速度比内存快得多,故缓存的作用就是帮助硬件更快地运行。

Web缓存

客户端和服务器之间是通过请求和响应来相互通信的。

请求的本质就是从客户端向服务器发起请求,获取服务器资源(图片、文件、数据)返回给客户端。

Web缓存就是保存从服务器响应的资源,当发起下一次请求请求同样的资源的时候,不需要再请求客户端,直接从缓存中得到。

缓存类型

HTTP缓存分为强缓存和协商缓存,共有四种缓存类型。

强缓存

浏览器第一次请求服务器时,服务器会将文件和缓存时间一起返回给客户端,客户端将二者备份至缓存数据库中。再次请求数据的时候,客户端会根据文件的过期时间去判断文件是否过期,如果未过期就从缓存数据库中拿文件,如果过期,则重新从服务器上请求文件。

Cache-Control

Cache-Control是优先级最高的强缓存,它有一下值:

  1. Cache-Control: no-cache必须先与代理服务器确认是否更改,然后在在决定使用缓存还是请求,类似于协商缓存(304)。可以用于不让浏览器自己缓存,我们自己来控制缓存,让文件更可控。
  2. Cache-Control: no-store 才是真正的不缓存数据到本地。
  3. Cache-Control: public 可以被所有用户缓存(多用户共享),包括终端和CDN等中间代理服务器。
  4. Cache-Control: private 只能被终端浏览器缓存(而且是私有缓存),不允许中继缓存服务器进行缓存
  5. Cache-Control: must-revalidate如果缓存内容失效,请求必须发送服务器进行验证。
  6. Cache-Control: max-age=s 设置缓存时间,缓存内容在s秒后失效,仅HTTP1.1可用

第一次请求服务器,响应头会返回一个max-age,表示文件的缓存过期时间。

第二次请求 客户端会校验文件是否过期,如果文件未过期则直接使用本地缓存,返回返状态码200(from memory cache)或200(from disk cache),如果过期则进行协商缓存。

Expires

Expires是http1.0提出的一个表示资源过期时间的header,它描述的是一个绝对时间,由服务器返回。正是因为又服务器返回,而服务器时间和本地时间不同,所以它有时候是不准的。

浏览器第一次请求服务器,响应头里会返回一个Expires的文件过期时间。

第二次请求服务器时,客户端使用本地时间和文件的过期时间相比对,如果未过期则直接使用本地缓存返回状态码200(from memory cache)或200(from disk cache)则进行协商缓存。

协商缓存

浏览器第一次请求服务器的时候,服务器会将缓存标识和资源一起响应给客户端,客户端将二者备份至缓存服务器。再次请求数据时,客户端将备份的缓存标识发给服务器,服务器根据缓存标识决定是从缓存拿数据还是从服务器上请求数据。如果判断成功,返回304状态码,通知客户端从缓存中拿数据;如果判断失败,则再次请求进行缓存。

Etag/If-None-Match

Etag规则是通过文件的内容来判断该不该读缓存,服务器把文件读出来,通过某种方式为文件加上标识(一般是通过MD5进行base64加密得出hash值,把这个值设置在相应头里面),客户端下一次请求通过If-None-Mach带过来,服务器再比对和当前文件内容加密得出的hash值是否相同,如果相同则说明文件内容没有发生变化,可以从缓存中获取,如果不相同则文件发生变化,重新请求。这种是最准确的方式,同样也是最耗时的。

客户端第一次请求服务器,响应头中返回包含文件缓存标识的Etag标签。

客户端第二次请求服务器,请求头包含IF-None-Match,服务器获得缓存标识后,用该标识和文件hash值进行比对。比对成功,则文件未过期,从缓存中拿返回状态码304,比对失败,重新请求文件并缓存,返回状态码200

Last-Modified/If-Modified-Since

Last-Modefied规则是通过文件的最后修改时间来判断该不该读缓存,服务器端设置响应头Last-Modified,表示最后修改时间。客户端再次请求服务器的时候通过请求头If-Modified-Since把最后修改时间提交给服务器,服务器判断客户端返回的时间和文件的时候相比对,如果相等则表示未过期,可以从缓存中拿,如果不相等则表示缓存已过期,再次请求并缓存。

第一次请求服务器,响应头中返回Last-Modified 头,表示文件最后修改时间。

第二次请求服务器,请求头中返回If-Modified-Since头,把文件最后修改时间返回给服务器,服务器来做决策。

什么样的文件可以缓存,什么样是文件不可以缓存?

  1. 静态资源可以缓存
  2. 动态资源不能缓存
  3. 需要根据cookie拿到信息不能缓存
  4. post请求不能缓存
  5. HTTP头中没有包含缓存策略标记的不能缓存

缓存策略图

Nginx服务器缓存实践

在Web缓存中我们一般用,Nginx作为代理服务器做缓存。这样做比较简单一些。

Nginx服务器是默认开启Etag规则的。可以通过一下几项配置浏览器缓存。

结果为