nginx服务器开启缓存、反向代理
一、反向代理配置
1、反向代理服务器配置如下
反向代理就是需要这一行proxy_pass来完成。当我们要访问后端web服务器的时候,我们只需要访问代理服务器就可以了,此时代理服务器就充当后端web服务器的角色。proxy_pass依赖的模块是:
至于后两行是什么意思呢?
“proxy_set_header Host”表示后端web服务器的域名要与当前配置文件中的域名保持一致。
后端web服务器我们配置一下:
代理服务器和web服务器都重载一下nginx。我们在windows上浏览一下(注意修改hosts文件,对代理服务器ip添加映射)
看看这个
浏览成功了。反向代理成功。访问不同的域名有不同的路径关系。
2、proxy_pass后面的域名加上一个“/”是什么作用呢?
比如:后面有没有加上这个“/”,差别是很大的。
比如:我们再次配置代理服务器:
注意在web服务器上也要创建admin目录。然后我们访问一下:
再看看这个目录:
总结:这就是加不加根号“/”的区别。不加根号表示域名的后面跟上location中的uri。而加上根号则表示域名后面的根替换了location后的uri。此时访问的是根下的index.html。所以说当你的location后面只有一个根“/”,域名结尾加不加“/”都一个样子,但是location后面有uri时,域名后面加不加根差别很大。还有一个:
当location中包含正则表达式的时候,proxy_pass的域名后面绝对不能带上根号,否则报错:
总结:
2、proxy_set_header field value;
设定发往后端主机的请求报文的请求首部的值;Context: http, server, location
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
一般是来说我们更多使用X-Forwarded-For这个参数,参数的用法我在之前的博客也说过。https://www.cnblogs.com/FengGeBlog/p/10529821.html
添加响应报文守护主要是将添加的内容发送给客户端的,比如上面那个add_header参数,“add_header X-Vis $server_addr”表示将服务器地址发送给客户端。
3、缓存话题:
一个web缓存坐落于客户端和“原始服务器(origin server)”中间,它保留了所有可见内容的拷贝。如果一个客户端请求的内容在缓存中存储,则可以直接在缓存中获得该内容而不需要与服务器通信。这样一来,由于web缓存距离客户端“更近”,就可以提高响应性能,并更有效率的使用应用服务器,因为服务器不用每次请求都进行页面生成工作。
在浏览器和应用服务器之间,存在多种“潜在”缓存,如:客户端浏览器缓存、中间缓存、内容分发网络(CDN)和服务器上的负载平衡和反向代理。缓存,仅在反向代理和负载均衡的层面,就对性能提高有很大的帮助。
举个例子说明,去年,我接手了一项任务,这项任务的内容是对一个加载缓慢的网站进行性能优化。首先引起我注意的事情是,这个网站差不多花费了超过1秒钟才生成了主页。经过一系列调试,我发现加载缓慢的原因在于页面被标记为不可缓存,即为了响应每一个请求,页面都是动态生成的。由于页面本身并不需要经常性的变更,并且不涉及个性化,那么这样做其实并没有必要。为了验证一下我的结论,我将页面标记为每5秒缓存一次,仅仅做了这一个调整,就能明显的感受到性能的提升。第一个字节到达的时间降低到几毫秒,同时页面的加载明显要更快。
并不是只有大规模的内容分发网络(CDN)可以在使用缓存中受益——缓存还可以提高负载平衡器、反向代理和应用服务器前端web服务的性能。通过上面的例子,我们看到,缓存内容结果,可以更高效的使用应用服务器,因为不需要每次都去做重复的页面生成工作。此外,Web缓存还可以用来提高网站可靠性。当服务器宕机或者繁忙时,比起返回错误信息给用户,不如通过配置NGINX将已经缓存下来的内容发送给用户。这意味着,网站在应用服务器或者数据库故障的情况下,可以保持部分甚至全部的功能运转。
1)如何安装配置基础缓存。
我们只需要两个命令就可以启用基础缓存: proxy_cache_path[1]和proxy_cache[2]。proxy_cache_path用来设置缓存的路径和配置,proxy_cache用来启用缓存。
我们建议将proxy_cache_path放在nginx的主配置文件http段中,表示对所有的server生效。
http{
proxy_cache_path /path/to/cache levels=1:2 keys_zone=my_cache:10m max_size=10g inactive=60m use_temp_path=off; server { ... location / { proxy_cache my_cache; proxy_pass http://my_upstream; } }
}
proxy_cache_path命令中的参数及对应配置说明如下:
1.用于缓存的本地磁盘目录是/path/to/cache/
2.levels在/path/to/cache/设置了一个两级层次结构的目录。将大量的文件放置在单个目录中会导致文件访问缓慢,所以针对大多数部署,我们推荐使用两级目录层次结构。如果levels参数没有配置,则NGINX会将所有的文件放到同一个目录中。
3.keys_zone设置一个共享内存区,该内存区用于存储缓存键和元数据,有些类似计时器的用途。将键的拷贝放入内存可以使NGINX在不检索磁盘的情况下快速决定一个请求是`HIT`还是`MISS`,这样大大提高了检索速度。一个1MB的内存空间可以存储大约8000个key,那么上面配置的10MB内存空间可以存储差不多80000个key。
4.max_size设置了缓存的上限(在上面的例子中是10G)。这是一个可选项;如果不指定具体值,那就是允许缓存不断增长,占用所有可用的磁盘空间。当缓存达到这个上线,处理器便调用cache manager来移除最近最少被使用的文件,这样把缓存的空间降低至这个限制之下。
5.inactive指定了项目在不被访问的情况下能够在内存中保持的时间。在上面的例子中,如果一个文件在60分钟之内没有被请求,则缓存管理将会自动将其在内存中删除,不管该文件是否过期。该参数默认值为10分钟(10m)。注意,非活动内容有别于过期内容。NGINX不会自动删除由缓存控制头部指定的过期内容(本例中Cache-Control:max-age=120)。过期内容只有在inactive指定时间内没有被访问的情况下才会被删除。如果过期内容被访问了,那么NGINX就会将其从原服务器上刷新,并更新对应的inactive计时器。
6.NGINX最初会将注定写入缓存的文件先放入一个临时存储区域, use_temp_path=off命令指示NGINX将在缓存这些文件时将它们写入同一个目录下。我们强烈建议你将参数设置为off来避免在文件系统中不必要的数据拷贝。use_temp_path在NGINX1.7版本和NGINX Plus R6[3]中有所介绍。
最终, proxy_cache命令启动缓存那些URL与location部分匹配的内容(本例中,为`/`)。你同样可以将proxy_cache命令添加到server部分,这将会将缓存应用到所有的那些location中未指定自己的proxy_cache命令的服务中。
NGINX内容缓存[4]的一个非常强大的特性是:当无法从原始服务器获取最新的内容时,NGINX可以分发缓存中的陈旧(stale,编者注:即过期内容)内容。这种情况一般发生在关联缓存内容的原始服务器宕机或者繁忙时。比起对客户端传达错误信息,NGINX可发送在其内存中的陈旧的文件。NGINX的这种代理方式,为服务器提供额外级别的容错能力,并确保了在服务器故障或流量峰值的情况下的正常运行。为了开启该功能,只需要添加proxy_cache_use_stale[5]命令即可:
location / {
...
proxy_cache_use_stale error timeout http_500 http_502 http_503 http_504;
}
按照上面例子中的配置,当NGINX收到服务器返回的error,timeout或者其他指定的5xx错误,并且在其缓存中有请求文件的陈旧版本,则会将这些陈旧版本的文件而不是错误信息发送给客户端。
2)缓存微调
NGINX提供了丰富的可选项配置用于缓存性能的微调。
proxy_cache_path /path/to/cache levels=1:2 keys_zone=my_cache:10m max_size=10g inactive=60m use_temp_path=off; server { ... location / { proxy_cache my_cache; proxy_cache_revalidate on; proxy_cache_min_uses 3; proxy_cache_use_stale error timeout updating http_500 http_502 http_503 http_504; proxy_cache_lock on; proxy_pass http://my_upstream; } }
这些命令配置了下列的行为:
1.proxy_cache_revalidate[6]指示NGINX在刷新来自服务器的内容时使用GET请求。如果客户端的请求项已经被缓存过了,但是在缓存控制头部中定义为过期,那么NGINX就会在GET请求中包含If-Modified-Since字段,发送至服务器端。这项配置可以节约带宽,因为对于NGINX已经缓存过的文件,服务器只会在该文件请求头中Last-Modified记录的时间内被修改时才将全部文件一起发送。
2.proxy_cache_min_uses[7]设置了在NGINX缓存前,客户端请求一个条目的最短时间。当缓存不断被填满时,这项设置便十分有用,因为这确保了只有那些被经常访问的内容才会被添加到缓存中。该项默认值为1。
3.proxy_cache_use_stale[8]中的updating参数告知NGINX在客户端请求的项目的更新正在原服务器中下载时发送旧内容,而不是向服务器转发重复的请求。第一个请求陈旧文件的用户不得不等待文件在原服务器中更新完毕。陈旧的文件会返回给随后的请求直到更新后的文件被全部下载。
4.当proxy_cache_lock[9]被启用时,当多个客户端请求一个缓存中不存在的文件(或称之为一个MISS),只有这些请求中的第一个被允许发送至服务器。其他请求在第一个请求得到满意结果之后在缓存中得到文件。如果不启用proxy_cache_lock,则所有在缓存中找不到文件的请求都会直接与服务器通信。
3)跨多硬盘分隔缓存
使用NGINX,不需要建立一个RAID(磁盘阵列)。如果有多个硬盘,NGINX可以用来在多个硬盘之间分割缓存。下面是一个基于请求URI跨越两个硬盘之间均分缓存的例子:
proxy_cache_path /path/to/hdd1 levels=1:2 keys_zone=my_cache_hdd1:10m max_size=10g inactive=60m use_temp_path=off; proxy_cache_path /path/to/hdd2 levels=1:2 keys_zone=my_cache_hdd2:10m max_size=10g inactive=60m use_temp_path=off; split_clients $request_uri $my_cache { 50% “my_cache_hdd1”; 50% “my_cache_hdd2”; } server { ... location / { proxy_cache $my_cache; proxy_pass http://my_upstream; } }
上例中的两个proxy_cache_path定义了两个缓存(my_cache_hdd1和my_cache_hd22)分属两个不同的硬盘。split_clients[10]配置部分指定了请求结果的一半在my_cache_hdd1中缓存,另一半在my_cache_hdd2中缓存。基于$request_uri(请求URI)变量的哈希值决定了每一个请求使用哪一个缓存,对于指定URI的请求结果通常会被缓存在同一个缓存中。
4)常见问题解答
4.1)可以检测NGINX缓存状态吗?
可以,使用add_header[11]指令:
add_header X-Cache-Status $upstream_cache_status;
上面的例子中,在对客户端的响应中添加了一个`X-Cache-Status`HTTP响应头,下面是$upstream_cache_status[12]的可能值:
- MISS——响应在缓存中找不到,所以需要在服务器中取得。这个响应之后可能会被缓存起来。
- BYPASS——响应来自原始服务器而不是缓存,因为请求匹配了一个proxy_cache_bypass(见下面我可以在缓存中打个洞吗?[13])。这个响应之后可能会被缓存起来。
- EXPIRED——缓存中的某一项过期了,来自原始服务器的响应包含最新的内容。
- STALE——内容陈旧是因为原始服务器不能正确响应。需要配置proxy_cache_use_stale。
- UPDATING——内容过期了,因为相对于之前的请求,响应的入口(entry)已经更新,并且proxy_cache_use_stale的updating已被设置。
- REVALIDATED——proxy_cache_revalidate[14]命令被启用,NGINX检测得知当前的缓存内容依然有效(If-Modified-Since或者If-None-Match)。
- HIT——响应包含来自缓存的最新有效的内容。
4.2)nginx如何决定缓存
默认情况下,NGINX需要考虑从原始服务器得到的Cache-Control标头。当在响应头部中Cache-Control被配置为Private,No-Cache,No-Store或者Set-Cookie,NGINX不进行缓存。NGINX仅仅缓存GET和HEAD客户端请求。你也可以参照下面的解答覆盖这些默认值。
Cache-Control头部可否被忽略?
可以,使用proxy_ignore_headers命令。如下列配置:
location /images/ { proxy_cache my_cache; proxy_ignore_headers Cache-Control; proxy_cache_valid any 30m; ... }
NGINX会忽略所有/images/下的Cache-Control头。proxy_cache_valid[15]命令强制规定缓存数据的过期时间,如果忽略Cache-Control头,则该命令是十分必要的。NGINX不会缓存没有过期时间的文件。
4.3)NGINX 可以缓存动态内容吗?
可以,提供的Cache-Control头部可以做到。缓存动态内容,甚至短时间内的内容可以减少在原始数据库和服务器中加载,可以提高第一个字节的到达时间,因为页面不需要对每个请求都生成一次。
4.4)nginx使用了哪些缓存键?
NGINX生成的键的默认格式是类似于下面的NGINX变量[17]的MD5哈希值: $scheme$proxy_host$request_uri,实际的算法有些复杂。
proxy_cache_path /path/to/cache levels=1:2 keys_zone=my_cache:10m max_size=10g inactive=60m use_temp_path=off; server { ... location / { proxy_cache $my_cache; proxy_pass http://my_upstream; } }
按照上面的配置, http://www.example.org/my_image.jpg的缓存键被计算为md5(“http://my_upstream:80/my_image.jpg”)。
注意,$proxy_host[18]变量用于哈希之后的值而不是实际的主机名(www.example.com)。$proxy_host被定义为proxy_pass[19]中指定的代理服务器的主机名和端口号。
为了改变变量(或其他项)作为基础键,可以使用proxy_cache_key[20]命令(下面的问题会讲到)。
4.5)可以使用Cookie作为缓存键的一部分吗?
可以,缓存键可以配置为任意值,如:
proxy_cache_key $proxy_host$request_uri$cookie_jessionid;
案例演示:
其他的参数使用默认值就可以了。
补充点知识:
2、proxy_set_header field value; 设定发往后端主机的请求报文的请求首部的值;Context: http, server, location proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; 3、proxy_cache_path 定义可用于proxy功能的缓存;Context: http 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]; 4、proxy_cache zone | off; 指明要调用的缓存,或关闭缓存机制;Context: http, server, location 5、 proxy_cache_key string; 缓存中用于“键”的内容; 默认值:proxy_cache_key $scheme$proxy_host$request_uri; 6、proxy_cache_valid [code ...] time; 定义对特定响应码的响应内容的缓存时长; 定义在http{...}中; proxy_cache_path /var/cache/nginx/proxy_cache levels=1:1:1 keys_zone=pxycache:20m max_size=1g; 定义在需要调用缓存功能的配置段,例如server{...}; proxy_cache pxycache; proxy_cache_key $request_uri; proxy_cache_valid 200 302 301 1h; proxy_cache_valid any 1m; 7、proxy_cache_use_stale proxy_cache_use_stale error | timeout | invalid_header | updating | http_500 | http_502 | http_503 | http_504 | http_403 | http_404 | off ...; Determines in which cases a stale cached response can be used when an error occurs during communication with the proxied server. 8、proxy_cache_methods GET | HEAD | POST ...; If the client request method is listed in this directive then the response will be cached. “GET” and “HEAD” methods are always added to the list, though it is recommended to specify them explicitly. 9、proxy_hide_header field; By default, nginx does not pass the header fields “Date”, “Server”, “X-Pad”, and “X-Accel-...” from the response of a proxied server to a client. The proxy_hide_header directive sets additional fields that will not be passed. 10、proxy_connect_timeout time; Defines a timeout for establishing a connection with a proxied server. It should be noted that this timeout cannot usually exceed 75 seconds. 客户端面向服务端的超时连接是多长时间。默认为60s;最长为75s; 11、proxy_read_timeout time; Defines a timeout for reading a response from the proxied server. The timeout is set only between two successive read operations, not for the transmission of the whole response. 12、proxy_send_timeout time; Sets a timeout for transmitting a request to the proxied server. he timeout is set only between two successive write operations, not for the transmission of the whole request. If the proxied server does not receive anything within this time, the connection is closed.