天天看点

第六章 Nginx服务器的Rewrite功能

概述:Rewrite地址修改,重定向问题

本章涉及内容:

  • 后端服务器组的配置指令
  • Rewrite功能的配置指令
  • Rewrite功能的多种应用

6.1、Nginx后端服务器组的配置的5个指令

Nginx服务器支持设置一组服务器作为后端服务器(设置服务器)

它们是由标准HTTP模块ngx_http_upstream_module进行解析

1、upstream指令

该指令时设置后端服务器组的主要指令

upstream name { ... }

name 是给后端服务器组起的组名

花括号中列出后端服务器组中包含的服务器。

默认值采用轮叫调度(Round-Robin RR)策略顺序选择  (轮询直到响应正常)

2、server指令

可以设置权重和其他参数

该指令用于设置组内的服务器。

server address [parameters]

address : 服务器的地址 可以是包含端口号的IP地址(IP:Port)、域名或者以“unix:”为前缀用于进程间通信的Unix Domain Socket

parameters. 这里有很多属性

weight=number  为组内服务器设置权重,权重值高的服务器被优先用于处理请求。加权轮叫策略。组内所有服务器的权重默认设置为1

max_fails=number 设置一个请求失败的次数 默认设置为1。如果设置为0,则不使用上面的办法检查服务器是否有效。超过次数,服务器认为无效。

HTTP 404 状态不被认为是请求失败

fail_timeout=time  默认设置为10s 设置max_fails指令尝试请求某台组内服务器的时间

backup  将某台组内服务器标记为备用服务器,只有当正常服务器出于无效状态或繁忙状态时,该服务器才被用来处理客户端请求。

down、将某台组内服务器记为永久的无效状态,通常与ip_hash指令配合使用。

upstream backend
{

  server backend1.example.com weight=5;
  server127.0.0.1:8080 max_fails=3 fail_timeout=30s;
  server unix:/tmp/backend3;
}
           

设置一个名为backend的服务器组,组内包含三台服务器,分别是基于域名的backend1.example.com、基于IP地址的127.0.0.1:8080和用于进程间通信的Unix Domain Socket。

backend1.example.com的权重设置为5,为组内最大,优先接收和处理请求;对本地服务器127.0.0.1:8080的状态检查设置是,如果在30s内连续产生3次请求失败,则该服务器在之后的30s内被认为是无效(down)状态

3、ip_hash指令

实现会话保持功能,将某个客户端的多次请求定向到组内同一台服务器上。保证客户端与服务器之间建立稳定的会话。

ip_hash;  (某个服务器down,才会选择下一个服务器) ip_hash指令不能与server指令中的weight变量一起使用。ip_hash技术主要根据客户端IP地址分配服务器。

upstream backend
{
  ip_hash;
  server myback1.proxy.com;
  server myback2.proxy.com;

}
           

4、keepalive命令

该指令用于控制网络连接保持功能。

keepalive connections;  

connections 为Nginx服务器的每一个工作进程允许该服务器组保持的空闲网络连接数的上限值。如果超过该值,工作进程将采用最近最少使用的策略关闭网络连接。

5、least_conn指令

该指令用于配置Nginx服务器使用负载均衡策略为网络连接分配服务器组内的服务器。

6.2、Rewrite功能的配置

URL的重写。Rewrite功能依赖于PCRE(Perl Compatible Regular Expressions, Perl 兼容的正则表达式)

6.2.1、“地址重写”与“地址转发”

地址重写:为了实现地址标准化 google.cn 、google 、在服务器中被改变为www.google.com

转发: 指将一个域名指到另一个已有站点的过程。

地址重写和地址转发区别

  • 地址转发后客户端浏览器地址中的地址显示是不改变的,而地址重写后客户端浏览地址栏中的地址改变为服务器选择确定的地址。
  • 在一次地址转发整个过程中,只产生一次网络请求。而一次地址重写一般会产生两次请求。
  • 地址转发一般发生在同一站点项目内;而地址重写没有该限制。
  • 地址转发到的页面可以不用全路径名表示,而地址重写到的页面必须使用完整的路径名表示。
  • 地址转发过程中,可以将客户端请求的request范围内属性传递给新的页面,但地址重写不可以
  • 地址转发的速度较地址重定向快

6.2.2、Rewrite规则

Rewrite规则是学习和使用Nginx服务器Rewrite功能的基础,可以借助PCRE实现URI的重写,并且它还支持Nginx预设变量。Rewrite规则的核心就是PCRE。

6.2.3 If指令

可以在server块或location块中配置该指令

if(condition){...}

condition 判断条件(true/false)

变量名:如果变量的值为空字符串或者以“0”开头的任意字符串,if指令认为条件为false,其他情况认为条件为true

if($slow) {

    ... #Nginx配置

}

使用“=”(等于)和“!=”(不等于)比较变量和字符串是否相等,相等时if指令认为条件为true,反之为false。

if($request_method=POST) {

     return 405;

}

"~"、“~*”、“!~” 或“!~”连接,"~"表示匹配过程中对大小写敏感,"~*"表示匹配过程中对大小写不敏感

if(-f $request_filename){
     ...   #判断请求的文件是否存在
}
           
if(!-f $request_filename){
    ...           #判断请求的文件是否不存在
}
           

6.2.4、break指令

类似java,跳过

location / {
   if($slow){
     set $id $1             #处于break指令之前,配置有效
     break;
     limit_rate 10k;      #处于break指令之后,配置无效
  }
  ...    #其他Nginx配置,处于break指令所在作用域的上一层作用域,配置有效
}
           

1、return指令

return [text]

return code URL;

return URL;

code:为返回客户端的HTTP状态代码。

text  : 为返回给客户端的响应体内容,支持变量的使用。

URL  为返回给客户端URL地址

6.2.5 rewrite指令

该指令通过正则表达式的使用来改变URI,可以同时存在一个或者多个指令,按照顺序依次对URL进行匹配和处理

语法:rewrite regex replacement [flag]

regex,用于匹配URI的正则表达式。使用括号“()”标记要截取的内容

replacement. 匹配成功后用于替换URI中被截断内容的字符串。默认情况下,如果该字符串是由“http://”或者“https://”开头的,则不会继续向下对URI进行其他处理,而直接将重写后的URI返回给客户端。

flag 用来设置rewrite对URI的处理行为,可以为以下标志中一个:

last : 终止继续在本location块中处理接收到的URI,并将此处重写的URI作为一个新的URI,使用各location块进行处理。该标志将重写后的URI重新在server块中执行,为重写后的URI提供了转入到其他location块的机会。

break: 此处重写的URI作为一个新的URI,在本块中继续进行处理。该标志将重写后的地址在当前的location块中执行。不会将新的URI转向到其他location块。

redirect 将重写后的URI返回给客户端,状态代码为302,指明是临时重定向URI,主要用在replacement变量不是以“http://” 或者"https://"开头的情况下

permanent ,将重写后的URI返回给客户端,状态代码为301,指明是永久重定向URI。

6.2.6、rewrite_log指令

该指令配置是否开启URL重写日志的输出功能

Rewrite_log on | off   

默认值为off,如果配置为开启(on) URL重写的相关日志将以notice级别输出到error_log指令配置的日志文件中。

6.2.7、set指令

指令用于设置一个新的变量

set variable value

variable 为变量的名称。注意要用$作为变量的第一个字符,且变量不能与Nginx服务器预设的全局变量同名

value 为变量的值,可以是字符串,其他变量或变量的组合等。

6.2.8、uninitialized_variable_warn指令

该指令用于配置使用为初始化的变量时,是否记录警告日志

uninitialized_variable_warn on | off

6.2.9、Rewrite常用全局变量

$args  : 变量中存放了请求URL中的请求指令。比如http://www.myweb.name/server/source? arg1=value1&arg2=value2中的“arg1=value1&arg2=value2”

$remote_addr 变量中存放了客户端的地址

$remote_port 变量中存放了客户端与服务器建立的连接的端口号

6.3、Rewrite的使用

6.3.1、域名跳转

#例子1
...
server
{
  listen 80;
  server_name jump.myweb.name;
  rewrite ^/ http://www.myweb.info/;   #域名跳转
  ...

}
...
#例子2

... 
server
{
	listen 80;
	server_name jump.myweb.name jump.myweb.info;
	if($host ~ myweb\.info)      #注意正在表达式中对点号要用于\进行转义
	{
		rewrite ^(.*) http://jump.myweb.name$1 permanent;  #多域名跳转
	}
	...
}
...
#例子3
...
server
{
	listen 80;
	server_name jump1.myweb.name jump2.myweb.name;
	if($http_host ~* ^(.*)\.myweb\.name$)
	{
		rewrite ^(.*) http://jump.myweb.name$1;    #三级域名跳转
		break;
	}
	....

}
...
           

在例子1中,客户端访问http://jump.myweb.name时,URL将被Nginx服务器重写为http://jump.myweb.info,客户端得到的数据其实是由http://jump.myweb.info响应的。例子2中,客户端访问http://jump.myweb.info/reqsource时,URL将被Nginx服务器重写为http://jump.myweb.name/reqsource.客户端得到的数据实际上是由http://jump.myweb.name响应的,在例子3中,客户端访问http://jump1.myweb.name/reqsource或者 http://jump2.myweb.name/reqsource, URL 都将被Nginx服务器重写为http://jump.myweb.name/reqsource.实现了三级域名跳转。

6.3.2、域名镜像

镜像网站是指将一个完全相同的网站分别放置到几个服务器上,并分别使用独立的URL,其中一个服务器上的网站叫主站,其他的为镜像网站。

...
server
{
  ...
  listen 80;
  server_name mirror1.myweb.name;
  rewrite ^(.*) http://jump1.myweb.name$1 last;
}
server
{
   ...
   listen 81;
   server_name mirror2.myweb.name;
   rewrite ^(.*) http://jump2.myweb.name$1 last;
}
.....
           

6.3.3、独立域名

server {
   ... 
   listen 80;
   server_name bbs.myweb.name;
   rewrite ^(.*) http://www.myweb.name/bbs$1 last;
   break;
}

server 
{
  ...
  server_name home.myweb.name;
  rewrite ^(.*) http://www.myweb.name/home$1 last;
  break;
}
...
           

6.3.4、目录自动添加"/"

达到输入www.myweb.name,进入index.html    直接访问, /index.html

如果是二级目录下 例如 在访问http://www.myweb.name/bbs/index.html .如果将URL省略"http://www.myweb.name/bbs/"是可以访问,但是少了最后的"/"是不能访问的。

如果自动加上“/”

server {
	...
	listen 81;
	server_name www.myweb.name;
	location ^~ /bbs
	{
		...
		if(-d $request_filename){
			rewrite ^/(.*)([^/])$ http://$host/$1$2/ permanent;
		}
	}
}
           

6.3.5 目录合并

多级目录很难被访问到(不利于检索)

例如 【root】/server/12/34/56/78/9.htm

server
{
	...
	listen 80;
	server_name www.myweb.name;
	locaton ^~ /server
	{
		...
		rewrite ^/server-([0-9]+)-([0-9]+)-([0-9]+)-([0-9]+)-([0-9]+)\.htm $
		/server/$1/$2/$3/$4/$5.html last;
	}
}
...
           

客户端输入"http://www.myweb.name/server-12-34-56-78-9.htm" 即可访问到9.htm这个资源文件

6.3.6、防盗链

盗链 给原网站所在服务器造成额外负担的非法行为。 例如查询图片来自其他服务器的

语法:

valid_referers none | blocked | server_names | String ...;

none 检测Referer头域不存在的情况

blocked  检测Referer头域的值被防火墙或代理服务器删除或伪装的情况。这种情况下,该头域的值不是以“https://” 或“”http://“”开头

server_names 设置一个或多个URL,检测Referer头域的值是否是这些URL中某个。

实现盗链有两种方式,一种是根据请求资源的资源类型。一种是根据请求的目录

根据请求资源的资源类型

server
{
	...
	listen 80;
	server_name www.myweb.name;
	location ~* ^.+\.(gif|jpg|png|swf|flv|rar|zip)$
	{
		...
		valid_referers none blocked server_name *. myweb.name;
		if($invalid_referer){
			rewrite ^/ http://www.myweb.com/images/forbidden.png;
		}
	}
}
...
           

根据请求的目录

server
{
	...
	listen 80;
	server_name www.myweb.name;
	location /file/
	{
		...
		root /server/file/;
		valid_referers none blocked server_name *. myweb.name;
		if($invalid_referer){
			rewrite ^/ http://www.myweb.com/images/forbidden.png;
		}
	}
}
...
           

继续阅读