反向代理:工作在服务器前端,如nginx
正向代理:工作在客户端前端,如vpn
nginx反向代理
nginx可以作为七层协议上的负载均衡主机,即在应用层上的负载均衡主机,七层负载是面向服务的,报文已经被转发至用户空间,这是不同于四层负载的地方(四层负载在内核(TCP协议栈)就被转发给后台RS)。
proxy模块
Nginx通过proxy模块实现反向代理功能。在作为web反向代理服务器时,nginx负责接收客户请求,并能够根据URI、客户端参数或其它的处理逻辑将用户请求调度至上游服务器上(upstream server)。nginx在实现反向代理功能时的最重要指令为proxy_pass,它能够将location定义的某URI代理至指定的上游服务器(组)上。如下面的示例中,location的/uri将被替换为上游服务器上的/newuri。
location /uri { proxy_pass http://:/newuri; }
不过,这种处理机制中有两个例外。
一个是如果location的URI是通过模式匹配定义的,其URI将直接被传递至上游服务器,而不能为其指定转换的另一个URI。例如下面示例中的/forum将被代理为:/forum。
location ~ ^/bbs { proxy_pass http://; }
如果在loation中使用的URL重定向,那么nginx将使用重定向后的URI处理请求,而不再考虑上游服务器上定义的URI。如下面所示的例子中,传送给上游服务器的URI为/?page=<match>,而不是/index。
location / { rewrite /(.*)$ /index.php?page=$1 break; proxy_pass http://localhost:8080/index; }
proxy模块的指令
proxy模块的可用配置指令非常多,它们分别用于定义proxy模块工作时的诸多属性,如连接超时时长、代理时使用http协议版本等。下面对常用的指令做一个简单说明。
proxy_connect_timeout:nginx将一个请求发送至upstream server之前等待的最大时长;proxy_cookie_domain:将upstream server通过Set-Cookie首部设定的domain属性修改为指定的值,其值可以为一个字符串、正则表达式的模式或一个引用的变量;proxy_cookie_path: 将upstream server通过Set-Cookie首部设定的path属性修改为指定的值,其值可以为一个字符串、正则表达式的模式或一个引用的变量;proxy_hide_header:设定发送给客户端的报文中需要隐藏的首部;proxy_pass:指定将请求代理至upstream server的URL路径;proxy_set_header:将发送至upsream server的报文的某首部进行重写;proxy_redirect:重写location并刷新从upstream server收到的报文的首部;proxy_send_timeout:在连接断开之前两次发送至upstream server的写操作的最大间隔时长;proxy_read_timeout:在连接断开之前两次从接收upstream server接收读操作的最大间隔时长;
设置示例:
proxy_redirect off; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; client_max_body_size 10m; client_body_buffer_size 128k; proxy_connect_timeout 30; proxy_send_timeout 15; proxy_read_timeout 15;
proxy_pass指令
在server模块内部,设置反向代理:
location ^~ /proxy/ { proxy_pass http://172.25.254.18:80; }//这就是特殊情况一,不能为其指定转换的另一个URI location /forum { proxy_pass http://172.25.254.18:80/bbs; }//这是将访问本地ip/forum转发给172.25.254.18,并访问改服务器发布目录下的/bbs目录
upstream模块
与proxy模块结合使用的模块中,最常用的就是upstream模块。upstream模块可定义一个新的上下文,它包含了一组upstream服务器,这些服务器可能被赋予了不同的权重、不同的类型甚至可以基于维护等原因被标记为down。
upstream模块的指令
upstream模块常用的指令有:
ip_hash:基于客户端IP地址完成请求的分发,它可以保证来自于同一个客户端的请求始终被转发至同一个upstream服务器;keepalive:每个worker进程为发送到upstream服务器的连接所缓存的个数;least_conn:最少连接调度算法;server:定义一个upstream服务器的地址,还可包括一系列可选参数,如:
weight:权重; max_fails:最大失败连接次数,失败连接的超时时长由fail_timeout指定; fail_timeout:等待请求的目标服务器发送响应的时长; backup:用于fallback的目的,所有服务均故障时才启动此服务器; down:手动标记其不再处理任何请求;
如:
upstream backend { server .com weight=5; server :8080 max_fails=3 fail_timeout=30s; }
upstream模块的负载均衡算法主要有三种,轮调(round-robin)、ip哈希(ip_hash)和最少连接(least_conn)三种。
upstream定义一个后端服务器组,定义在server模块之外。
upstream backend { server IP:PORT weight=n; server IP:PORT weight=n' ... server unix:/tmp/backend3; } server { location / { proxy_pass http:backend; } }
实例配置:
172.25.254.11和172.25.254.18均提供web服务,172.25.254.17为nginx反向代理服务器IP地址
编辑172.25.254.17nginx反向代理服务器主配置文件,
在server外部设置upstream模块:
upstream fsx { server 172.25.254.11:80 weight=3 max_fails=2 fail_timeout=2; server 172.25.254.18:80 weight=1; server 127.0.0.1 backup; }
在server内部设置发向代理,并指向upstream模块:
location /fsx { proxy_pass http://fsx/; index index.html; }
访问代理服务器:
[root@nginx nginx]# for i in {1..10};do curl 172.25.254.17/fsx;done <h1> RS 172.25.254.11 </h1> <h1> RS 172.25.254.11 </h1> <h1> RS 172.25.254.18 </h1> <h1> RS 172.25.254.11 </h1> <h1> RS 172.25.254.11 </h1> <h1> RS 172.25.254.11 </h1> <h1> RS 172.25.254.18 </h1> <h1> RS 172.25.254.11 </h1> <h1> RS 172.25.254.11 </h1> <h1> RS 172.25.254.11 </h1>
nginx缓存
nginx做为反向代理时,能够将来自upstream的响应缓存至本地,并在后续的客户端请求同样内容时直接从本地构造响应报文。
nginx缓存大致上由两部分组成:
cache:共享内存(存储键和缓存对象元数据),查找在内存上
data:数据在磁盘空间
proxy_cache_path:定义缓存空间(不能定义在server段中,在http段中),属于proxy模块
proxy_cache_path:定义一个用记保存缓存响应报文的目录,及一个保存缓存对象的键及响应元数据的共享内存区域(keys_zone=name:size),其可选参数有:
levels:每级子目录名称的长度,有效值为1或2,每级之间使用冒号分隔,最多为3级;1:2表示两个级别目录,一级子目录由一个字符组成,二级子目录由二个字符组成 keys_zone:给共享内存命名,存储键的区域,可以定义多个区域,每个区域要有个名称引用。 inactive:非活动缓存项从缓存中剔除之前的最大缓存时长; max_size:缓存空间大小的上限,当需要缓存的对象超出此空间限定时,缓存管理器将基于LRU算法对其进行清理; loader_files:缓存加载器(cache_loader)的每次工作过程最多为多少个文件加载元数据; 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_path /data/nginx/cache/three levels=1:1:2 keys_zone=three:1000m;
在proxy反向代理服务器上实现cache:
-
编辑文件,添加cache模块
proxy_cache_path /nginx/cache/first levels=1:2 keys_zone=first:20m max_size=1g; upstream fsx { #ip_hash; server 172.25.254.11:80 weight=3 max_fails=2 fail_timeout=2; server 172.25.254.18:80 weight=1; server 127.0.0.1 backup; }
在指定的location模块中启用chache
location /fsx { proxy_pass http://fsx/; proxy_cache first; proxy_cache_valid 200 10m; } add_header X-Via $server_addr; add_header X_cache_hit $upstream_cache_status;
-
创建指定的目录
[root@nginx nginx]# mkdir -p /nginx/cache/first/
-
重启服务(reload即可)
[root@nginx nginx]# nginx -t nginx: the configuration file /etc/nginx/ syntax is ok nginx: configuration file /etc/nginx/ test is successful [root@nginx nginx]# nginx -s reload
在浏览器访问服务器URL:IP/fsx,因为使用了缓存,所以不会负载均衡
-
查看缓存文件
[root@nginx 3e]# pwd /nginx/cache/first/4/3e [root@nginx 3e]# ls b902746d2bc6b97f03809b8f36d263e4 [root@nginx 3e]# file b902746d2bc6b97f03809b8f36d263e4 b902746d2bc6b97f03809b8f36d263e4: Hitachi SH big-endian COFF object, not stripped
-
浏览器上按F12可以查看到response header信息
Accept-Ranges: bytes Connection: keep-alive Content-Length: 201 Content-Type: text/html; charset=UTF-8 Date: Sat, 16 Jun 2018 16:04:47 GMT Etag: "c9-56de7d12abff8" Last-Modified: Tue, 05 Jun 2018 16:48:17 GMT Server: nginx/fsx-1.0 server X-Via: 172.25.254.17 //服务器地址 X_cache_hit: HIT //命中
也可以这样编辑:
add_header X-Via $server_addr; add_header X_cache_hit $upstream_cache_status; 更改为: add_header X_cache "$upstream_cache_status from $server_addr"; 效果相同
proxy_cache其他的一些指令:
proxy_cache zone|off:定义一个用于缓存的共享内存区域,其可被多个地方调用;缓存将遵从up stream服务器的响应报文首部中关于缓存的设定,如 "Expires"、"Cache-Control: no-cache"、 "Cache-Control: max-age=XXX"、"private"和"no-store" 等,但nginx在缓存时不会考虑响应报文的"Vary"首部。为了确保私有信息不被缓存,所有关于用户的私有信息可以upstream上通过"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: 0proxy_cache_key:设定在存储及检索缓存时用于“键”的字符串,可以使用变量为其值,但使用不当时有可能会为同一个内容缓存多次;另外,将用户私有信息用于键可以避免将用户的私有信息返回给其它用户; proxy_cache_lock:启用此项,可在缓存未命令中阻止多个相同的请求同时发往upstream,其生效范围为worker级别;proxy_cache_lock_timeout:proxy_cache_lock功能的锁定时长;proxy_cache_min_uses:某响应报文被缓存之前至少应该被请求的次数;
proxy_cache_use_stale:在无法联系到upstream服务器时的哪种情形下(如error、timeout或http_500等)让nginx使用本地缓存的过期的缓存对象直接响应客户端请求;其格式为:
proxy_cache_use_stale error | timeout | invalid_header | updating | http_500 | http_502 | http_503 | http_504 | http_404 | off
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_authorization;
使用示例:
http { proxy_cache_path /data/nginx/cache levels=1:2 keys_zone=STATIC:10m inactive=24h max_size=1g; server { location / { proxy_pass http://; proxy_set_header Host $host; proxy_cache STATIC; proxy_cache_valid 200 1d; proxy_cache_valid 301 302 10m; proxy_cache_vaild any 1m; proxy_cache_use_stale error timeout invalid_header updating http_500 http_502 http_503 http_504; } } }
另外常用的三种缓存:
open_log_cache:日志缓存
open_file_cache:将打开的文件直接缓存到nginx内存空间
fastcgi_cache:将php处理的结果缓存到nginx内存空间
nginx的limit限制也基于共享内存实现。
nginx压缩功能
nginx将响应报文发送至客户端之前可以启用压缩功能,这能够有效地节约带宽,并提高响应至客户端的速度。通常编译nginx默认会附带gzip压缩的功能,因此,可以直接启用。
gzip_proxied指令可以定义对客户端请求哪类对象启用压缩功能,如“expired”表示对由于使用了expire首部定义而无法缓存的对象启用压缩功能,其它可接受的值还有“no-cache”、“no-store”、“private”、“no_last_modified”、“no_etag”和“auth”等,而“off”则表示关闭压缩功能。
如:
http { gzip on; gzip_http_version 1.0; gzip_comp_level 2; gzip_types text/plain text/css application/x-javascript text/xml application/xml application/xml+rss text/javascript application/javascript application/json; gzip_disable msie6; }
nginxURL重定向
rewrite是实现URL重写的关键指令,根据regex(正则表达式)部分内容,重定向到replacement,结尾是flag标记。
Nginx的rewrite功能在企业里应用非常广泛:
可以调整用户浏览的URL,看起来更规范,合乎开发及产品人员的需求。
为了让搜索引擎搜录网站内容及用户体验更好,企业会将动态URL地址伪装成静态地址提供服务。
网址换新域名后,让旧的访问跳转到新的域名上。例如,访问京东的会跳转到
根据特殊变量、目录、客户端的信息进行URL调整等
rewrite语法格式及参数:
rewrite <regex> <replacement> [flag]; rewrite:关键字,不能改变,可以在http段定义、也可以在location模块定义 <regex>:正则 <replacement>:代替内容,将正则内容替换成<replacement>的内容 [flag]:标记,可以不定义
关于flag可以选取四个参数:
last #本条规则匹配完成后,继续向下匹配新的location URI规则
break #本条规则匹配完成即终止,不再匹配后面的任何规则
redirect #返回302临时重定向,浏览器地址会显示跳转后的URL地址
permanent #返回301永久重定向,浏览器地址栏会显示跳转后的URL地址
例如:
rewrite ^/poem/(.*)$ http://172.25.254.18/libai/$1 redirect; ^/poem/(.*)$,是一个正则表达式,匹配URL下poem目录里的所有内容 http://172.25.254.18/libai/$1,将正则匹配的内容重写到某一个主机下libai目录内 redirect:302临时重定向
常用正则表达式说明
字符 | 描述 |
---|---|
\ | 将后面接着的字符标记为一个特殊字符或一个原义字符或一个向后引用。如“\n”匹配一个换行符,而“$”则匹配“$” |
^ | 匹配输入字符串的起始位置 |
$ | 匹配输入字符串的结束位置 |
* | 匹配前面的字符零次或多次。如“ol*”能匹配“o”及“ol”、“oll” |
+ | 匹配前面的字符一次或多次。如“ol+”能匹配“ol”及“oll”、“oll”,但不能匹配“o” |
? | 匹配前面的字符零次或一次,例如“do(es)?”能匹配“do”或者“does”,"?"等效于"{0,1}" |
. | 匹配除“\n”之外的任何单个字符,若要匹配包括“\n”在内的任意字符,请使用诸如“[.\n]”之类的模式。 |
(pattern) | 匹配括号内pattern并可以在后面获取对应的匹配,常用9属性获取小括号中的匹配内容,要匹配圆括号字符需要(Content) |
具体配置:
-
编辑172.25.254.17服务器nginx配置文件,在server段添加:
location / { root html; index index.html index.htm; rewrite ^/poem/(.*)$ http://172.25.254.18/libai/$1 redirect; }
将当前服务器的URL/poem/临时重定向到172.25.254.18RS服务器的URL/libai/目录下
-
172.25.254.18nginx服务器开启,并在发布目录下有libai目录
[root@nginx_rs libai]# pwd /web/libai [root@nginx_rs libai]# cat <h1> rewrite for nginx </h1>
在浏览器*问172.25.254.17/poem会被重定向到172.25.254.18/libai/
-
在终端使用curl命令会有如下效果:
[root@nginx nginx]# curl 172.25.254.17/poem/ <html> <head><title>302 Found</title></head> <body bgcolor="white"> <center><h1>302 Found</h1></center> <hr><center>nginx/fsx-1.0 server</center> </body> </html>
表示已经被临时重定向了
nginx读写分离
在location模块内,使用if:
location /forum { proxy_pass http://172.25.254.11:80/; if ($request_method = "PUT") { proxy_pass http://172.25.254.18:80; } }
当访问nginx服务器URL/forum时,读操作11服务器完成。如果时PUT操作,只能18完成
读操作:
[root@nginx nginx]# curl 172.25.254.17:/forum <h1>范顺心</h1> <a href="/" download="fsx"> <img border="0" src="/" alt="点击下载"> </a> <a href="/html" download="博客"> <img border="0" src="/html" alt="进入博客"> </a> [root@nginx nginx]# curl 172.25.254.11 <h1>范顺心</h1> <a href="/" download="fsx"> <img border="0" src="/" alt="点击下载"> </a> <a href="/html" download="博客"> <img border="0" src="/html" alt="进入博客"> </a> [root@nginx nginx]# curl 172.25.254.18 <h1> welcome to nginx </h1>
反复刷新,读操作也只负载到172.25.254.11服务器上
写操作:
[root@nginx nginx]# curl -T 172.25.254.17:/forum % Total % Received % Xferd Average Speed Time Time Time Current Dload Upload Total Spent Left Speed 0 0 0 0 0 0 0 0 --:--:-- --:--:-- --:--:-- 0<html> <head><title>405 Not Allowed</title></head> <body bgcolor="white"> <center><h1>405 Not Allowed</h1></center> <hr><center>nginx/fsx-1.0</center> </body> </html> 100 3705 100 174 100 3531 148k 3008k --:--:-- --:--:-- --:--:-- 3448k
此时上传的文件被上传到172.25.254.18服务器上