http缓存简介

244 阅读4分钟

第一次发起http请求时是没有缓存的,以下情况都是在第二次发起请求时。

强制缓存

第一次请求返回的的响应头中带有cache-control或者expires,则说明这个资源设置了强制缓存。

在第二次请求这个资源的时候,会先在浏览器判断cache-control或者expires的值,如果成立,则命中强制缓存。

expires是http1.0的标准,cache-control是http1.1的标准。

  1. expires

    Expires: Mon, 31 Aug 2020 10:05:31 GMT
    

    expires指定资源的过期时间,在第一次请求时,由响应头返回,在第二次请求时,浏览器会把expires时间和本地时间做比较,如果未过期,直接使用浏览器的缓存,Status Code返回200 OK (from memory cache),否则重新向服务器发起请求。由于是和本地时间作比较,如果本地时间和服务器时间不一致,就会产生误差。

  2. cache-control

    Cache-Control: max-age=2592000
    Date: Sat, 08 Aug 2020 15:26:03 GMT
    

    cache-Control有多个指令,其中有一个max-age,max-age是个相对值,单位是秒,相对于第一次请求返回的响应头中的Date的值。如果超过了这个时间,就需要向服务器发起请求。

http请求中如果同时存在expires和cache-control,则需要同时满足,才会从浏览器获取缓存。

cache-control的优先级高于expires。expires是相对于本地时间,如果一旦修改了本地时间,和服务器时间不一致,这个判断就不准确了。

协商缓存

第一次发起请求时,如果响应头中携带ETag或者last-modified字段,说明服务器也会缓存这个资源。

发起第二次请求时,如果没有命中强制缓存,就会向服务器发起请求。

如果第一次请求时,返回的响应头中带有ETag或者last-modified字段,那么在第二次http请求时,会在请求头中加入if-none-match或者if-modified-since。

  1. ETag/if-none-match

    ETag: W/"5f2a8a31-224cc"
    

    第一次http请求返回的响应头中带有ETag,这个ETag是响应数据的一个hash值,在第二次请求时,会将这个hash值给到if-none-match,然后在服务器端计算数据的hash值进行比对,如果相等,则说明第二次请求的数据没有变化,返回状态码304,告诉浏览器端,直接取浏览器的缓存。如果不相等,则返回状态码200,生成新的ETag,返回新的响应数据,给到浏览器。

  2. last-modified/if-modified-since

    Last-Modified: Fri, 07 Aug 2020 09:23:33 GMT
    

    last-modified的目的和ETag一样,它是一个相对于服务器的绝对时间,会在第二次请求时将last-modified的值给到if-modified-since当作请求头中的信息发送给服务器。有2个缺陷,一是时间只能精确到1秒,如果在1秒内文件被修改,服务器无法准确标注文件的最后修改时间,二是服务器有时候会定期生成一些文件,这时候文件的内容并没有改变,但是last-modified值却发生了变化,导致文件无法使用缓存。

补充知识

  1. cache-control可设置的值:

    1. no-store:没有缓存,缓存中不得存储任何关于客户端和服务器的信息。
    2. no-cache:使用缓存但是需要发送到服务器校验是否过期。
    3. private:私有缓存,专用于某单个用户的缓存。
    4. public:公共缓存,该响应可以被任何中间人缓存。
    5. must-revalidate:验证方式,缓存在考虑使用一个陈旧的资源时,必须先校验他的状态,已过期的缓存将不被使用。
    6. max-age=123456:表示资源能够被缓存的最大时间。相对于expires而言,max-age是距离请求发起时间的秒数。针对应用中不会改变的文件,通常可以设置一定的时长以保证缓存有效,例如图片、css、js等静态资源。
  2. Pragma

    Pragma 是http1.0标准中定义的一个header属性,请求中包含Pragma的效果跟在头信息中定义Cache-Control: no-cache相同,但是HTTP的响应头没有明确定义这个属性,所以它不能拿来完全替代HTTP/1.1中定义的Cache-control头。通常定义Pragma以向后兼容基于HTTP/1.0的客户端。