文章目录
- [1. 背景介绍](#1. 背景介绍)
- [2. 测试环境搭建](#2. 测试环境搭建)
- [3. 缓存字段](#3. 缓存字段)
-
- [3.1 Expires](#3.1 Expires)
- [3.2 Cache-Control](#3.2 Cache-Control)
- [3.3 协商缓存](#3.3 协商缓存)
1. 背景介绍
Http协议标准有RFC定义好的请求和响应头部字段用于进行缓存设置,本文主要进行介绍缓存功能相关的头部字段及其使用方法。在使用CDN功能是,协议标准缓存字段的识别和判断是十分重要的!
缓存字段优先级如下:
Cache-Control(Private > Max-age) > Expires
Etag > Last-Modified
2. 测试环境搭建
安装Nginx服务,且配置conf.d子配置文件目录(实验环境ip为内网地址)
bash
# 在已经安装好的nginx服务conf主配置文件的http模块下添加如下配置
[root@localhost nginx]# cat conf/nginx.conf | grep 'conf.d'
include /middleware/nginx/conf.d/*.conf; # 该配置代表http模块将conf.d目录下的conf后缀文件也作为配置文件进行加载
# 创建备用配置文件目录并且创建新的端口服务
[root@localhost nginx]# mkdir conf.d
[root@localhost nginx]# cat conf.d/ceshi01.conf
server {
listen 8081; # 新端口使用8081
server_name localhost;
location /ceshi01 {
root /middleware/nginx/conf.d/data; # ceshi01访问路径为/middleware/nginx/conf.d/data/ceshi01/ceshi.html
index /ceshi01/ceshi.html;
default_type text/html;
}
location /ceshi02 {
root /middleware/nginx/conf.d/data; # ceshi02访问路径为/middleware/nginx/conf.d/data/ceshi02/ceshi.html
index /ceshi02/ceshi.html;
default_type text/html;
}
error_page 403 404 /middleware/nginx/conf.d/data/40x.html; # 403和404状态码进行特殊配置
location = /middleware/nginx/conf.d/data/40x.html {
root html;
}
}
# 准备目标访问html文件
[root@localhost nginx]# cat /middleware/nginx/conf.d/data/ceshi01/ceshi.html
{'uasername': 'ceshi01', 'age': 27}
[root@localhost nginx]# cat /middleware/nginx/conf.d/data/ceshi02/ceshi.html
{'uasername': 'ceshi02', 'age': 27}
# 重启Nginx服务
[root@localhost nginx]# ./sbin/nginx -t # 重启服务前必须进行检测配置文件是否可以正确执行,这是一个非常好的习惯!
nginx: the configuration file /usr/local/nginx/conf/nginx.conf syntax is ok
nginx: configuration file /usr/local/nginx/conf/nginx.conf test is successful # 配置文件可以执行无错误
[root@localhost nginx]# ./sbin/nginx -s reload
# 功能验证
[root@localhost nginx]# curl -Lv 'http://9.134.244.180:8081/ceshi02/ceshi.html'
* Trying 9.134.244.180:8081...
* Connected to 9.134.244.180 (9.134.244.180) port 8081
> GET /ceshi02/ceshi.html HTTP/1.1
> Host: 9.134.244.180:8081
> User-Agent: curl/8.9.1
> Accept: */*
>
* Request completely sent off
< HTTP/1.1 200 OK
< Server: nginx/1.25.3
< Date: Wed, 04 Sep 2024 07:44:30 GMT
< Content-Type: text/html
< Content-Length: 36
< Last-Modified: Thu, 29 Aug 2024 10:54:41 GMT
< Connection: keep-alive
< ETag: "66d05371-24"
< Accept-Ranges: bytes
<
{'uasername': 'ceshi02', 'age': 27}
* Connection #0 to host 9.134.244.180 left intact
3. 缓存字段
3.1 Expires
Expire字段代表一个固定的缓存过期时间,为0代表缓存过期,需要注意的是,在添加了Expire之后,响应会自动加入Cache-Control: max-age=xxx的响应头部,而这个缓存时间等同于Expire设置的过期时间。
bash
# Nginx配置如下
location /ceshi01 {
root /middleware/nginx/conf.d/data;
index /ceshi01/ceshi.html;
default_type text/html;
expires 1M; # 设置过期时间为1个月之后
}
# 结果验证
[root@localhost nginx]# curl -Lv 'http://9.134.244.180:8081/ceshi01/ceshi.html'
* Trying 9.134.244.180:8081...
* Connected to 9.134.244.180 (9.134.244.180) port 8081
> GET /ceshi01/ceshi.html HTTP/1.1
> Host: 9.134.244.180:8081
> User-Agent: curl/8.9.1
> Accept: */*
>
* Request completely sent off
< HTTP/1.1 200 OK
< Server: nginx/1.25.3
< Date: Wed, 04 Sep 2024 07:51:09 GMT # 当前请求时间
< Content-Type: text/html
< Content-Length: 36
< Last-Modified: Thu, 29 Aug 2024 10:54:32 GMT
< Connection: keep-alive
< ETag: "66d05368-24"
< Expires: Fri, 04 Oct 2024 07:51:09 GMT # 设置缓存过期时间的返回字段
< Cache-Control: max-age=2592000 # CC字段标识
< Accept-Ranges: bytes
<
{'uasername': 'ceshi01', 'age': 27}
* Connection #0 to host 9.134.244.180 left intact
从测试结果可以看出响应头部的 Expires: Fri, 04 Oct 2024 07:51:09 GMT 时间为当前请求时间的一个月之后,而 Cache-Control: max-age=2592000 代表秒数,正好为30days。
3.2 Cache-Control
Cache-Control在http协议标准内为缓存指令头部,可以使用如下配置(加粗为常见配置):
- 是否缓存
public
:响应可以被任何对象缓存,包含不可以被缓存的内容;搭配请求方式为POST类型;private
:响应只可以被单个用户缓存,不能作为共享缓存(即代理服务器不可以缓存);no-cache
:强制要求回源使用协议缓存方式进行验证;no-store
:不使用任何缓存功能。
- 到期时间
max-age=<secounds>
:设置缓存的最大周期,xxx为秒级配置,时间设置是针对于请求的发起时间而后的过期秒数,如发起时间是a,max-age=1000,即过期时间为a+1000s之后;smax-age=<secounds>
:覆盖max-age或Expires头部配置,仅适用于共享缓存(即代理服务器缓存);max-stale=<secounds>
:客户端可以允许接受一个过期时间在设置的时间范围内文件;min-fresh=<secounds>
:客户端允许获取一个在指定秒数内保持其最新状态的响应;
- 重新加载与验证
must-revalidate
:若资源过期,在获取到新资源之前不使用旧资源响应后续请求;proxy-revalidate
:与must-revalidate作用一致,但只适用于共享缓存模式;
- 其他
no-transform
:不对资源进行转换或转变,Content-Encoding、Content-Range、Content-Type等HTTP头不能由代理修改;only-if-cached
:客户端只接受已经缓存的响应,不向源站检测是否有新资源。
bash
# Nginx配置如下
location /ceshi01 {
root /middleware/nginx/conf.d/data;
index /ceshi01/ceshi.html;
default_type text/html;
# expires 1M;
add_header Cache-Control max-age=1024; # 设置CC字段max-age=1024
}
# 结果验证
[root@localhost nginx]# curl -Lv 'http://9.134.244.180:8081/ceshi01/ceshi.html'
* Trying 9.134.244.180:8081...
* Connected to 9.134.244.180 (9.134.244.180) port 8081
> GET /ceshi01/ceshi.html HTTP/1.1
> Host: 9.134.244.180:8081
> User-Agent: curl/8.9.1
> Accept: */*
>
* Request completely sent off
< HTTP/1.1 200 OK
< Server: nginx/1.25.3
< Date: Wed, 04 Sep 2024 07:56:08 GMT
< Content-Type: text/html
< Content-Length: 36
< Last-Modified: Thu, 29 Aug 2024 10:54:32 GMT
< Connection: keep-alive
< ETag: "66d05368-24"
< Cache-Control: max-age=1024 # 只有CC字段,没有Expires
< Accept-Ranges: bytes
<
{'uasername': 'ceshi01', 'age': 27}
* Connection #0 to host 9.134.244.180 left intact
3.3 协商缓存
协商缓存指的是http协议请求和响应的两个字段配合,如:「Last-Modified + If-Modified-Since」 与 「Etag + If-None-Match」。
Last-Modified
:其中包含源头服务器认定的资源做出修改的日期及时间。它通常被用作一个验证器来判断接收到的或者存储的资源是否彼此一致。由于精确度比 ETag 要低,所以这是一个备用机制。包含有 If-Modified-Since 或 If-Unmodified-Since 首部的条件请求会使用这个字段Etag
:HTTP 响应头是资源的特定版本的标识符。这可以让缓存更高效,并节省带宽,因为如果内容没有改变,Web 服务器不需要发送完整的响应。而如果内容发生了变化,使用 ETag 有助于防止资源的同时更新相互覆盖("空中碰撞 - 强校验哈希值不匹配情况")。
需要注意的是:
- Etag的精细程度比Mtime更高,Mtime无法解决文件内容不变而创建时间改变的场景;
- Mtime的检测周期是秒级,Etag为毫秒级
bash
# Nginx配置如下
location /ceshi01 {
root /middleware/nginx/conf.d/data;
index /ceshi01/ceshi.html;
default_type text/html;
# expires 1M;
add_header Cache-Control no-cache;
# add_header Cache-Control no-store;
}
# 结果验证
[root@localhost nginx]# curl -Lv 'http://9.134.244.180:8081/ceshi01/ceshi.html'
* Trying 9.134.244.180:8081...
* Connected to 9.134.244.180 (9.134.244.180) port 8081
> GET /ceshi01/ceshi.html HTTP/1.1
> Host: 9.134.244.180:8081
> User-Agent: curl/8.9.1
> Accept: */*
>
* Request completely sent off
< HTTP/1.1 200 OK
< Server: nginx/1.25.3
< Date: Wed, 04 Sep 2024 08:30:24 GMT
< Content-Type: text/html
< Content-Length: 36
< Last-Modified: Thu, 29 Aug 2024 10:54:32 GMT
< Connection: keep-alive
< ETag: "66d05368-24"
< Cache-Control: no-cache
< Accept-Ranges: bytes
<
{'uasername': 'ceshi01', 'age': 27}
* Connection #0 to host 9.134.244.180 left intact
[root@localhost nginx]# stat /middleware/nginx/conf.d/data/ceshi01/ceshi.html
File: /middleware/nginx/conf.d/data/ceshi01/ceshi.html
Size: 36 Blocks: 8 IO Block: 4096 regular file
Device: fd01h/64769d Inode: 655368 Links: 1
Access: (0755/-rwxr-xr-x) Uid: ( 0/ root) Gid: ( 0/ root)
Access: 2024-08-29 18:54:32.151256443 +0800 # 注意时区,GMT时间需要+8h=国内时间
Modify: 2024-08-29 18:54:32.151256443 +0800
Change: 2024-08-29 18:59:48.756262327 +0800
Birth: -
当 Cache-Control: no-cache 配置生效之后,会强制进行协议缓存校验,比对 Last-Modified 字段和源站文件的创建时间,如果不一致则返回新资源。
bash
# Nginx配置修改CC字段为不使用任何缓存
location /ceshi01 {
root /middleware/nginx/conf.d/data;
index /ceshi01/ceshi.html;
default_type text/html;
# expires 1M;
# add_header Cache-Control no-cache;
add_header Cache-Control no-store;
}
# 结果验证
[root@localhost nginx]# curl -Lv 'http://9.134.244.180:8081/ceshi01/ceshi.html'
* Trying 9.134.244.180:8081...
* Connected to 9.134.244.180 (9.134.244.180) port 8081
> GET /ceshi01/ceshi.html HTTP/1.1
> Host: 9.134.244.180:8081
> User-Agent: curl/8.9.1
> Accept: */*
>
* Request completely sent off
< HTTP/1.1 200 OK
< Server: nginx/1.25.3
< Date: Wed, 04 Sep 2024 08:36:57 GMT
< Content-Type: text/html
< Content-Length: 36
< Last-Modified: Thu, 29 Aug 2024 10:54:32 GMT
< Connection: keep-alive
< ETag: "66d05368-24"
< Cache-Control: no-store
< Accept-Ranges: bytes
<
{'uasername': 'ceshi01', 'age': 27}
* Connection #0 to host 9.134.244.180 left intact
当 Cache-Control: no-store 配置生效后,则代表不再使用任何缓存,直接从源站获取目标资源。