1 RFC7232 指纹
1.1 响应头部
ETag = entity-tag,仅对同一个URL下的比较有意义。
为啥需要这玩意?
因为 HTTP 协议本质就是个KV,K=URL,V=body。因为 URL 并没有变,但我的 V 是会变的!所以需要对 V 生成一个摘要!
1.2 请求头部
- If-Match ="*" / 1#entity-tag。用于并发修改资源 (POST/PUT/DELETE) 时,防止误覆盖
- If-None-Match ="*" / 1#entity-tag。用于过期缓存的更新
2 查看 etag
3 关闭 etag
定位NGINX配置文件:
/etc/nginx/nginx.conf
先看关闭前:
vim nginx.conf
改成
etag off;
重启 Nginx:
nginx -s reload
发现关闭后:
etag 消失了!
3.1 如果不使用Etag指纹,浏览器还会开启缓存吗?
Syntax: etag on | off;
Default:etag on;
Context:http, server, location
生成规则:
ngx_sprintf(etag->value.data, "\"%xT-%xO\"",
r->headers out.last modified time
r->headers out.content_length_n)
发现响应头里也没说缓存时间,为啥浏览器还给我们缓存了?
为什么要预估缓存时间?max-age (days)
"max-age"是HTTP响应头中的一个指令,控制客户端(例如浏览器)缓存页面的时间。值表示从接收到响应开始,客户端将在该时间段内将响应视为有效,并在此期间内不再发送请求到服务器。
- 单位:s。如,若响应头包含"Cache-Control: max-age=3600",则表示该响应在客户端缓存有效期为3600秒,即1h。
- 优先级:当同时存在"Expires"和"max-age"时,浏览器优先考虑"max-age",因为它提供相对时间,而"Expires"提供绝对时间
- 缓存控制:max-age指令可以单独使用,也可以与其他缓存控制指令结合使用,例如"public"、"private"、"no-cache"等。这些指令共同决定了响应在客户端和代理服务器中的缓存行为。
- 更新:一旦响应被缓存,客户端会在max-age过期之前认为响应有效,而不会向服务器发送请求。当max-age过期后,客户端会向服务器发送请求验证响应是否依然有效。
总之,"max-age"字段缓存时间代表了客户端缓存响应的有效期限,它是控制缓存行为的重要标头之一。
55%的请求没有携带max-age
也就是没有告诉客户端这个资源要不要缓存。很多内容不咋变,都应该被缓存,如图片,js css,但服务器配置这些有问题,没有考虑到带宽优化,用户体验提升,所以没有配置描述缓存过期时间的内容。所以浏览器就有默认缓存时间。
那浏览器如何预估时间?
常见的预估时间
RFC7234 推荐:(DownloadTime– LastModified)*10%
4 缓存过程
浏览器缓存大概示意图(非普世版本)
4.1 首次缓存
基于过期缓存提高网络效率
304 Not Modified
若服务器在响应中没有提供Etag标头,浏览器通常会依赖其他标头来确定内容是否可以缓存。例如,如果响应中包含了"Cache-Control"标头,并且指示可以缓存响应,那么即使没有Etag指纹,浏览器仍然可能会将响应缓存起来。
若响应中包含"Last-Modified"标头,浏览器也可以使用该信息来验证缓存是否仍然有效。
参考:
- https://www.stevesouders.com/blog/2012/03/22/cache-them-if-you-can/
- https://www.bilibili.com/video/BV1iK411T73K/?spm_id_from=333.337.search-card.all.click&vd_source=1223dd226a2750a42150cbd1cd3048e3