缓存出现原因
查询和缓存总是配套出现,HTTP的GET请求也是一种查询,是客户端通过HTTP向服务器查询资源,为了减少不必要的查询,也为了降低网络负担,HTTP也引入了缓存。
缓存的Key就是URL,Value就是对应的回应Body。
缓存详解
当浏览器第一次请求一个URL的时候,服务器的响应头中有一个Cache-Control字段中记录了max-age,指的是缓存的有效时间。
缓存是由Cache-Control字段来控制的,注意只有客户端的请求头中的Cache-Control才能控制是否使用缓存。
1、no-store : 不使用缓存,服务器直接重新发送数据
2、no-cache: 叫做协商缓存,不直接使用缓存,服务器会判断缓存对应的资源是否被改变,如果被改变,就发送新数据,如果没改变,就发送一个304状态码,就说明缓存还可用。浏览器接受到后,就会直接使用缓存。
3、must-revalidate: 也叫做强制缓存,在缓存有效期内,直接使用缓存,如果过了有效期,就要去服务器验证。如果不能用就更新浏览器中的缓存,如果能用,就直接使用缓存。
从上图看,浏览器对应有几种操作,几种操作中对于缓存的操作是不一样的。
1、Ctrl + F5: 不会使用缓存
2、F5: 只会使用协议缓存
3、地址栏回车、前进后退、页面跳转、新开窗口等: 根据Cache-Control的值来选择使用强缓存还是协议缓存。
我们来主要说说强制缓存和协商缓存。
强制缓存 must-revalidate
强制缓存的做法是只要缓存还有效,就直接使用缓存,不会向服务器请求缓存对应的数据是否发生变换。
如果过了有效期,就去服务器服务器验证。如果缓存不可用就更新浏览器中的缓存;如果能用,就直接使用缓存。
协商缓存 no-cache
协商缓存每次都需要向服务器发送请求,只不过不是请求数据,而是验证缓存是否失效,如果缓存不失效,就使用缓存,如果缓存失效,服务器就重新发送数据。
HTTP缓存有两种方式来查看缓存对应的资源是否被更改了。
1、Last-Modified + If-Modified-Since
Last-Modified + If-Modified-Since 是通过修改时间来判断资源是否被更改的。
判断过程如下:
1、当浏览器第一次请求对应资源的时候,浏览器会返回相关的信息
Last-Modified 是 资源最新的修改时间
2、浏览器在发送验证请求的时候,会携带一个If-Modified-Since字段,字段对应的值为之前服务器发来的Last-Modified。
3、服务器在接收到客户端的验证请求后,会比对服务器中资源的最新修改时间是否大于If-Modified-Since中的时间。
1、如果大于说明在此期间,资源被修改了,就会重新发送对应的资源,并返回新的Last-Modified。
2、如果等于,HTTP就认为资源没有发生变化,就直接返回一个status code = 304的空响应包,代表缓存可用,当浏览器收到后,就直接使用缓存就可以了。
Last-Modified + If-Modified-Since存在以下缺点:
1、 虽然文件发生了更改,但是却是无效更改,比如加了个空格等操作,内容没有变,但是这种会造成 最新修改时间更新,会造成服务器重新将资源发送给浏览器。
2、 Last-Modified 的时间精确度是到 秒, 如果服务器发送给浏览器报文之内的一秒中资源发生了改变,客户端仍然是会使用缓存的,造成了浏览器无法读取到最新的数据。
2、ETag + If-Not-Match
ETag 是通过算法对缓存对应的资源生成的唯一值。
每个不同的资源对应的ETag都不一样,资源的变化会导致ETag变化。
1、 浏览器第一次获取数据的时候,服务器发送对应的ETag。
2、 当浏览器进行缓存验证的时候,会添加一个If-None-Match字段,对应的值为之前服务器发送的ETag值。
3、 服务器将收到的ETag 和 当前资源的ETag进行对比,如果不一致,就返回当前资源的ETag和对应的数据;如果一致,就返回HTTP 304。
浏览器直接使用缓存。
ETag + If-None-Match 解决了重复发送的问题,以及数据不一致的问题。