Nginx 必知必会 — 缓存 (Proxy Cache)

Dec 6, 2018 阅读(3691)

标签: Nginx

什么是 Nginx 缓存

Nginx 缓存 (Proxy Cache)机制主要实现 Nginx 服务器对客户端数据请求的快速相应。 Nginx 服务器在接收到被代理服务器的响应数据之后,一方面通过 Proxy Buffer将数据传递给客户端,另一方面根据 Proxy Cache 的配置将这些数据缓存到本地硬盘上。 当客户端再次访问相同的数据时, Nginx 服务器直接从硬盘检索到相应的数据返回给用户,从而减少与被代理服务器交互的时间。

特别说明,Proxy Cache 机制依赖于 Proxy Buffer 机制,只有在 Proxy Buffer 机制开启的情况下 Proxy Cache 的配置才能发挥作用。

在 Nginx 服务器中还提供另外一种将被代理服务器数据缓存到本地的方法 Proxy Store,与 Proxy Cache 的区别是,它对来自被代理服务器的响应数据,尤其是静态数据只进行简单的缓存,不支持缓存过期更新、内存索引建立等功能,但支持设置用户或用户组对缓存数据的访问权限。

 

Proxy Cache 配置相关指定

  • proxy_cache 指令

该指令用于配置一块共用的内存区域的名称,该区域可以存放缓存的索引数据。 这些数据在 Nginx 服务器启动时由缓存索引重建进程负责建立,在Nginx 服务器的整个运行过程中由缓存管理进程负责定时检查过期数据、检索等管理工作。指令语法结构为:

proxy_cache zone | off;

zone:设置的用于存放缓存索引的内存区域的名称。

off:关闭 proxy_cache 功能,是默认的设置。

从 Nginx 0.7.66 开始,Proxy Cache 机制开启后会检查被代理服务器响应数据 HTTP 头中的 "Cache-Control" 头域、"Expires"头域。当"Cache-Control"头域中的值为 "no-cache"、"no-store"、"private"或者 "max-age" 赋值为0或者无意义时,当 "Expires" 头域包含一个过期的时间时,该响应数据不被 Nginx 服务器缓存。这样做的主要目的是为了避免私有的数据被其他客户端得到。

 

  • proxy_cache_bypass 指令

  配置nginx服务器向客户端发送数据时,数据不从缓存中获取的条件。这些条件支持使用 Nginx 配置的常用变量。其语法结构为:

proxy_cache_bypass string ...;

  其中,string 为条件变量,支持设置多个,当至少有一个字符串指令不为空或者不等于0时,响应数据不从缓存中获取。看一个实例:

proxy_cache_bypass $cookie_nocache $arg_nocache $arg_comment $http_pragma $http_authorization ;

  其中,$cookie_nocache、$arg_nocache、$arg_comment、$http_pragma 和 $http_authorization都是Nginx配置文件的变量,有关 Nginx 配置常用变量使用,请参见:Nginx 内置变量

 

  • proxy_cache_key 指令

设置nginx服务器在内存中为缓存数据建立索引时使用的关键字,其语法结构为:

proxy_cache_key string ;

  其中,string 为设置的关键字,支持变量。在 Nginx 0.7.48 之前的版本中默认的设置是:

proxy_cache_key $scheme$proxy_host$request_uri;

  如果我们希望缓存数据包含服务器主机名称等关键字,则可以将该指令设置为:

proxy_cache_key $scheme$host$request_uri;

  在 Nginx 0.7.48 之后的版本中,通常使用以下配置:

proxy_cache_key $scheme$proxy_host$uri$is_args$args;

 

  • proxy_cache_lock 指令

是否开启缓存的锁功能,开启后,nginx同时只能有一个请求填充缓存中的某一数据项,相当于给数据项上锁,不允许其他请求操作。如果其他请求也想填充该项,必须等待该数据项的锁被释放。这个等待时间由 proxy_cache_lock_timeout 指令配置。其语法结构为:

proxy_cache_lock on | off;

  该指令在Nginx 1.1.2 及之后的版本中可以使用,默认情况下,设置为关闭状态。

 

  • proxy_cache_lock_timeout 指令

缓存锁功能开启以后锁的超时时间,默认5s。其语法结构为:

proxy_cache_lock_timeout time;

 

  • proxy_cache_min_uses 指令

配置客户端请求发送的次数,当相同请求达到设置次数后才会缓存该请求的响应数据,默认为1。其语法结构为:

proxy_cache_min_uses number;

 

  • proxy_cache_path 指令

用于配置 Nginx 服务器存储缓存数据的路径以及和缓存索引相关的内容。其语法结构为:

	proxy_cache_path path [levels=levels] [use_temp_path=on|off] keys_zone=name:size [inactive=time] [max_size=size] [manager_files=number] [manager_sleep=time] [manager_threshold=time] [loader_files=number] [loader_sleep=time] [loader_threshold=time] [purger=on|off] [purger_files=number] [purger_sleep=time] [purger_threshold=time];

path:缓存数据存放根目录,该路径应该预先存在于磁盘上;

levels:相对于path 指定目录的第几级hash 目录中缓存数据。levels=1,表示一级hash目录;levels=1:2,表示二级,依次类推。目录的名称是基于请求URL通过哈希算法获取到的;

keys_zone:设置缓存索引的内存区域的名字和大小;

inactive:强制更新缓存数据的时间,当硬盘上的缓存数据在设定的时间内没有被访问时,Nginx 服务器就强制从硬盘上将其删除,下次客户端访问该数据时重新缓存。该这里默认设置为10s(天:d、秒:s、分:m);

max_size:设置硬盘中缓存数据的大小限制。我们知道,硬盘中缓存源数据有Nginx服务器的缓存管理进程进行管理,当缓存的大小超过该变量时,缓存管理进程将根据最近最少被访问的策略删除缓存;

loader_files:缓存索引重建进程每次加载的数据元素的数量上线。在重建缓存索引的过程中,进程通过一系列的递归遍历读取硬盘上的缓存数据目录及缓存数据文件,对每个数据文件中的缓存数据在内存中建立对应的索引,我们称每建立一个索引为加载一个数据元素。进程在每次遍历过程中可以同时加载多个数据元素,该值限制了每次遍历中同时加载的数据元素的数量。默认设置为100。

loader_sleep:设置缓存索引重建进程在一次遍历结束、下次遍历开始之间的暂停时长。默认设置为 50ms。

loader_threshold:设置遍历以此磁盘缓存源数据的时间上限。默认设置为 200ms。

该指令设置比较复杂,一般需要设置前面三个指令的情形比较多,后面的几个变量与Nginx 服务器缓存索引重建进程及管理进程的性能相关,一般情况下保持默认设置就可以了。以下是几个简单的配置实例:

proxy_cache_path /nginx/cache/a level=1 keys_zone=a:10m;
proxy_cache_path /nginx/cache/b level=2:2 keys_zone=b:100m;
proxy_cache_path /nginx/cache/c level=1:1:2 keys_zone=c:1000m;

注意:该指令和其他指令不同,只能放在 http 块中。

 

  • proxy_cache_use_stale 指令

如果 Nginx 在访问被代理服务器过程中出现被代理服务器无法访问或者访问出错等现象时, Nginx 服务器可以使用历史缓存响应客户端的请求,这些数据不一定和被代理服务器上最新的数据相一致,但对于更新遍历不高的后端服务器来说,Nginx 服务器的该功能在一定程度上能能够为客户端提供不间断访问。该指令用来设置一些状态,当后端被代理服务器处于这些状态时,Nginx 服务器启用该功能。其语法结构为:

proxy_cache_use_stale error | timeout | invalid_header | updating | http_500 | http_502 | http_503 | http_504 | http_403 | http_404 | http_429 | off ...;

该指令中可以支持的状态于语法结构中所示。大部分状态和 proxy_next_upstream 指令是对应的。需要注意其中的 updating 状态的含义。该状态并不是指被代理服务器在updating状态,而是指客户度请求的数据在 Nginx 服务器中正好处于更新状态。这一点需要留意。

该指令的默认设置为默认off。

 

  • proxy_cache_valid 指令;

对不同的http响应状态设置不同的缓存时间。其语法结构为:

proxy_cache_valid  [code ...] time;

code:设置HTTP响应的状态码。该指令可选,如果不设置,Nginx 服务器只为 HTTP 状态码为 200、301和302的响应数据做缓存。可以使用 “any” 表示缓存所有该指令中未设置的其他响应数据。

time:设置缓存的时间。

以下几个简单的配置实例:

proxy_cache_valid 200 302 10m;
proxy_cache_valid 301 1m;
proxy_cache_valid any 1m;

在该例子中,对返回状态为 200 和 302 的响应数据缓存10分钟,对返回状态为301的响应数据缓存1小时,对返回状态为非 200、302、301的响应数据缓存1分钟。

 

  • proxy_cache_methods 指令

设置客户端那些请求方法响应将被缓存。其语法结构为:

proxy_cache_methods GET | HEAD | POST ...;

GET 和 HEAD 方法总是会存在于列表中。

  • proxy_no_cache 指令

设置什么情况下不适用cache 的功能。其语法结构为:

proxy_no_cache string ...;

其中,string可以是一个或者多个变量,当string 的值不为空或不为0则启用cache功能。

简单的配置实例:

proxy_no_cache $cookie_nocache $arg_nocache$arg_comment;
proxy_no_cache $http_pragma    $http_authorization;

 

  • proxy_store 指令

配置是否在本地磁盘缓存来自被代理服务器的响应数据。这是 Nginx 服务器提供的另外一种缓存数据的方法,但是该功能相对Proxy Cache 简单一些。它不提供缓存过期更新、内存索引建立等功能,不占用内存空间,对静态数据的效果比较好。该指令的语法结构为:

proxy_store on | off | string;

on | off : 设置是否开启 Proxy Cache 功能。如果使用变量 on,功能开启,缓存文件会存放在alias指令或者root指令设置的本地路径下。默认设置为 off。

string:自定义缓存文件存放路径。

Proxy Store 方法多使用在被代理服务器端发生错误的情况下,用来缓存被代理服务器的响应数据。

 

  • proxy_store_access

配置用户或者用户组对Proxy Store 缓存的数据访问权限,其语法结构为:

proxy_store_access users:permissions ...;

users:可以设置为 user、 group 或 all。

permissions: 设置权限。

配置实例:

location /images/ {
    root               /data/www;
    error_page         404 = /fetch$uri;		#定义了404错误的请求页面
}

location /fetch/ {					#匹配 404错误时的请求页面
    internal;

    proxy_pass         http://backend/;
    proxy_store        on;				#开启 Proxy Store 方法
    proxy_store_access user:rw group:rw all:r;
    proxy_temp_path    /data/temp;

    alias              /data/www/;			#缓存数据的路径
}

或者

location /images/ {
    root               /data/www;
    error_page         404 = @fetch;
}

location @fetch {
    internal;

    proxy_pass         http://backend;
    proxy_store        on;
    proxy_store_access user:rw group:rw all:r;
    proxy_temp_path    /data/temp;

    root               /data/www;
}

 

 

缓存实例

user smqk;
worker_processes auto;
error_log /home/smqk/logs/nginx/error.log;
pid /run/nginx.pid;

# Load dynamic modules. See /usr/share/nginx/README.dynamic.
include /usr/share/nginx/modules/*.conf;

events {
    worker_connections 1024;
}

http {
    log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                      '$status $body_bytes_sent "$http_referer" '
                      '"$http_user_agent" "$http_x_forwarded_for"';

    access_log  /home/smqk/logs/nginx/access.log  main;

    #设置允许发布内容为200M
    client_max_body_size 200M;

    client_header_buffer_size 16k;

    #underscores_in_headers on; 
    sendfile            on;
    tcp_nopush          on;
    tcp_nodelay         on;
    keepalive_timeout   65;
    types_hash_max_size 2048;

    include             /etc/nginx/mime.types;
    default_type        application/octet-stream;

    proxy_cache_path /home/smqk/xuexiyuan.cn/cache/blog levels=2:2 keys_zone=blog:100m inactive=3d max_size=1g;

    server {
        listen       80;
        server_name  localhost;
        index index.html;

        proxy_cache blog;
        #proxy_cache_methods GET HEAD;

		#Nginx静态资源代理(静态资源由Nginx来处理并响应用户请求)	
		location ~ /resources/.*\.(js|css|png|jpg|ico|gif|woff2|mp3|mp4)$ {
			add_header Handler nginx;

			#定义用户浏览器缓存时间15天
			expires      15d;

			#请求根目录,Web服务器收到请求之后,首先要在服务器端指定目录中寻找请求资源,以下root指令就是用来配置这个根目录
			root /home/smqk/xuexiyuan.cn/;
		}


        location / {			
			#添加缓存状态响应消息头
			add_header X-Cache "$upstream_cache_status From $host";

			proxy_cache_valid  200 5m;
			
			# 尝试指定有参数的不使用 proxy cache,但没有用,不知道为什么????
			#proxy_no_cache $arg_nocache;
			#proxy_cache_bypass $arg_nocache;

			proxy_cache_key $scheme$proxy_host$uri$is_args$args;

			proxy_pass http://127.0.0.1:8080;
            error_page 404 /404.html;
        }

        error_page  404 /resources/html/404.html;
        error_page  500 502 503 504  /50x.html;
        location = /50x.html {
            root  /resources/html/;
        }
  }
}

 

参考文献:

http://nginx.org/en/docs/http/ngx_http_proxy_module.html



MongoDB学习园