Nginx缓存相关配置解析

文章目录


前言

客户端需要访问服务器的数据时,如果都直接向服务器发送请求,服务器接收过多的请求,压力会比较大,也比较耗时;而如果在nginx缓存一定的数据,使客户端向基于nginx的代理服务器发送请求,可以有效节省时间。

Nginx缓存机制的作用

  • 缓存能够提升性能,学会Nginx中如何使用缓存很重要。
  • Nginx作为静态资源服务器,静态资源变动频率小,缓存能够加速访问。
  • Nginx离用户最近,启用缓存能更好的提高性能,结合Redis可以组成类似二级缓存。

完整的官方配置文档

缓存放置内容过程:

  1. 当nginx从上游服务器读取响应时,首先将内容写入缓存目录结构之外的临时文件。
  2. 当nginx完成处理请求时,它会重命名临时文件并将其移动到缓存目录。如果用于代理的临时文件目录位于另一个文件系统上,则文件将被复制,因此建议将临时目录和缓存目录保留在同一个文件系统上。当需要显式清除文件时,从缓存目录结构中删除文件也是非常安全的。
  3. 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;
  1. 该设置从上到下进行,如果在上面的步骤中被设置(如404,202,302),就不会更改,最后的any只能设置除404,202,302以外的状态。
  2. 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;

可添加的头示例 :

  1. add_header Access-Control-Allow-Methods

    明确了客户端所要访问的资源允许使用的方法或方法列表,可以是"GET,OPTIONS,POST,HEAD,PUT,DELETE"

  2. add_header Accept-Ranges

    此字段的值表示可用于定义范围的单位,可以是"bytes"

  3. add_header Access-Control-Allow-Origin "*"

    表示服务器可以接受所有的请求源(Origin),即接受所有跨域的请求。

  4. add_header Access-Control-Allow-Headers

    可支持的请求首部名字。请求头会列出所有支持的首部列表,用逗号隔开。

    示例:

  5. 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 :

json 复制代码
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;
	}
}

原博客

案例博客原文

案例学习原文

知乎案例博客

相关推荐
EnCi Zheng1 分钟前
Spring Security 最简配置完全指南-从入门到精通前后端分离安全配置
java·安全·spring
NicolasCage1 小时前
解决苍穹外卖WebSocket连接失败的问题
nginx
沐浴露z2 小时前
分布式场景下防止【缓存击穿】的不同方案
redis·分布式·缓存·redission
鸽鸽程序猿3 小时前
【项目】基于Spring全家桶的论坛系统 【下】
后端·spring·restful
Lisonseekpan3 小时前
Spring Boot 中使用 Caffeine 缓存详解与案例
java·spring boot·后端·spring·缓存
小许学java4 小时前
Spring AI快速入门以及项目的创建
java·开发语言·人工智能·后端·spring·ai编程·spring ai
维尔切5 小时前
Nginx 反向代理与负载均衡
运维·nginx·负载均衡
kfepiza5 小时前
Spring 如何解决循环依赖 笔记251008
java·spring boot·spring
kfepiza7 小时前
Spring的三级缓存原理 笔记251008
笔记·spring·缓存
jun71187 小时前
msi mesi moesi cpu缓存一致性
缓存