Nginx反向代理和缓存服务功能说明和简单实现-运维笔记
⼀、Nginx反向代理功能
Nginx不仅能作为Web Server,还具有反向代理、负载均衡和缓存的功能。下⾯就简单说下这些功能:
1、proxy模块
nginx通过proxy模块实现将客户端的请求代理⾄上游服务器,此时nginx与上游服务器的连接是通过http协议进⾏的。nginx在实现反向代理功能时的最重要指令为 proxy_pass,它能够并能够根据URI、客户端参数或其它的处理逻辑将⽤户请求调度⾄上游服务器上(upstream server)。
1.1  proxy_pass URL;
设置后端服务器的协议和地址;这条指令可以设置的协议是“http”或者“https”,⽽地址既可以使⽤域名或者IP地址加端⼝(可选)的形式来定义:
proxy_pass localhost:8000/uri/;
如果解析⼀个域名得到多个地址,所有的地址都会以轮转的⽅式被使⽤。当然也可以使⽤服务器组来定义多个地址。
如果proxy_pass没有使⽤URI,传送到后端服务器的请求URI⼀般是客户端发起的原始URI,如果nginx改变了请求URI,则请求路径与配置中的路径的匹配部分将被替换为指令中定义的URI:若nginx接到的请求的uri是/name/a.html
#传送到后端服务器的URI是/remote/a.html
location /name/ {
proxy_pass 172.16.60.20/remote/;
}
========================================================
#传送到后端服务器的URI是/name/a.html
location /name/ {
proxy_pass 172.16.60.20;
}
========================================================
#注意与上⾯⽤法的区别,这⾥地址末尾带有斜线,实际上被认为定义了URI,该“/”会替换“/name/",传送到后端服务器的URI是/a.html。
location /name/ {
proxy_pass 172.16.60.20/;
}
如果使⽤正则表达式定义路径,则proxy_pass指令不应使⽤URI。例如:
location ~ ^/mmb {
proxy_pass www.kevin;
}
在需要代理的路径中,使⽤rewrite指令改变了URI,那么nginx将使⽤重写后的URI处理请求,⽽忽略proxy_pass指令设置的URI。如下⾯所⽰的例⼦中,传送给上游服务器的URI为/index.php?page=<ma
tch>。
location / {
rewrite /(.*)$ /index.php?page=$1 break;
proxy_pass localhost:8080;
}
1.2  proxy模块的其它指令
① proxy_connect_timeout time;
与后端服务器建⽴连接的超时时间。⼀般不可能⼤于75秒;
② proxy_cookie_domain off;
取消当前配置级别的所有proxy_cookie_domain指令;
如果配置,则格式为:proxy_cookie_domain domain replacement(替代),即设置"Set-Cookie"响应头中的domain属性的替换⽂本,其值可以为⼀个字符串、正则表达式的模式或⼀个引⽤的变量;例如:
proxy_cookie_domain ;
浏览器对 Cookie 有很多限制,如果 Cookie 的 Domain 部分与当前页⾯的 Domain 不匹配就⽆法写⼊。所以如果请求 A 域名,服务器proxy_pass 到 B 域名,然后 B 服务器输出 Domian=B 的 Cookie,前端的页⾯依然停留在 A 域名上,于是浏览器就⽆法将 Cookie 写⼊。
不仅是域名,浏览器对 Path 也有限制。我们经常会 proxy_pass 到⽬标服务器的某个 Path 下,不把这个 Path 暴露给浏览器。这时候如果⽬标服务器的 Cookie 写死了 Path 也会出现 Cookie ⽆法写⼊的问题。
③ proxy_cookie_path off;
格式"proxy_cookie_path path replacement;",即设置"Set-Cookie"响应头中的path属性的替换⽂本,其值可以为⼀个字符串、正则表达式的模式或⼀个引⽤的变量;例如:
proxy_cookie_path /two/ /;
若“Set-Cookie”响应头含有属性“path=/two/some/uri/”,那么该指令会将这个属性改写为“path=/some/uri/”。
④ proxy_hide_header field;
nginx默认不会将"Date"、"Server"、"X-Pad",和""响应头发送给客户端。该指令则可以设置额外隐藏的响应头,这些响应头也不会发送给客户端。相反的,如果希望允许传递某些响应头给客户端,可以使⽤proxy_pass_header指令。
⑤ proxy_set_header field value;
重新定义或者添加发往后端服务器的请求头。value可以包含⽂本、变量或者它们的组合。例如:
proxy_set_header X-Real-IP $remote_addr;  #给请求头中添加客户端IP
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
默认情况下,只有两个请求头会被重新定义:
proxy_set_header Host $proxy_host;
proxy_set_header Connection close;
如果某个请求头的值为空,那么这个请求头将不会传送给后端服务器:
proxy_set_header Accept-Encoding "";
⑥ proxy_pass_request_headers on|off;
是否将http⾸部发往上游服务器
⑦ proxy_pass_request_body on|off;
是否将http请求报⽂的包体部分发往上游服务器
⑧ proxy_redirect [default|off|redirect replacement];
修改上游服务器传来的响应头中的"Location"和"Refresh"字段。例如:
proxy_redirect localhost:8000/two/ frontend/one/;
replacement字符串可以省略服务器名:
proxy_redirect localhost:8000/two/ /;
此时将使⽤代理服务器的主域名和端⼝号来替换。如果端⼝是80,可以不加。
⑨ proxy_send_timeout time;
在连接断开之前两次发送⾄upstream server的写操作的最⼤间隔时长;
⑩ proxy_read_timeout time;
在连接断开之前两次从接收upstream server接收读操作的最⼤间隔时长;
1.3  proxy模块的内置变量
① $proxy_host:
后端服务器的主机名和端⼝;
② $proxy_port:
后端服务器的端⼝;
③ $proxy_add_x_forwarded_for
将$remote_addr变量值添加在客户端“X-Forwarded-For”请求头的后⾯,并以逗号分隔。如果客户端请求未携带“X-Forwarded-For”请求
头,$proxy_add_x_forwarded_for变量值将与$remote_addr变量相同
2、upstream模块
如果有多个上游服务器,我们可以把它们放到⼀个组中,并且给它们赋予不同的权重和类型,进⾏负载均衡等,这些功能是由upstream模块实现的。
2.1  配置语法:
upstream name {
server address [parameters];
...
}
⽰例:
upstream web {
server web1.kevin      weight=5;
server web2.kevin:8080;
server unix:/tmp/web3;
server backup1.kevin:8080  backup;
}
server {
location / {
proxy_pass web;
}
}
2.2  uptream使⽤注意:
①只能⽤于http上下⽂
②各server只能直接使⽤IP或主机名,不要加协议
2.3  默认情况下,nginx按加权轮转的⽅式将请求代理到各上游服务器。与上游服务器通信的时候,如果出现错误,请求会被传给下⼀个服务器,直到所有可⽤的服务器都被尝试过。如果所有服务器都返回失败,客户端将会得到最后通信的那个服务器的(失败)响应结果。2.4  地址可以是域名或者IP地址,端⼝是可选的(默认是80),或者是指定“unix:”前缀的UNIX域套接字的路径。如果⼀个域名解析到多个IP,本质上是定义了多个server。
2.5  server后可定义的参数:
① weight=number
设定服务器的权重,默认是1。
② max_fails=number
设定Nginx与服务器通信的尝试失败的次数。在fail_timeout参数定义的时间段内,如果失败的次数达到此值,Nginx就认为服务器不可⽤。在下⼀个fail_timeout时间段,服务器不会再被尝试。失败的尝试次数默认是1。设为0就会停⽌统计尝试次数,认为服务器是⼀直可⽤的。
③ fail_timeout=time
默认是10秒,设定统计失败尝试次数的时间段。在这段时间中,服务器失败次数达到指定的尝试次数,服务器就被认为不可⽤。服务器被认为不可⽤的时间段。
④ backup
标记为备⽤服务器。当主服务器不可⽤以后,请求会被传给这些服务器。
⑤ down
标记服务器永久不可⽤,可以跟ip_hash指令⼀起使⽤
2.6  upstream模块的其它负载均衡算法(⽤于upstream上下⽂):
① ip_hash;
作⽤同lvs中的sh调度算法,将来⾃于同⼀个客户端的请求始终调度⾄同⼀台后端服务器(除了当服务器不可⽤的时候)
② least_conn;
将请求发送到活动连接数最少的那台服务器。如果这样的服务器有多台,就尝试按加权轮循来调度
③ sticky cookie name [expires=time] [domain=domain] [httponly] [secure] [path=path];
session绑定,将来⾃于同⼀个客户端的请求始终调度⾄同⼀台后端服务器,从⽽实现客户端与后端服务器的session保持。
ip_hash指令⽆法实现对内⽹NAT⽤户的均衡,⽽sticky指令可以做到;
◆    sticky⼯作原理
1. 浏览器⾸次发起请求,请求头未带cookie。nginx接收请求,发现请求头没有cookie,则以轮询⽅式将请求代理给后端服务器。
2. 后端服务器处理完请求,将响应头和内容返回给nginx。
3. nginx⽣成cookie,返回给客户端浏览器。cookie的值与后端服务器对应,可能是明⽂,也可能是md5、sha1等Hash值。
4. 浏览器接收请求,并创建cookie。
5. 浏览器再次发送请求时,带上cookie。
6. nginx接收到cookie,直接转给对应的后端服务器
参数说明:
domain:cookie作⽤的域名
path:cookie作⽤的路径
expires:cookie的过期时长
⽰例如下:
upstream web {
server web1.kevin;
server web2.kevin;
sticky cookie srv_id expires=1h domain=.kevin path=/;
}
2.7  health_check [interval=time] [fails=number] [passes=number] [uri=uri] [match=name];
对上游服务器组进⾏健康状态检测,⽤于location中;
参数说明:
interval=time      #检测的间隔时长,默认为5秒
fails=number      #连续检测失败多少次即认为上游服务器不可⽤,默认为1次
passes=number  #上游服务器从不可⽤到可⽤状态时需要连续检测的次数,默认为1次
uri=uri                #定义⽤于健康检测的URI,默认为“/”,即默认检测⽬标服务器的主页
match=name      #指定⼀段配置来当作检测条件,默认当响应码为2XX或3XX时认为上游服务器是可⽤的
⽰例如下:
http {
server {
...
location / {
proxy_pass backend;
health_check uri=/.health.html match=welcome;
}
}
match welcome {      #match配置段要位于http上下⽂
status 200;
header Content-Type = text/html;
body ~ "Welcome to nginx!";
}
}
3、fastcgi模块nginx部署前端项目
nginx能够通过fastcgi模块实现将客户端的动态⽂件请求代理⾄fastcgi server,此时nginx与fastcgi server的通信是通过fastcgi协议进⾏的
3.1  fastcgi模块的常⽤指令
①fastcgi_pass address;
指定fastcgi server的地址和端⼝,也⽀持使⽤unix sock;例如:
fastcgi_pass localhost:9000;
fastcgi_pass 192.168.30.20:9000;
fastcgi_pass unix:/tmp/fastcgi.socket;
②fastcgi_bind address | off;
指定联系fpm服务器时使⽤的地址;
③fastcgi_param parameter value [if_not_empty];
定义传递给fastcgi server的参数;参数值可以是⽂本、变量或它们的组合,if_not_empty表⽰不为空时才传递。例如:
fastcgi_param SCRIPT_FILENAME /web/scripts$fastcgi_script_name;
④fastcgi_index name;
默认主页名;就是当URI中的⽂件名缺省时,使⽤此⽂件名
⑤fastcgi_connect_timeout time;
连接fastcgi服务器的超时时长;
⑥fastcgi_send_timeout time;
向fastcgi服务传输数据的超时时长;
3.2  通常建议nginx和fastcgi server(如php-fpm)部署在同⼀台服务器上,因为⼆者如果通过⽹络通信的话会造成额外的性能开销。
3.3  配置⽰例
location ~ \.php$ {
fastcgi_pass 127.0.0.1:9001;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME /web/scripts$fastcgi_script_name;
include fastcgi_params;
}
说明:
①参数SCRIPT_FILENAME保存是的脚本⽂件的绝对路径;例如,若请求的URI是/test/status.php,那么向fastcgi server传递的脚本⽂件路径就是/web/scripts/test/status.php
②nginx有两个⽂件fastcgi_params和f,它们存放着nginx向fastcgi server传递的参数,⼆者唯⼀的区别是后者⽐前者多了⼀⾏SCRIPT_FILENAME 的定义:
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
3.4  通过nginx查看后端php-fpm的运⾏状态
# vim /etc/php-fpm.f(若php-fpm是编译安装,则为主配置⽂件)
pm.status_path = fpm_status
ping.path = fpm_ping
# vim /etc/f
location ~* /(fpm_status|fpm_ping) {
root          /www/a;
fastcgi_pass  127.0.0.1:9000;
fastcgi_param  SCRIPT_FILENAME  $fastcgi_script_name;
include      fastcgi_params;
}
⼆、nginx的缓存功能
nginx做为反向代理时,能够将来⾃上游服务器的响应缓存⾄本地,并在后续的客户端请求同样内容时直接从本地构造响应报⽂。nginx使⽤磁盘做缓存;
缓存将遵从上游服务器的响应报⽂⾸部中关于缓存的设定,如 "Expires"、"Cache-Control: no-cache"、 "Cache-Control: max-age=XXX"、"private"和"no-store" 等,但nginx在缓存时不会考虑响应报⽂的"Vary"⾸部。为了确保私有信息不被缓存,所有关于⽤户的私有信息可以在上游服务器上通过"no-cache" or "max-age=0"来实现,也可在nginx设定proxy_cache_key必须包含⽤户特有数据如$cookie_xxx的⽅式实现,但最后这种⽅式在公共缓存上使⽤可能会有风险。因此,在响应报⽂中含有以下⾸部或指定标志的报⽂将不会被缓存。
Set-Cookie
Cache-Control containing "no-cache", "no-store", "private", or a "max-age" with a non-numeric or 0 value
Expires with a time in the past
X-Accel-Expires: 0
与缓存有关的指令:
① proxy_cache zone | off;
定义⼀个⽤于缓存的共享内存区域,其可被多个地⽅调⽤;
② proxy_cache_key string;
设定在存储及检索缓存时⽤于“键”的字符串,可以使⽤变量为$uri其值,但使⽤不当时有可能会为同⼀个内容缓存多次;另外,将⽤户私有信息⽤于键可以避免将⽤户的私有信息返回给其它⽤户;
例如:proxy_cache_key "$host$request_uri;
③ proxy_cache_lock on | off;
启⽤此项,可在缓存未命令中阻⽌多个相同的请求同时发往upstream,其⽣效范围为worker级别;
④ proxy_cache_lock_timeout time;
proxy_cache_lock功能的锁定时长;
⑤ proxy_cache_min_uses number;
某响应报⽂被缓存之前⾄少应该被请求的次数;
⑥ proxy_cache_path path [levels=levels] keys_zone=name:size [inactive=time] [max_size=size] [loader_files=number] [loader_sleep=time] [loader_threshold=time] ;
定义⼀个⽤记保存缓存响应报⽂的⽬录,及⼀个保存缓存对象的键及响应元数据的共享内存区域(keys_zone=name:size),其可选参数有:levels:每级⼦⽬录名称的长度,有效值为1或2,每级之间使⽤冒号分隔,最多为3级;
inactive:⾮活动缓存项从缓存中剔除之前的最⼤缓存时长;
max_size:缓存空间⼤⼩的上限,当需要缓存的对象超出此空间限定时,缓存管理器将基于LRU算法对其进⾏清理;
loader_files:缓存加载器的每次⼯作过程最多为多少个⽂件加载元数据;
loader_sleep:缓存加载器的每次迭代⼯作之后的睡眠时长;
loader_threashold:缓存加载器的最⼤睡眠时长;
⽰例:
proxy_cache_path /data/nginx/cache/one levels=1 keys_zone=one:10m;
proxy_cache_path /data/nginx/cache/two levels=2:2 keys_zone=two:100m;
⑦ proxy_cache_use_stale error | timeout | invalid_header | updating | http_500 | http_502 | http_503 |http_504 | http_403 | http_404 | off ...;在⽆法联系到upstream服务器时的哪种情形下(如error、timeout或http_500等)让nginx使⽤本地缓存的过期的缓存对象直接响应客户端请求;
⑧ proxy_cache_valid [code ...] time;
⽤于为不同的响应设定不同时长的有效缓存时长
例如:
proxy_cache_valid  200 302  10m;
⑨ proxy_cache_methods GET | HEAD | POST ...;
为哪些请求⽅法启⽤缓存功能;
⑩ proxy_cache_bypass string;
设定在哪种情形下,nginx将不从缓存中取数据。
proxy_cache_bypass $cookie_nocache $arg_nocache $arg_comment;
proxy_cache_bypass $http_pragma $http_authorization;
nginx也可将后端fastcgi server的响应结果缓存:
fastcgi_cache
fastcgi_cache_path
fastcgi_cache_valid

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。