文章目录
- 前言
- 配置示例
- proxy_cache
- proxy_cache_path
- proxy_cache_key
- proxy_cache_valid
- proxy_cache_lock
- proxy_cache_methods
- proxy_cache_bypass
- proxy_no_cache
- proxy_cache_min_uses
- add_header 可选项
- 使用示例
- 通过响应头判断是否走缓存
- 缓存手动删除
- 原博客
前言
客户端需要访问服务器的数据时,如果都直接向服务器发送请求,服务器接收过多的请求,压力会比较大,也比较耗时;而如果在nginx缓存一定的数据,使客户端向基于nginx的代理服务器发送请求,可以有效节省时间。
Nginx缓存机制的作用
- 缓存能够提升性能,学会Nginx中如何使用缓存很重要。
- Nginx作为静态资源服务器,静态资源变动频率小,缓存能够加速访问。
- Nginx离用户最近,启用缓存能更好的提高性能,结合Redis可以组成类似二级缓存。
完整的官方配置文档
缓存放置内容过程:
- 当nginx从上游服务器读取响应时,首先将内容写入缓存目录结构之外的临时文件。
- 当nginx完成处理请求时,它会重命名临时文件并将其移动到缓存目录。如果用于代理的临时文件目录位于另一个文件系统上,则文件将被复制,因此建议将临时目录和缓存目录保留在同一个文件系统上。当需要显式清除文件时,从缓存目录结构中删除文件也是非常安全的。
- nginx有第三方扩展,可以远程控制缓存的内容,并计划在主发行版中集成此功能
缓存的资源也不是一成不变的,因此缓存也需要有更新的机制。
因此,对于Nginx的缓存主要围绕以下几点展开:
- 缓存文件存放在哪儿
- 缓存的有效期
- 如何指定哪些请求走缓存,哪些请求不缓存
- 如何删除缓存
配置示例
proxy_cache
proxy_cache
:用于定义共享内存区域的名称。可以使用变量,默认值为off
表示禁用缓存。此参数是proxy_cache_path 指令的基础。
该指令用来开启或关闭缓存,如果是开启则自定使用哪个缓存区来缓存
- 开启 proxy_cache zone_name;
- 关闭 proxy_cache off;
zone_name 为自定义名称。
配置位置
:http、server、location里
proxy_cache_path
proxy_cache_path
:定义缓存的存储路径。
配置位置
: 在 http中,server外
语法 :
proxy_cache_path path [levels=a:b:c] keys_zone=zone_name:zone_size [inactive=time] [max_size=sizes]
-
path
: 可以是 /usr/local/proxy_cache ,为设置缓存文件的存放地址 -
levels
:levels可以将字符串密文与缓存目录进行结合,指定缓存空间对应的目录,最多可以设置三层,每层取值为1或2;
例如: levels=1:2 ,表示缓存空间有两层目录,一层是1个字母,二层是2个字母
如果字符串密文为dsciwbdciow87y8hwdh29,那么levels=1:2最终的存储目录为:/usr/local/proxy_cache/9/h2
该参数与 proxy_cache_key 指令有关,proxy_cache_key 的默认值为$scheme$proxy_host$request_uri
,然后将获取到的值MD5加密,然后依次从末尾按照levels的设置取值来创建目录。 -
keys_zone
:可以指定缓存区的名称与大小,名称就是上面proxy_cache
定义的名称,例keys_zone=impar:300m 表示缓存区名称为impar,大小为300m. -
inactive
:指定缓存的数据多久未被访问会被删除的时间;inactive=2d,2d表示2天 -
max_size
:设置最大的缓存空间,如果缓存空间存满,会根据LRU算法,删除最近最少使用的数据或覆盖目前缓存时间最长的数据,示例max_size=10g
proxy_cache:定义共享内存区域的名称。
proxy_cache_path:定义缓存的存储路径。
proxy_cache_key
该指令用来设置web缓存中的key值,nginx会根据key值的MD5进行哈希缓存
语法 :
proxy_cache_key string;
默认值 :
proxy_cache_key $scheme$proxy_host$request_uri;
配置位置
:http、server、location里
proxy_cache_valid
该指令用来对不同返回状态码的URL设置不同的缓存时间
语法 :
proxy_cache_valid [code …] time;
配置位置
:http、server、location里
示例 :
#不指定响应码,则只对200、301和302进行缓存。
proxy_cache_valid 10m;
#对指定响应码进行缓存。
proxy_cache_valid 200 301 10m;
#对任何响应码进行缓存。
proxy_cache_valid any 10m;
前面我们在配置proxy_cache_path指令时,inactive参数可以指定一定时间内缓存未被访问就会被删除。而proxy_cache_valid指定的是缓存的过期时间,超过该时间缓存将会过期,但是不会被删除。
因此我们在配置的时候,一般inactive的值会大于proxy_cache_valid中的值,否则将会导致缓存还不过期就被删除了。
proxy_cache_valid 404 1m;
proxy_cache_valid 202 302 1m;
proxy_cache_valid any 1m;
- 该设置从上到下进行,如果在上面的步骤中被设置(如404,202,302),就不会更改,最后的any只能设置除404,202,302以外的状态。
- nginx缓存代理中常有情况:nginx尚未缓存某数据,但是客户端发出请求该数据的信息,nginx往往只能先回复404。但是稍后nginx从服务器请求到了该数据后,客户端再请求该数据那按照原理必然要返回该数据,而不是404。因此,之前请求对应的返回状态码应该有一个“限定有效的时间”。这就需要靠proxy_cache_valid来设置了。
proxy_cache_valid 不是唯一设置缓存时间的,还可以通过如下方式(优先级从上到下):
以秒为单位的“X-Accel-Expires”响应头来设置响应缓存时间 如果没有“X-Accel-Expires”,可以根据“Cache-Control”、“Expires”来设置响应缓存时间 否则使用proxy_cache_valid设置的缓存时间。
如果响应头包含Cache-Control:private/no-cache/no-store、Set-Cookie或者只有一个Vary响应头且其值为*,则响应内容将不会被缓存。可以使用proxy_ignore_headers来忽略这些响应头。
proxy_cache_lock
当多个客户端同时请求同一份内容时,如果开启proxy_cache_lock(默认off)则只有一个请求被发送至后端;其他请求将等待该内容返回;当第一个请求返回时,其他请求将从缓存中获取内容返回;当第一个请求超过了proxy_cache_lock_timeout超时时间(默认5s),则其他请求将同时请求到后端来获取响应,且响应不会被缓存;启用proxy_cache_lock可以应对雪崩效应。
proxy_cache_lock_age time;
默认值 :
proxy_cache_lock_age 5s;
配置位置
:http、server、location里
proxy_cache_methods
该指令用户设置哪些http方法可以被缓存
proxy_cache_methods method
method可选方式为GET, HEAD, POST.
默认方式为GET, HEAD。
配置位置
:http、server、location里
proxy_cache_bypass
该指令配置不走缓存响应的条件,如果条件命中,则不走缓存
。可与proxy_no_cache配合使用。
如果参数中的值至少有一个值不为空且不为"0",则不走缓存响应。
# 以$arg开头的参数表示url中的对应的参数。
proxy_cache_bypass $cookie_nocache $arg_nocache$arg_comment;
proxy_no_cache
该指令配置不缓存响应的条件,如果条件命中,则不缓存
。可与proxy_cache_bypass配合使用。
配置位置
:http、server、location里
语法:proxy_no_cache string …;
如果参数中的值至少有一个值不为空且不为"0",则不缓存响应。
# 以$arg开头的参数表示url中的对应的参数。
proxy_no_cache $cookie_nocache $arg_nocache$arg_comment;
proxy_cache_min_uses
该指令设置某个请求达到指定次数后,才对其进行缓存。
配置位置
:http、server、location里
语法:
proxy_cache_min_uses number;
默认值:proxy_cache_min_uses 1;
add_header 可选项
当前选项不是必须的,只是方便在测试的时候查看是否命中缓存
add_header nginx-cache $upstream_cache_status;
可添加的头示例 :
-
add_header Access-Control-Allow-Methods
明确了客户端所要访问的资源允许使用的方法或方法列表,可以是"GET,OPTIONS,POST,HEAD,PUT,DELETE" -
add_header Accept-Ranges
此字段的值表示可用于定义范围的单位,可以是"bytes" -
add_header Access-Control-Allow-Origin "*"
表示服务器可以接受所有的请求源(Origin),即接受所有跨域的请求。 -
add_header Access-Control-Allow-Headers
可支持的请求首部名字。请求头会列出所有支持的首部列表,用逗号隔开。
示例: -
add_header Access-Control-Allow-Headers "*"
注意以下这些特定的首部是一直允许的:Accept, Accept-Language, Content-Language, Content-Type,这些被称作simple headers,无需特意声明它们。
使用示例
使用内置$upstream_cache_status
变量可以查看缓存命中状态。状态值分别为MISS、BYPASS、EXPIRED、STALE、UPDATING、REVALIDATED、HIT。
在响应中添加Nginx-Cache
头,显示缓存命中状态.
配置服务端前置Nginx :
http {
# 缓存在10分钟之内未被访问即删除
proxy_cache_path /home/stone/proxy_cache levels=1:2 keys_zone=my_cache:10M inactive=10m max_size=10G;
server {
listen 80;
server_name localhost;
location /cache {
proxy_cache my_cache;
proxy_cache_key $uri$is_args$args;
# 缓存的有效期会10s
proxy_cache_valid any 10s;
proxy_cache_min_uses 1;
# 添加缓存命中状态,$upstream_cache_status
add_header Nginx-Cache $upstream_cache_status;
proxy_pass http://127.0.0.1:81;
}
}
}
同时在html文件夹下创建cache文件,并放入test.html文件。
代码块 :
server {
listen 81;
server_name localhost;
location /cache {
root html;
}
}
访问http://127.0.0.1:80/cache/test.html
第一次访问:缓存状态为MISS,即未命中。
第二次访问:缓存状态为HIT,即已命中缓存。
查看缓存文件夹,已经按照levels参数指定的规则生成目录结构,并缓存文件。
第三次访问:缓存状态为EXPIRED,缓存已过期,因为我们设置的10s过期。
通过响应头判断是否走缓存
首次访问 http://localhost:7000/cache/
服务器返回如下几个缓存控制头部:
- Last-Modified:表示文档的最后修改时间,当去服务器验证时会拿这个时间去;
Expires:http/1.0规范定义,表示文档在浏览器中的过期时间,当缓存的内容超过这个时间则需要重新去服务器获取最新的内容; - Cache-Control:http/1.1规范定义,表示浏览器缓存控制,例:Cache-Control: public, max-age=31536000,max-age=3153600表示文档可以在浏览器中缓存一年。
- ETag:发送到服务端进行内容变更验证的,而Catch-Control是用于控制缓存时间的(浏览器、代理层等)。此处我们使用了弱实体W\”6124c”,弱实体(”6124c”)只要内容语义没变即可,比如内容的gzip版和非gzip版可以使用弱实体验证;而强实体指字节必须完全一致(gzip和非gzip情况是不一样的),因此建议首先选择使用弱实体。
nginx在生成etag时使用的算法是Last-Modified + Content-Length计算的。根据规范定义Cache-Control优先级高于Expires,实际使用时可以两个都用,或仅使用Cache-Control就可以了。一般情况下Expires=当前系统时间(Date) + 缓存时间(Cache-Control: max-age)。
再次访问 http://localhost:7000/cache/ 时,发现浏览器请求头部有变化:
-
Modified-Since请求头,其值是上次请求响应中的Last-Modified,即浏览器会拿这个时间去服务端验证内容是否发生了变更。
-
If-None-Match请求头,其值是上次请求响应中的ETag,即浏览器会拿这个时间去服务端验证内容是否发生了变更。
Last-Modified与ETag同时使用时,浏览器在验证时会同时发送If-Modified-Since和If-None-Match,按照http/1.1规范,如果同时使用If-Modified-Since和If-None-Match则服务端必须两个都验证通过后才能返回304;且nginx就是这样做的。因此实际使用时应该根据实际情况选择。
当我们按下cmd-F5强制刷新后:浏览器在请求时不会带上If-Modified-Since,并带上Cache-Control:no-cache和Pragma:no-cache,这是为了告诉服务端说我请给我一份最新的内容。
通过响应状态码判断是否走缓存
304 Not Modified
304表示服务器返回文档没有过期
200 (from cache) 表示浏览器直接使用缓存数据
Last-Modified/Modified-Since 用于验证文档内容是否变更 max-age/Expires 定义文档缓存时间,如在有效期内会返回 200(from cache)
原文博客
缓存手动删除
如果服务端的文件发生变化,那么也需要将文件同步到Nginx的缓存中去,因此我们需要对缓存进行删除。
-
删除对应缓存目录:这种方式看上去简单粗暴,但是想要删除指定的缓存,则犹如大海捞针。
rm -rf /home/stone/proxy_cache
-
ngx_cache_purge:第三方模块,通过请求删除指定的缓存文件。
ngx_cache_purge :
可以借助第三方模块ngx_cache_purge来实现对指定缓存的删除。
下载地址
语法:
proxy_cache_purge keys_zone key;
- keys_zone:该参数为proxy_cache指令指定的值。
- key:该参数为proxy_cache_key指定的值。
配置位置
:location里
示例 :
server {
listen 80;
server_name localhost;
location /cache {
proxy_cache my_cache;
# 设置proxy_cache_key
proxy_cache_key $uri$is_args$args;
proxy_cache_valid 200 302 10s;
# 添加缓存命中状态
add_header Nginx-Cache $upstream_cache_status;
proxy_pass http://127.0.0.1:81;
}
# 删除指定缓存
location ~/purge(/.*) {
proxy_cache_purge my_cache $1$is_args$args;
}
}
原博客
案例博客原文
案例学习原文
知乎案例博客