缓存的作用
减少了冗余的数据传输,节省了网费;
减少了服务器的负担,大大提高了网站的性能;
加快了客户端加载网页的速度。
缓存分类
强制缓存 和 协商缓存
强制缓存如果生效,不需要再和服务器发生交互;而协商缓存不管是否生效,都需要和服务器发生交互;
两类缓存规则可以同时存在,强制缓存优先级高于协商缓存: 当强制缓存生效,就直接使用缓存,不用再进行 协商缓存。
强制缓存
在缓存数据未失效的情况下,可以直接使用缓存数据;
在没有缓存数据的时候,浏览器会向服务器请求数据时,服务器会将数据和缓存规则一并返回,缓存规则信息包含在响应 header 中。
缓存数据库在浏览器中。
协商缓存
协商缓存,需要进行比较判断是否可以使用缓存;
浏览器第一次请求数据时,服务器会将 缓存标识 与 数据 一起返回客户端,客户端将二者备份至缓存数据库中。
再次请求数据时,客户端将备份的缓存标识发送给服务器,服务器根据缓存标识进行判断,判断成功后,返回304状态码,通过客户端比较成功,可以使用缓存数据。
请求流程
第一次请求
网图第二次请求
网图缓存的具体实现
协商缓存
网图,对比缓存就是协商缓存1. Last-modified 通过最后修改时间来判断缓存是否可用
Last-modified:响应时告诉客户端此资源的最后修改时间;
if-Modified-Since:当资源过期时(使用Cache-Control标识的 max-aga),发现资源具有 Last-Modified 声明,则再次向服务器请求时带上 if-Modified-Since;
服务器收到请求后发现有 if-Modified-Since 则与被请求资源的最后修改时间进行比较,如果最后修改时间比较新,说明资源被修改过,则返回最新的资源 并返回 200 状态码;
如果最后修改时间与 if-Modified-Since 一样,则说明资源没有修改,返回 304 表示可以使用缓存数据, 通知浏览器继续使用它所保存的缓存文件。
Last-modified问题
1 某些服务器不能精确得到文件的 最后修改时间,这样就无法通过最后修改时间来判断文件是否更新了;
2 某些文件的修改非常频繁,Last-Modified 只能精确到秒,所以可能出现在秒以内的时间内进行文件的修改,造成因时间精度而出想的误差;
3 一些文件的最后修改时间改变了,但是 内容并未改变,所以还是会造成误差;
4 如果同样的一个文件位于多个 CDN 服务器上的时候内容虽然一样,修改时间不一样。
ETag 通过文件的内容来判断缓存是否可用
Etag是实体标签的缩写,它是根据实体内容生成的一段 hash 字符串,可以标识资源的状态,当资源发生改变的时候, Etag 也会发生改变。服务端将生成 的 Etag 并发送给 浏览器。
1 浏览器想判断缓存是否可用,可以先获取缓存中文档的 ETag,然后通过 if-None-Match 发送请求给 Web 服务器询问此缓存是否可用;
2 服务器根据 if-None-Match 这个请求头,将服务器中的该文件的 Etag 与它进行比较,如果二者值相同,则说明 文件未改变,可以使用改缓存,返回 304;
3 如果不一样,返回最新的文件。
每个 Web 服务器对 Etag 的计算方法都不一样, 只要保证数据变化后的值不一样就好了,复制的计算会增加服务器的负担。Nginx 的算法是 修改时间 + 长度。
etag 没修改文件走304 文件修改后走200重新获取数据即使有“Last-modified”和“ETag”,强制刷新(Ctrl+F5)也能够从服务器获取最新数据(返回 200 而不是 304),强制刷新请求头里的 If-Modified-Since 和 If-None-Match 会被清空所以会返回最新数据。
强制缓存
网图Expires 是服务器响应消息头字段,在响应http 请求时,告诉浏览器在过期时间前浏览器可以直接从浏览器缓存中去数据,而不用再去发起请求。(这是 HTTP 1.0 的内容,现在浏览器均默认使用 HTTP 1.1 所以可以忽略)
Cache-Control 与 Expires 的作用一样,都是指明当前资源的有效期,告诉浏览器是直接从缓存中取数据 还是 重新发起请求, Cache-Control 的优先级高。
浏览器会将文件缓存到 Cache 目录,第二次请求时,浏览器会先检查 Cache-Control 或者Expires,看看设置的时间是否过期,过期则再次请求,否则直接使用。
Cache-Controlmax-age=30 缓存内容将在 300 秒后失效; no-cache 不缓存,需要使用协商缓存验证数据;private 客户端可以缓存;public 客户端 和 代理服务器都可以缓存。
总结
强制缓存会在有效期内直接取本地缓存的数据,而不会向服务器发起请求;
协商缓存都会向服务器发送请求。
网友评论