一、双缓存的工作机制和使用场景
1. 强制缓存
强制缓存是指浏览器不与服务器进行任何通信,直接使用本地缓存的资源。当资源还在有效期内时,浏览器不会向服务器发送请求,直接从缓存中读取数据。强制缓存的控制通常通过HTTP头信息来实现,例如 Expires
和 Cache-Control
。
1.1 主要字段
-
Expires
Expires
是一个HTTP响应头,它表示资源的过期时间。浏览器在过期时间之前,都会直接使用缓存。如果当前时间超过了Expires
指定的时间,缓存失效。Expires: Wed, 21 Oct 2023 07:28:00 GMT
-
Cache-Control
Cache-Control
是HTTP/1.1中引入的更为灵活的头部字段,可以指定缓存的多种行为。常见的指令包括:max-age
:表示资源的有效期,单位是秒。public
:资源可以被任何缓存(浏览器、代理服务器等)缓存。private
:资源只能被浏览器缓存,代理服务器不能缓存。no-cache
:强制客户端发送请求到服务器进行缓存验证。no-store
:完全不进行缓存。
Cache-Control: max-age=3600, public
1.2 工作原理
当浏览器请求一个资源时,服务器会在响应头中加入 Expires
或 Cache-Control
。浏览器根据这些头部信息决定是否可以直接使用缓存。如果缓存有效,浏览器不会再次请求服务器。
1.3 特点
- 浏览器不与服务器通信,直接使用本地缓存。
- 通过
Expires
和Cache-Control
控制缓存时间。 - 若资源未过期,即使服务器上的资源已更新,浏览器也不会知道。
2. 协商缓存
协商缓存是指浏览器在使用缓存之前,会先与服务器确认缓存资源是否仍然有效。如果资源没有变化,服务器会返回304状态码,告知浏览器可以使用本地缓存。如果资源已变化,服务器会返回新的资源。协商缓存主要通过 Last-Modified
、If-Modified-Since
和 ETag
、If-None-Match
头部字段实现。
2.1 主要字段
-
Last-Modified 和 If-Modified-Since
Last-Modified
表示资源最后修改的时间。If-Modified-Since
是浏览器下次请求资源时,携带的上次资源最后修改时间,服务器根据这个时间判断资源是否发生了变化。
Last-Modified: Wed, 21 Oct 2022 07:28:00 GMT
-
ETag 和 If-None-Match
ETag
是一个资源的唯一标识符(通常是文件内容的哈希值)。If-None-Match
是浏览器下次请求资源时,携带的上次资源的ETag
,服务器根据这个标识符判断资源是否发生了变化。
ETag: "34ac87a3"
2.2 工作原理
- 第一次请求资源时,服务器会在响应头中加入
Last-Modified
或ETag
。 - 浏览器下一次请求该资源时,会在请求头中带上
If-Modified-Since
或If-None-Match
。 - 服务器收到请求后,比较资源的修改时间和
ETag
,如果资源未修改,返回304状态码,浏览器使用缓存。如果资源已修改,返回新的资源。
2.3 特点
- 浏览器与服务器通信,确认缓存是否有效。
- 通过
Last-Modified
/If-Modified-Since
或ETag
/If-None-Match
实现。 - 即使资源未修改,仍然会有HTTP请求,但返回的是304状态码,不返回资源内容。
3. 强制缓存和协商缓存的区别
对比项 | 强制缓存 | 协商缓存 |
---|---|---|
是否与服务器通信 | 否 | 是 |
主要控制头 | Expires , Cache-Control | Last-Modified , ETag |
缓存有效时状态码 | 200 (from cache) | 304 (Not Modified) |
缓存过期后行为 | 重新请求服务器 | 重新请求服务器 |
适用场景 | 资源长期不变的静态资源 | 资源可能频繁更新的动态资源 |
4. 实际应用
在实际开发中,通常会结合使用强制缓存和协商缓存:
- 对于静态资源(如图片、CSS、JavaScript),使用强制缓存,设置较长的过期时间(例如一年)。
- 对于动态资源(如HTML页面),使用协商缓存,确保资源更新时客户端能够及时获取最新内容。
要确定缓存的有效期,主要是通过分析服务器响应头中的相关字段来实现的。浏览器根据这些字段来决定是否可以直接使用缓存,或者需要与服务器进行协商确认缓存是否仍然有效。
二、如何查看缓存的有效期
要查看一个资源的缓存有效期,可以通过浏览器的开发者工具(通常是 "Network" 面板)来查看请求和响应头。以下是在不同浏览器中查看缓存有效期的步骤:
1. Chrome 浏览器
- 打开 Chrome 浏览器并加载网页。
- 按
F12
或右键点击页面,选择 "检查" 以打开开发者工具。 - 点击 "Network"(网络)选项卡。
- 重新加载页面(可以按
Ctrl + R
或Cmd + R
)。 - 点击一个资源(例如一个图片、CSS文件或JavaScript文件)以查看其请求和响应头。
- 在右侧的 "Headers"(头部)面板中,查看响应头中的
Cache-Control
和Expires
字段。
2. Firefox 浏览器
- 打开 Firefox 浏览器并加载网页。
- 按
F12
或右键点击页面,选择 "检查元素" 以打开开发者工具。 - 点击 "Network"(网络)选项卡。
- 重新加载页面。
- 点击一个资源,在右侧的 "Headers"(头部)面板中查看
Cache-Control
和Expires
字段。
3. Edge 浏览器
- 打开 Edge 浏览器并加载网页。
- 按
F12
或右键点击页面,选择 "检查元素" 以打开开发者工具。 - 点击 "Network"(网络)选项卡。
- 重新加载页面。
- 点击一个资源,在右侧的 "Headers"(头部)面板中查看
Cache-Control
和Expires
字段。
缓存有效期的计算
- 对于
Expires
,直接比较当前时间与响应头中的过期时间即可。 - 对于
Cache-Control: max-age
,有效期的计算方式是:请求时间 +max-age
的值。
示例:
假设当前时间是 2023-10-21 07:00:00 GMT
,服务器返回的响应头如下:
Cache-Control: max-age=3600
那么缓存的有效期就是 2023-10-21 08:00:00 GMT
。
缓存验证(协商缓存)
如果缓存已经过期,浏览器会使用协商缓存机制与服务器进行验证。协商缓存通过 Last-Modified
/If-Modified-Since
或 ETag
/If-None-Match
来实现。即使缓存过期,如果资源未发生变化,服务器会返回 304 Not Modified
,浏览器仍然可以使用缓存。
三. ETag
和 Last-Modified
的优先级
在HTTP缓存机制中,ETag
和 Last-Modified
都是用于协商缓存的响应头部字段,它们允许浏览器和服务器之间进行缓存验证,以确定缓存的资源是否仍然有效。但是,ETag
的优先级高于 Last-Modified
,当两者同时存在时,服务器会优先使用 ETag
进行缓存验证。
1. 工作原理
1.1 Last-Modified
- 定义:
Last-Modified
是一个HTTP响应头部,表示资源的最后修改时间。它是一个GMT时间值,例如Mon, 10 Nov 2023 10:00:00 GMT
。 - 工作机制:
- 当浏览器第一次请求资源时,服务器会在响应头中返回
Last-Modified
,表示该资源最后一次修改的时间。 - 在后续请求中,浏览器会通过
If-Modified-Since
请求头将这个时间发送回服务器,服务器会比较这个时间与资源的实际修改时间,以判断资源是否发生了变化。- 如果资源未变化,服务器返回
304 Not Modified
。 - 如果资源已变化,服务器返回新的资源和
200 OK
。
- 如果资源未变化,服务器返回
- 当浏览器第一次请求资源时,服务器会在响应头中返回
1.2 ETag
- 定义:
ETag
是一个HTTP响应头部,表示资源的唯一标识符。通常,这个标识符是基于资源内容生成的哈希值或版本号。 - 工作机制:
- 当浏览器第一次请求资源时,服务器会在响应头中返回
ETag
,表示该资源的唯一标识。 - 在后续请求中,浏览器会通过
If-None-Match
请求头将这个ETag
发送回服务器,服务器会比较客户端发送的ETag
与当前资源的ETag
,以判断资源是否发生了变化。- 如果资源未变化,服务器返回
304 Not Modified
。 - 如果资源已变化,服务器返回新的资源和
200 OK
。
- 如果资源未变化,服务器返回
- 当浏览器第一次请求资源时,服务器会在响应头中返回
2. 优先级
ETag
的优先级高于 Last-Modified
。当服务器同时返回 ETag
和 Last-Modified
时,浏览器会优先使用 ETag
进行缓存验证。具体原因如下:
-
精确度:
ETag
是基于资源内容的哈希值或版本号,能够精确地标识资源的变动,即使资源在一秒之内多次修改,ETag
也能正确反映这种变化。而Last-Modified
只能精确到秒级,如果资源在同一秒内发生多次修改,Last-Modified
可能无法正确标识这些变化。 -
一致性:
ETag
提供了更一致的验证机制,尤其是在分布式系统或多服务器环境中,不同服务器上的文件修改时间可能不一致,但ETag
可以确保资源的唯一标识。 -
HTTP规范:根据HTTP规范和实际应用,当
ETag
存在时,服务器应优先使用ETag
进行缓存验证,而忽略Last-Modified
。
3. 工作流程
3.1 只有 Last-Modified
-
第一次请求:
GET /resource HTTP/1.1
响应:
HTTP/1.1 200 OK Last-Modified: Mon, 10 Nov 2023 10:00:00 GMT Content-Type: text/html
-
第二次请求(缓存过期或需要验证):
GET /resource HTTP/1.1 If-Modified-Since: Mon, 10 Nov 2023 10:00:00 GMT
服务器验证:
- 如果资源未变化,返回
304 Not Modified
。 - 如果资源已变化,返回新的资源和
200 OK
。
- 如果资源未变化,返回
3.2 同时有 ETag 和 Last-Modified
-
第一次请求:
GET /resource HTTP/1.1
响应:
HTTP/1.1 200 OK ETag: "34ac87a3" Last-Modified: Mon, 10 Nov 2023 10:00:00 GMT Content-Type: text/html
-
第二次请求(缓存过期或需要验证):
GET /resource HTTP/1.1 If-None-Match: "34ac87a3"
服务器验证:
- 服务器优先检查
If-None-Match
,并将其与当前资源的ETag
进行比较。- 如果匹配(资源未变化),返回
304 Not Modified
。 - 如果不匹配(资源已变化),返回新的资源和
200 OK
。
- 如果匹配(资源未变化),返回
- 服务器不会检查
If-Modified-Since
,因为ETag
优先级更高。
- 服务器优先检查
4. 示例
4.1 请求头(浏览器发送的请求,带有 If-None-Match
):
GET /resource HTTP/1.1
If-None-Match: "34ac87a3"
4.2 响应头(服务器返回 304 Not Modified
):
HTTP/1.1 304 Not Modified
ETag: "34ac87a3"
在这种情况下,服务器返回 304 Not Modified
,浏览器可以使用本地缓存中的资源,Last-Modified
不会被用于验证。
总结
- 优先级:
ETag
的优先级高于Last-Modified
。当两者同时存在时,服务器会优先使用ETag
进行缓存验证,而忽略Last-Modified
。 - 精确度:
ETag
提供了更精确的资源验证机制,因为它基于资源内容的哈希值或版本号,而Last-Modified
只能精确到秒级。 - 一致性:在分布式系统或多服务器环境中,
ETag
提供了更一致的验证机制。
通过这种方式,ETag
和 Last-Modified
共同提供了灵活且高效的缓存验证机制,减少了不必要的资源传输,提高了性能。但在同时使用时,ETag
具有更高的优先级。
今天就先码到这儿吧!!!