HTTP 强缓存和协商缓存

1,977 阅读4分钟

前言

强缓存: 浏览器不会向服务器发送任何请求,直接从本地缓存中读取文件并返回 Status Code: 200 OK。常见如下:

Status Code: 200 OK (from memory cache) // 内存缓存
Status Code: 200 OK (from disk cache)   // 磁盘缓存

读取本地的缓存有from memory cachefrom disk cache的区别: 这是浏览器的缓存策略。一般memory cache一般存放比较小的文件,disk cache一般存放比较大的文件。

协商缓存: 向服务器发送请求,服务器会根据这个请求的request header的一些参数来判断是否命中协商缓存。如果命中,则返回304状态码,并带上新的response header通知浏览器从缓存中读取资源。

Response Headers中展示如下图:

工作流程

  1. 浏览器在加载资源时,根据请求头的expirescache-control判断是否命中强缓存,若命中则直接从缓存读取资源,不会发请求到服务器Status Code显示为200 OK (from memory cache)200 OK (from disk cache)
  2. 如果没有命中强缓存,则浏览器会发送一个请求到服务器,通过Etaglast-modified验证资源是否命中协商缓存,如果命中,服务器会将这个请求返回,状态码为304 Not Modified,但是不会返回这个资源的数据,浏览器则依然是从缓存中读取资源
  3. 如果前面两个都没有命中,则直接从服务器加载资源,并返回状态码200

详细说明

1. expirescache-control

首先cache-control的优先级高于expirescache-controlHTTP/ 1.1中出现,表示的是相对时间。而ExpiresHTTP/ 1.0中出现,标识一个资源过期时间,是一个绝对时间,由服务器返回,但由于Expires 受限于本地时间,如果修改了本地时间,则可能会造成缓存失效,因此Expires有这样的bug存在。

HTTP HEADER中常见返回值:

Expires: Wed, 15 Apr 2020 01:09:53 GMT

Cache-Control: max-age=86400
Cache-Control: no-cache // 可以存储在本地缓存区中,只是在于原始服务器进行新鲜度验证之前,缓存不能将其提供给客户端使用
Cache-Control: no-store // 真正的不缓存数据到本地
Cache-Control: public // 以被所有用户缓存(多用户共享),包括终端和CDN等中间代理服务器
Cache-Control: private // 只能被终端浏览器缓存(而且是私有缓存),不允许中继缓存服务器进行缓存

2. ETagIf-None-Match

ETagIf-None-Match是组合来使用的。Etag就像一个指纹,资源变化都会导致ETag变化,跟最后修改时间没有关系,因此,ETag可以保证每一个资源是唯一的。If-None-Matchheader会将上次返回的Etag发送给服务器,询问该资源的Etag是否有更新,有变动就会发送新的资源回来。

ETag的优先级比Last-Modified更高

参考文档: ETag

浏览器在请求时在Request Headers中携带内容如下:

If-None-Match: W/"5exxxd45-9xx"

If-None-Match的值为上次返回的Etag 如果资源未改变,返回状态码如下:

Status Code: 304 Not Modified

3. Last-ModifiedIf-Modified-Since

Last-Modified 表示本地文件最后修改日期,浏览器会在request header加上If-Modified-Since(上次返回的Last-Modified的值),如下图所示,询问服务器在该日期后资源是否有更新,如果有更新的话就会将新的资源发送回来。但是如果在本地打开缓存文件,就会造成Last-Modified被修改,所以在HTTP/1.1出现了ETag

If-Modified-Since: Fri, 10 Apr 2020 14:05:57 GMT

缓存的选择

协商缓存需要配合强缓存使用,如果不启用强缓存的话,协商缓存根本没有意义。 大部分web服务器都默认开启协商缓存,而且是同时启用【Last-Modified,If-Modified-Since】【ETag、If-None-Match】Etag等一般是在nginx中配置完成的。

希望对你能有所帮助!