Fork me on GitHub

nginx proxy_cache缓存详解

1. 关于缓冲区指令

1.1 proxy_buffer_size

语法:	proxy_buffer_size size;
默认值:	proxy_buffer_size 4k|8k;
上下文:	http, server, location
  1. 该缓冲用于来自上游服务器响应的开始部分,在该部分通常包含一个小小的响应头
  2. 该缓冲区大小默认等于proxy_buffers指令设置的一块缓冲区的大小,没有必要也跟着设置太大。 proxy_buffer_size最好单独设置,一般设置个4k就够了,但它也可以被设置得更小。
  3. 一块缓冲区的大小通常等于一个内存页的大小(4K或者8K),获取Linux 内存页(基页)大小的命令:getconf PAGE_SIZE ,一般的输出是4096,即 4KB。

1.2 proxy_buffering

语法:	proxy_buffering on | off;
默认值:	proxy_buffering on;
上下文:	http, server, location
  1. 该指令控制缓冲是否启用。默认情况下,它的值是“on”。如果这个设置为off,那么proxy_buffers和proxy_busy_buffers_size这两个指令将会失效。 但是无论proxy_buffering是否开启,对proxy_buffer_size配置都会起作用。
  2. 当开启缓冲时,nginx尽可能快地从被代理的服务器接收响应,再将它存入proxy_buffer_size和proxy_buffers指令设置的缓冲区中。如果响应无法整个纳入内存,那么其中一部分将存入磁盘上的临时文件,某些请求的响应过大,则超过_buffers的部分将被缓冲到硬盘, 当然这将会使读取响应的速度减慢, 影响用户体验。通过proxy_max_temp_file_size和proxy_temp_file_write_size指令可以控制临时文件的写入。
  3. 当关闭缓冲时,收到响应后,nginx立即将其同步传给客户端。nginx不会尝试从被代理的服务器读取整个请求,而是将proxy_buffer_size指令设定的大小作为一次读取的最大长度(所以无论是否开启,proxy_buffer_size都起作用)。每次传输内容小了,效率肯定会有影响。
  4. 响应头“X-Accel-Buffering”传递“yes”或“no”可以动态地开启或关闭代理的缓冲功能。 这个能力可以通过proxy_ignore_headers指令关闭。

proxy_buffering启用时,要提防使用的代理缓冲区太大。这可能会吃掉你的内存,限制代理能够支持的最大并发连接数。

1.3 proxy_buffers

语法:	proxy_buffers number size;
默认值:	proxy_buffers 8 4k|8k;
上下文:	http, server, location
  1. 为每个连接设置缓冲区的数量为number,每块缓冲区的大小为size。这些缓冲区用于保存从被代理的服务器读取的响应。
  2. proxy_buffers的缓冲区大小一般会设置的比较大,以应付大网页。proxy_buffers当中单个缓冲区的大小是由系统的内存页面大小决定的,Linux系统中一般为4k。 proxy_buffers由缓冲区数量和缓冲区大小组成的。总的大小为number*size。

1.4 proxy_busy_buffers_size

语法:	proxy_busy_buffers_size size;
默认值:	proxy_busy_buffers_size 8k|16k;
上下文:	http, server, location
  1. 当开启缓冲响应的功能以后,在没有读到全部响应的情况下,写缓冲到达一定大小时,nginx一定会向客户端发送响应,直到缓冲小于此值。这条指令用来设置此值。
  2. 同时,剩余的缓冲区可以用于接收响应,如果需要,一部分内容将缓冲到临时文件。该大小默认是proxy_buffer_size和proxy_buffers指令设置单块缓冲大小的两倍。

1.5 proxy_max_temp_file_size

语法:	proxy_max_temp_file_size size;
默认值:	proxy_max_temp_file_size 1024m;
上下文:	http, server, location
  1. 打开响应缓冲以后,如果整个响应不能存放在proxy_buffer_size和proxy_buffers指令设置的缓冲区内,部分响应可以存放在临时文件中。 这条指令可以设置临时文件的最大容量。而每次写入临时文件的数据量则由proxy_temp_file_write_size指令定义。
  2. 写入硬盘的临时文件的大小,如果超过了这个值, Nginx将与Proxy服务器同步的传递内容, 而不再缓冲到硬盘. 设置为0时,将禁止响应写入临时文件,也就相当于直接关闭硬盘缓冲。

1.6 proxy_temp_file_write_size

语法:	proxy_temp_file_write_size size;
默认值:	proxy_temp_file_write_size 8k|16k;
上下文:	http, server, location

在开启缓冲后端服务器响应到临时文件的功能后,设置nginx每次写数据到临时文件的size(大小)限制。 size的默认值是proxy_buffer_size指令和proxy_buffers指令定义的每块缓冲区大小的两倍, 而临时文件最大容量由proxy_max_temp_file_size指令设置。

1.7 缓冲区配置实例

通用网站的配置

proxy_buffer_size 4k; #设置代理服务器(nginx)保存用户头信息的缓冲区大小
proxy_buffers 4 32k; #proxy_buffers缓冲区,网页平均在32k以下的设置
proxy_busy_buffers_size 64k; #高负荷下缓冲大小(proxy_buffers*2)
proxy_temp_file_write_size 64k;
#设定缓存文件夹大小,大于这个值,将从upstream服务器传

docker registry的配置 这个每次传输至少都是9M以上的内容,缓冲区配置大;

proxy_buffering on;
proxy_buffer_size 4k; 
proxy_buffers 8 1M;
proxy_busy_buffers_size 2M;
proxy_max_temp_file_size 0;

关于缓冲区大小的配置,还是需要实地的分析,一般来说通用配置可以应付了。

2. 常用配置项

2.1 proxy_cache_path

语法:	proxy_cache_path path [levels=levels] keys_zone=name:size [inactive=time] [max_size=size] [loader_files=number] [loader_sleep=time] [loader_threshold=time];
默认值:	—
上下文:	http
  • path 指定缓存文件目录,和 proxy_temp_path 最好设置在同一文件分区下,缓存内容是先写在 temp_path,临时文件和缓存可以放在不同的文件系统,将导致文件在这两个文件系统中进行拷贝,而不是廉价的重命名操作。因此,针对任何路径,都建议将缓存和proxy_temp_path指令设置的临时文件目录放在同一文件系统。
  • level 定义了缓存的层次结构,每层可以用1(最多16中选择,0-f)或2(最多256种选择,00-ff)表示,中间用 [冒号] 分隔。“levels=1:2”表示开启1、2层级(第2层级理论有16*256个目录)。
proxy_cache_path /data/nginx/cache;  # 所有缓存只有一个目录
/data/nginx/cache/d7b6e5978e3f042f52e875005925e51b 

proxy_cache_path /data/nginx/cache levels=1:2;  # 第二层级有16*256=4096个目录
/data/nginx/cache/b/51/d7b6e5978e3f042f52e875005925e51b 

proxy_cache_path /data/nginx/cache levels=1:1:1; #第三层级有16*16*16个目录
/data/nginx/cache/b/1/5/d7b6e5978e3f042f52e87500592 

proxy_cache_path /data/nginx/cache levels=2; # 第一层级有256个目录
/data/nginx/cache/1b/d7b6e5978e3f042f52e875005925e51b 
  • keys_zone 指定一个共享内存空间zone,所有活动的键和缓存数据相关的信息都被存放在共享内存中,这样nginx可以快速判断一个request是否命中或者未命中缓存,1m可以存储8000个key,10m可以存储80000个key;
  • inactive inactive=30m 表示 30 分钟没有被访问的文件会被 cache manager 删除,inactive的默认值是10分钟。 需要注意的是,inactive和expired配置项的含义是不同的,expired只是缓存过期,但不会被删除,inactive是删除指定时间内未被访问的缓存文件
  • max_size cache存储的最大尺寸,如果不指定,会用掉所有磁盘空间,当尺寸超过,将会基于LRU算法移除数据,以减少占用大小。nginx启动时,会创建一个“Cache manager”进程,通过“purge”方式移除数据。
  • loader_files “cache loader”进程遍历文件时,每次加载的文件个数。默认为100.
  • loader_threshold 每次遍历消耗时间上限。默认为200毫秒。
  • loader_sleep 一次遍历之后,停顿的时间间隔,默认为50毫秒。

需要注意的是:

特殊进程“cache manager”监控缓存的条目数量,如果超过max_size参数设置的最大值,使用LRU算法移除缓存数据。nginx新启动后不就,特殊进程“cache loader”就被启动。该进程将文件系统上保存的过去缓存的数据的相关信息重新加载到共享内存。加载过程分多次迭代完成,每次迭代,进程只加载不多于loader_files参数指定的文件数量(默认值为100)。此外,每次迭代过程的持续时间不能超过loader_threshold参数的值(默认200毫秒)。每次迭代之间,nginx的暂停时间由loader_sleep参数指定(默认50毫秒)。缓存文件并不是越多越好,所以 cache_key 的设计非常关键。代理或 URL 跳转常常会添加的无用请求参数,这就会出现不同的 cache_key 保存了多份相同的缓存内容,这对缓存效果影响很大。

2.2 proxy_temp_path

语法:	proxy_temp_path path [level1 [level2 [level3]]];
默认值:	
proxy_temp_path proxy_temp;
上下文:	http, server, location

定义从后端服务器接收的临时文件的存放路径,可以为临时文件路径定义至多三层子目录的目录树。 比如,下面配置

proxy_temp_path /spool/nginx/proxy_temp 1 2;

那么临时文件的路径看起来会是这样:

/spool/nginx/proxy_temp/7/45/00000123457

2.3 proxy_cache

语法:	proxy_cache zone | off;
默认值:	proxy_cache off;
上下文:	http, server, location

指定用于页面缓存的共享内存。同一块共享内存可以在多个地方使用。off参数可以屏蔽从上层配置继承的缓存功能。zone名称由“proxy_cache_path”指令定义。

2.4 proxy_cache_key

语法:	proxy_cache_key string;
默认值:	
proxy_cache_key $scheme$proxy_host$request_uri;
上下文:	http, server, location

定义如何生成缓存的键,比如

proxy_cache_key "$host$request_uri $cookie_user";

这条指令的默认值类似于下面字符串

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

缓存文件并不是越多越好,所以 cache_key 的设计非常关键。代理或 URL 跳转常常会添加的无用请求参数,这就会出现不同的 cache_key 保存了多份相同的缓存内容,这对缓存效果影响很大。通过 ngx_lua 可以对 URL 参数进行过滤,保证 cache_key 唯一。

2.5 proxy_cache_valid

语法:	proxy_cache_valid [code ...] time;
默认值:	—
上下文:	http, server, location

为不同的响应状态码设置不同的缓存时间。比如,下面指令

proxy_cache_valid 200 302 10m;
proxy_cache_valid 404      1m;

设置状态码为200和302的响应的缓存时间为10分钟,状态码为404的响应的缓存时间为1分钟。

如果仅仅指定了time,

proxy_cache_valid 5m;

那么只有状态码为200、300和302的响应会被缓存。

如果使用了any参数,那么就可以缓存任何响应:

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

缓存参数也可以直接在响应头中设定。这种方式的优先级高于使用这条指令设置缓存时间。

“X-Accel-Expires”响应头可以以秒为单位设置响应的缓存时间,如果值为0,表示禁止缓存响应,如果值以@开始,表示自1970年1月1日以来的秒数,响应一直会被缓存到这个绝对时间点。
如果不含“X-Accel-Expires”响应头,缓存参数仍可能被“Expires”或者“Cache-Control”响应头设置。
如果响应头含有“Set-Cookie”,响应将不能被缓存。 这些头的处理过程可以使用指令proxy_ignore_headers忽略。

2.6 proxy_ignore_headers

语法:	proxy_ignore_headers field ...;
默认值:	—
上下文:	http, server, location

指定来自后端server的响应中的某些header不会被处理,如下几个fields可以被ignore:“X-Accel-Redirect”、“X-Accel-Expires”、“X-Accel-Limit-Rate”、“X-Accel-Buffering”、“X-Accel-Charset”、“Expires”、“Cache-Control”、“Set-Cookie”、“Vary”。“不被处理”就是nginx不会尝试解析这些header并应用它们,比如nginx处理来自后端server的“Expires”,将会影响它本地的文件cache的机制

如果不被取消,这些头部的处理可能产生下面结果:

“X-Accel-Expires”,“Expires”,“Cache-Control”,和“Set-Cookie” 设置响应缓存的参数;
“X-Accel-Redirect”执行到指定URI的内部跳转;
“X-Accel-Limit-Rate”设置响应到客户端的传输速率限制;
“X-Accel-Buffering”启动或者关闭响应缓冲;
“X-Accel-Charset”设置响应所需的字符集。

2.7 proxy_hide_header

语法:	proxy_hide_header field;
默认值:	—
上下文:	http, server, location

nginx默认不会将“Date”、“Server”、“X-Pad”,和“X-Accel-...”响应头发送给客户端。proxy_hide_header指令则可以设置额外的响应头,这些响应头也不会发送给客户端。相反的,如果希望允许传递某些响应头给客户端,可以使用proxy_pass_header指令。

2.8 proxy_pass_header

语法:	proxy_pass_header field;
默认值:	—
上下文:	http, server, location

允许传送被屏蔽的后端服务器响应头到客户端。

2.9 proxy_cache_min_uses

语法:	proxy_cache_min_uses number;
默认值:	proxy_cache_min_uses 1;
上下文:	http, server, location

设置响应被缓存的最小请求次数。默认为1,当客户端发送相同请求达到规定次数后,nginx才对响应数据进行缓存;指定请求至少被发送了多少次以上时才缓存,可以防止低频请求被缓存

2.10 proxy_cache_use_stale

语法:	proxy_cache_use_stale error | timeout | invalid_header | updating | http_500 | http_502 | http_503 | http_504 | http_404 | off ...;
默认值:	proxy_cache_use_stale off;
上下文:	http, server, location

如果后端服务器出现状况,nginx是可以使用过期的响应缓存的。这条指令就是定义何种条件下允许开启此机制。这条指令的参数与proxy_next_upstream指令的参数相同。

此外,updating参数允许nginx在正在更新缓存的情况下使用过期的缓存作为响应。这样做可以使更新缓存数据时,访问源服务器的次数最少。

在植入新的缓存条目时,如果想使访问源服务器的次数最少,可以使用proxy_cache_lock指令。

2.11 proxy_cache_lock

语法:	proxy_cache_lock on | off;
默认值:	proxy_cache_lock off;
上下文:	http, server, location
这个指令出现在版本 1.1.12.

开启此功能时,对于相同的请求,同时只允许一个请求发往后端,并根据proxy_cache_key指令的设置在缓存中植入一个新条目。 其他请求相同条目的请求将一直等待,直到缓存中出现相应的内容,或者锁在proxy_cache_lock_timeout指令设置的超时后被释放。如果不启用proxy_cache_lock,则所有在缓存中找不到文件的请求都会直接与服务器通信。

2.12 proxy_cache_bypass

语法:	proxy_cache_bypass string ...;
默认值:	—
上下文:	http, server, location

定义nginx不从缓存取响应的条件。如果至少一个字符串条件非空而且非“0”,nginx就不会从缓存中去取响应:

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

本指令可和与proxy_no_cache一起使用。

2.13 proxy_no_cache

语法:	proxy_no_cache string ...;
默认值:	—
上下文:	http, server, location

定义nginx不将响应写入缓存的条件。如果至少一个字符串条件非空而且非“0”,nginx就不将响应存入缓存:

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

这条指令可以和proxy_cache_bypass指令一起使用。

3. 其他一些配置

3.1 proxy_cache_lock_timeout

语法:	proxy_cache_lock_timeout time;
默认值:	proxy_cache_lock_timeout 5s;
上下文:	http, server, location

这个指令出现在版本 1.1.12.

为proxy_cache_lock指令设置锁的超时。

3.2 proxy_read_timeout

语法:	proxy_read_timeout time;
默认值:	proxy_read_timeout 60s;
上下文:	http, server, location

定义从后端服务器读取响应的超时。此超时是指相邻两次读操作之间的最长时间间隔,而不是整个响应传输完成的最长时间。如果后端服务器在超时时间段内没有传输任何数据,连接将被关闭。

3.3 proxy_connect_timeout

语法:	proxy_connect_timeout time;默认值:	
proxy_connect_timeout 60s;
上下文:	http, server, location

设置与后端服务器建立连接的超时时间。应该注意这个超时一般不可能大于75秒。

3.4 proxy_send_timeout

语法:	proxy_send_timeout time;
默认值:	proxy_send_timeout 60s;
上下文:	http, server, location

定义向后端服务器传输请求的超时。此超时是指相邻两次写操作之间的最长时间间隔,而不是整个请求传输完成的最长时间。如果后端服务器在超时时间段内没有接收到任何数据,连接将被关闭。

3.5 proxy_http_version

语法:	proxy_http_version 1.0 | 1.1;
默认值:	proxy_http_version 1.0;
上下文:	http, server, location

这个指令出现在版本 1.1.4.

设置代理使用的HTTP协议版本。默认使用的版本是1.0,而1.1版本则推荐在使用keepalive连接时一起使用。

3.6 proxy_ignore_client_abort

语法:	proxy_ignore_client_abort on | off;
默认值:	proxy_ignore_client_abort off;
上下文:	http, server, location

决定当客户端在响应传输完成前就关闭连接时,nginx是否应关闭后端连接。

3.7 proxy_intercept_errors

语法:	proxy_intercept_errors on | off;
默认值:	proxy_intercept_errors off;
上下文:	http, server, location

当后端服务器的响应状态码大于等于400时,决定是否直接将响应发送给客户端,亦或将响应转发给nginx由error_page指令来处理。

3.8 proxy_next_upstream

语法:	proxy_next_upstream error | timeout | invalid_header | http_500 | http_502 | http_503 | http_504 | http_404 | off ...;
默认值:	proxy_next_upstream error timeout;
上下文:	http, server, location

指定在何种情况下一个失败的请求应该被发送到下一台后端服务器:

error
和后端服务器建立连接时,或者向后端服务器发送请求时,或者从后端服务器接收响应头时,出现错误;
timeout
和后端服务器建立连接时,或者向后端服务器发送请求时,或者从后端服务器接收响应头时,出现超时;
invalid_header
后端服务器返回空响应或者非法响应头;
http_500
后端服务器返回的响应状态码为500;
http_502
后端服务器返回的响应状态码为502;
http_503
后端服务器返回的响应状态码为503;
http_504
后端服务器返回的响应状态码为504;
http_404
后端服务器返回的响应状态码为404;
off
停止将请求发送给下一台后端服务器。

需要理解一点的是,只有在没有向客户端发送任何数据以前,将请求转给下一台后端服务器才是可行的。也就是说,如果在传输响应到客户端时出现错误或者超时,这类错误是不可能恢复的。

语法:	proxy_cookie_domain off;
proxy_cookie_domain domain replacement;
默认值:	proxy_cookie_domain off;
上下文:	http, server, location

这个指令出现在版本 1.1.15.

设置“Set-Cookie”响应头中的domain属性的替换文本。 假设后端服务器返回的“Set-Cookie”响应头含有属性“domain=localhost”,那么指令

proxy_cookie_domain localhost example.org;
将这个属性改写为“domain=example.org”。

domain和replacement配置字符串,以及domain属性中起始的点将被忽略。 匹配过程大小写不敏感。

domain和replacement配置字符串中可以包含变量:

proxy_cookie_domain www.$host $host;
这条指令同样可以使用正则表达式。这时,domain应以“~”标志开始,且可以使用命名匹配组和位置匹配组,而replacement可以引用这些匹配组:

proxy_cookie_domain ~\.(?P<sl_domain>[-0-9a-z]+\.[a-z]+)$ $sl_domain;

可以同时定义多条proxy_cookie_domain指令:

proxy_cookie_domain localhost example.org;
proxy_cookie_domain ~\.([a-z]+\.[a-z]+)$ $1;

off参数可以取消当前配置级别的所有proxy_cookie_domain指令:

proxy_cookie_domain off;
proxy_cookie_domain localhost example.org;
proxy_cookie_domain www.example.org example.org;
语法:	proxy_cookie_path off;
proxy_cookie_path path replacement;
默认值:	proxy_cookie_path off;
上下文:	http, server, location

这个指令出现在版本 1.1.15.

设置“Set-Cookie”响应头中的path属性的替换文本。 假设后端服务器返回的“Set-Cookie”响应头含有属性“path=/two/some/uri/”,那么指令

proxy_cookie_path /two/ /;

将这个属性改写为“path=/some/uri/”。

path和replacement配置字符串可以包含变量:

proxy_cookie_path $uri /some$uri;

这条指令同样可以使用正则表达式。如果使用大小写敏感的匹配,path应以“”标志开始,如果使用大小写不敏感的匹配,path应以“*”标志开始。path可以使用命名匹配组和位置匹配组,replacement可以引用这些匹配组:

proxy_cookie_path ~*^/user/([^/]+) /u/$1;

可以同时定义多条proxy_cookie_path指令:

proxy_cookie_path /one/ /;
proxy_cookie_path / /two/;

off参数可以取消当前配置级别的所有proxy_cookie_path指令:

proxy_cookie_path off;
proxy_cookie_path /two/ /;
proxy_cookie_path ~*^/user/([^/]+) /u/$1;

3.11 proxy_pass

语法:	proxy_pass URL;
默认值:	—
上下文:	location, if in location, limit_except

设置后端服务器的协议和地址,还可以设置可选的URI以定义本地路径和后端服务器的映射关系。 这条指令可以设置的协议是“http”或者“https”,而地址既可以使用域名或者IP地址加端口(可选)的形式来定义:

proxy_pass http://localhost:8000/uri/;

又可以使用UNIX域套接字路径来定义。该路径接在“unix”字符串后面,两端由冒号所包围,比如:

proxy_pass http://unix:/tmp/backend.socket:/uri/;

如果解析一个域名得到多个地址,所有的地址都会以轮转的方式被使用。当然,也可以使用服务器组来定义地址。

请求URI按下面规则传送给后端服务器:

如果proxy_pass使用了URI,当传送请求到后端服务器时,规范化以后的请求路径与配置中的路径的匹配部分将被替换为指令中定义的URI:

location /name/ {
    proxy_pass http://127.0.0.1/remote/;
}

如果proxy_pass没有使用URI,传送到后端服务器的请求URI一般客户端发起的原始URI,如果nginx改变了请求URI,则传送的URI是nginx改变以后完整的规范化URI:

location /some/path/ {
    proxy_pass http://127.0.0.1;
}

在1.1.12版以前,如果proxy_pass没有使用URI,某些情况下,nginx改变URI以后,会错误地将原始URI而不是改变以后的URI发送到后端服务器。
某些情况下,无法确定请求URI中应该被替换的部分:

使用正则表达式定义路径。
这种情况下,指令不应该使用URI。

在需要代理的路径中,使用rewrite指令改变了URI,但仍使用相同配置处理请求(break):

location /name/ {
    rewrite    /name/([^/]+) /users?name=$1 break;
    proxy_pass http://127.0.0.1;
}

这种情况下,本指令设置的URI会被忽略,改变后的URI将被发送给后端服务器。

后端服务器的地址,端口和URI中都可以使用变量:

proxy_pass http://$host$uri;

甚至像这样:

proxy_pass $request;

这种情况下,后端服务器的地址将会在定义的服务器组中查找。如果查找不到,nginx使用resolver来查找该地址。

3.12 proxy_redirect

语法:	proxy_redirect default;
proxy_redirect off;
proxy_redirect redirect replacement;
默认值:	proxy_redirect default;
上下文:	http, server, location

设置后端服务器“Location”响应头和“Refresh”响应头的替换文本。 假设后端服务器返回的响应头是 “Location: http://localhost:8000/two/some/uri/”,那么指令

proxy_redirect http://localhost:8000/two/ http://frontend/one/;

将把字符串改写为 “Location: http://frontend/one/some/uri/”。

replacement字符串可以省略服务器名:

proxy_redirect http://localhost:8000/two/ /;

此时将使用代理服务器的主域名和端口号来替换。如果端口是80,可以不加。

用default参数指定的默认替换使用了location和proxy_pass指令的参数。因此,下面两例配置等价:

location /one/ {
    proxy_pass     http://upstream:port/two/;
    proxy_redirect default;
location /one/ {
    proxy_pass     http://upstream:port/two/;
    proxy_redirect http://upstream:port/two/ /one/;

而且因为同样的原因,proxy_pass指令使用变量时,不允许本指令使用default参数。

replacement字符串可以包含变量:

proxy_redirect http://localhost:8000/ http://$host:$server_port/;

而redirect字符串从1.1.11版本开始也可以包含变量:

proxy_redirect http://$proxy_host:8000/ /;

同时,从1.1.11版本开始,指令支持正则表达式。使用正则表达式的话,如果是大小写敏感的匹配,redirect以“”作为开始,如果是大小写不敏感的匹配,redirect以“*”作为开始。而且redirect的正则表达式中可以包含命名匹配组和位置匹配组,而在replacement中可以引用这些匹配组的值:

proxy_redirect ~^(http://[^:]+):\d+(/.+)$ $1$2;
proxy_redirect ~*/user/([^/]+)/(.+)$      http://$1.example.com/$2;

除此以外,可以同时定义多个proxy_redirect指令:

proxy_redirect default;
proxy_redirect http://localhost:8000/  /;
proxy_redirect http://www.example.com/ /;

另外,off参数可以使所有相同配置级别的proxy_redirect指令无效:

proxy_redirect off;
proxy_redirect default;
proxy_redirect http://localhost:8000/  /;
proxy_redirect http://www.example.com/ /;

最后,使用这条指令也可以为地址为相对地址的重定向添加域名:

proxy_redirect / /;

3.13 proxy_set_header

语法:	proxy_set_header field value;
默认值:	
proxy_set_header Host $proxy_host;
proxy_set_header Connection close;
上下文:	http, server, location

允许重新定义或者添加发往后端服务器的请求头。value可以包含文本、变量或者它们的组合。 当且仅当当前配置级别中没有定义proxy_set_header指令时,会从上面的级别继承配置。 默认情况下,只有两个请求头会被重新定义:

proxy_set_header Host       $proxy_host;
proxy_set_header Connection close;

如果不想改变请求头“Host”的值,可以这样来设置:

proxy_set_header Host       $http_host;

但是,如果客户端请求头中没有携带这个头部,那么传递到后端服务器的请求也不含这个头部。 这种情况下,更好的方式是使用$host变量——它的值在请求包含“Host”请求头时为“Host”字段的值,在请求未携带“Host”请求头时为虚拟主机的主域名:

proxy_set_header Host       $host;

此外,服务器名可以和后端服务器的端口一起传送:

proxy_set_header Host       $host:$proxy_port;

如果某个请求头的值为空,那么这个请求头将不会传送给后端服务器:

proxy_set_header Accept-Encoding "";
语法:	proxy_ssl_session_reuse on | off;
默认值:	proxy_ssl_session_reuse on;
上下文:	http, server, location

决定是否重用与后端服务器的SSL会话。如果日志中出现“SSL3_GET_FINISHED:digest check failed”错误,请尝试关闭会话重用。

3.14 proxy_store

语法:	proxy_store on | off | string;
默认值:	proxy_store off;
上下文:	http, server, location

开启将文件保存到磁盘上的功能。如果设置为on,nginx将文件保存在alias指令或root指令设置的路径中。如果设置为off,nginx将关闭文件保存的功能。此外,保存的文件名也可以使用含变量的string参数来指定:

proxy_store /data/www$original_uri;

保存文件的修改时间根据接收到的“Last-Modified”响应头来设置。响应都是先写到临时文件,然后进行重命名来生成的。从0.8.9版本开始,临时文件和持久化存储可以放在不同的文件系统,但是需要注意这时文件执行的是在两个文件系统间拷贝操作,而不是廉价的重命名操作。因此建议保存文件的路径和proxy_temp_path指令设置的临时文件的路径在同一个文件系统中。

这条指令可以用于创建静态无更改文件的本地拷贝,比如:

location /images/ {
    root                   /data/www;
    open_file_cache_errors off;
    error_page             404 = /fetch$uri;
}

location /fetch/ {
    internal;

    proxy_pass             http://backend/;
    proxy_store            on;
    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;
}
语法:	proxy_store_access users:permissions ...;
默认值:	proxy_store_access user:rw;
上下文:	http, server, location

设置新创建的文件和目录的访问权限,比如:

proxy_store_access user:rw group:rw all:r;

如果指定了任何group或者all的访问权限,那么可以略去user的访问权限:

proxy_store_access group:rw all:r;

4. 其他一些问题

4.1 缓存动态内容

NGINX可以缓存动态内容,但是这不应该乱用,有些情况需要考虑

首先,任何用户相关的数据不应被高速缓存。这可能导致一个用户的数据被呈现给其他用户。如果你的网站是完全静态的,这可能不是一个问题。

如果你的网站有一些动态元素,你将不得不考虑到这一点。你如何处理要看是什么应用程序或服务器处理的后端处理。对于私人的内容,你应该设置Cache-Control头为“no-cache”,“no-sotre”,或者“private”依赖于数据的性质:

4.2 缓存不生效问题

nginx是否缓存是由nginx缓存服务器与源服务器共同决定的, 缓存服务器需要严格遵守源服务器响应的header来决定是否缓存以及缓存的时长。

默认情况下,NGINX需要考虑从原始服务器得到的Cache-Control标头。当在响应头部中Cache-Control被配置为Private,No-Cache,No-Store或者Set-Cookie,NGINX不进行缓存。NGINX仅仅缓存GET和HEAD客户端请求。

可以尝试通过更改头信息改让反代服务器缓存

1、尝试修改源服务器代码,改变程序响应的头信息

2、nginx反代配置提供了proxy_ignore_headers配置来忽略某些头信息,我们可以忽略引起反代不缓存的头信息

proxy_ignore_headers X-Accel-Expires Expires Cache-Control Set-Cookie; 

4.2 缓存过期问题

引起缓存过期的因素

  • inactive:在proxy_cache_path配置项中进行配置,说明某个缓存在inactive指定的时间内如果不访问,将会从缓存中删除。
  • 源服务器php页面中生成的响应头中的Expires,生成语句为:
    header("Expires: Fri, 07 Sep 2013 08:05:18 GMT");
  • 源服务器php页面生成的max-age,生成语句为:
    header("Cache-Control: max-age=60");
  • nginx的配置项 proxy_cache_valid:配置nginx cache中的缓存文件的缓存时间,如果配置项为:proxy_cache_valid 200 304 2m;说明对于状态为200和304的缓存文件的缓存时间是2分钟,两分钟之后再访问该缓存文件时,文件会过期,从而去源服务器重新取数据。

优先级

  • 在同时设置了源服务器端Expires、源服务器端max-age和nginx cahe端的proxy_cache_valid的情况下,以源服务器端设置的Expires的值为标准进行缓存的过期处理
  • 若在nginx中配置了相关配置项(proxy_ignore_headers,proxy_hide_header),取消原服务器端Expires对缓存的影响,在同时设置了源服务器端Expires、源服务器端max-age和nginx cahe端的proxy_cache_valid的情况下,以源服务器端max-age的值为标准进行缓存的过期处理
  • 若同时取消源服务器端Expires和源服务器端max-age对缓存的影响,则以proxy_cache_valid设置的值为标准进行缓存的过期处理
  • Inactive的值不受上述三个因素的影响,即第一次请求页面之后,每经过inactvie指定的时间,都要强制进行相应的缓存清理。因此inactive的优先级最高。

详细的测试可以参照http://www.ttlsa.com/nginx/nginx-cache-priority/

4.3 缓存清除问题

nginx没有提供直接缓存清除的方法,但是我们可以使用以下方法清除

1、但是可以通过使用第三方的模块ngx_cache_purge清除指定的URL
需要加入一个新的location配置

location ~ /purge(/.*) {
    proxy_cache_purge cache_one $host$1$is_args$args;
}

原网址和清除缓存的url对应关系

www.firefoxbug.net/index.html ==>> www.firefoxbug.net/purge/index.html就能清除.

2、直接删除指定的缓存文件

直接想办法删除proxy_cache_path配置的目录下的所有文件,如果你可以直接操作linux那么可以直接rm -rf xxx了,如果不方便可以考虑写个脚本去删除相应的文件目录。

4.4 缓存命中率

nginx 提供了变量$upstream-cache-status 来显示缓存的命中状态,我们可以再nginx.conf配置中添加一个http响应头来显示这一状态

反代配置中加入

location / {
    proxy_pass http://zhengde.xxx.cn;
    proxy_set_header Host zhengde.xxx.cn;
    add_header X-Cache-Status $upstream_cache_status; 
    ... 其他配置
}

在对客户端的响应中添加了一个X-Cache-StatusHTTP响应头,这样可以在响应信息中查看X-Cache-Status状态来判定是否命中

如果想要统计命中率,那么在访问日志的格式中加入$upstream_cache_status记录即可

log_format main   ‘$remote_addr – $remote_user [$time_local] “$request” ‘
                                ‘$status $body_bytes_sent “$http_referer” ‘
                               ’”$http_user_agent” “$http_x_forwarded_for”‘
                               ’”$upstream_cache_status”‘;

然后可以使用awk命令进行统计

命令:awk '{if($NF=="\"HIT\"") hit++}  END  {printf "%.2f%",hit/NR}'   access.log
结果: 32.15%

下面是$upstream_cache_status的可能值:

1.MISS——响应在缓存中找不到,所以需要在服务器中取得。这个响应之后可能会被缓存起来。
2.BYPASS——响应来自原始服务器而不是缓存,因为请求匹配了一个proxy_cache_bypass(见下面我可以在缓存中打个洞吗?)。这个响应之后可能会被缓存起来。
3.EXPIRED——缓存中的某一项过期了,来自原始服务器的响应包含最新的内容。
4.STALE——内容陈旧是因为原始服务器不能正确响应。需要配置proxy_cache_use_stale。
5.UPDATING——内容过期了,因为相对于之前的请求,响应的入口(entry)已经更新,并且proxy_cache_use_stale的updating已被设置。
6.REVALIDATED——proxy_cache_revalidate命令被启用,NGINX检测得知当前的缓存内容依然有效(If-Modified-Since或者If-None-Match)。
7.HIT——响应包含来自缓存的最新有效的内容。

4.5 如何实现动静分离

server  
{  
    listen       10000;  
    server_name  localhost;  
     
    #静态处理交给nginx
    location ~ .*\.(htm|html|gif|jpg|jpeg|png|bmp|swf|ioc|ico|rar|zip|txt|flv|mid|doc|ppt|pdf|xls|mp3|wma|css|js)$ {
        proxy_cache cache_one;
        proxy_cache_valid 200 304 302 2d;
        proxy_cache_valid any 1d;
        proxy_cache_key $host$uri$is_args$args;
        add_header X-Cache '$upstream_cache_status from $host';
        
        proxy_pass http://127.0.0.1:8088;
        expires 30d;
    }
    
    #动态文件不处理
    location / {
        proxy_pass http://127.0.0.1:8080;
    }
}  

参考网址

http://tengine.taobao.org/nginx_docs/cn/docs/http/ngx_http_proxy_module.html#proxy_ignore_headers

https://blog.csdn.net/mary881225/article/details/70173907

http://www.cnblogs.com/bethal/p/5606062.html

http://lmdkfs.blog.163.com/blog/static/74611324201421283237778/

posted @ 2018-12-04 20:47  archer-wong  阅读(5739)  评论(0编辑  收藏  举报