Nginx Location Rewrite与动静分离

一、Nginx正则及location匹配
1、Nginx location规则匹配
^~ 标识符匹配后面跟一个字符串。匹配字符串后将停止对后续的正则表达式进行匹配,如location ^~ /images/,在匹配了/images/这个字符串后就停止对后续的正则匹配
= 精准匹配,如location = /,只会匹配url为/的请求-> http://www.a.com/
~ 区分大小写的匹配 -> location ~ \.jsp$
~* 不区分大小写的匹配-> location ~* \.jsp$
!~ 对区分大小写的匹配取非
!~* 对不区分大小写的匹配取非
/ 通用匹配, 如果没有其它匹配,任何请求都会被匹配到
2、正则表达式
* 重复前面的字符0次或多次
? 重复前面的字符0次或1次
+ 重复前面的字符1次或多次
. 匹配除换行符以外的任意1个字符
(a|b) 匹配a或b
^ 以…开头
$ 以…结尾
{n} 重复前面的字符n次
{n,} 重复前面的字符n次或更多次
{n,m} 重复前面的字符n到m次
*? 重复前面的字符0次或多次,但尽可能少重复
+? 重复前面的字符1次或更多次,但尽可能少重复
?? 重复前面的字符0次或1次,但尽可能少重复
{n,m}? 重复前面的字符n到m次,但尽可能少重复
{n,}? 重复前面的字符n次以上,但尽可能少重复
3、正则表达式补充:
\W 匹配任意不是字母,数字,下划线,汉字的字符
\S 匹配任意不是空白符的字符
\D 匹配任意非数字的字符
\B 匹配不是单词开头或结束的位置
[a] 匹配单个字符a
[a-z] 匹配a-z小写字母的任意一个
[^a] 匹配除了a以外的任意字符
[^abc] 匹配除了abc这几个字母以外的任意字符
4、Nginx location应用规则
location [=|~|~*|^~|!~|!~*|/] /url/{...}
默认值:no
使用字段:server
location参数根据URL的不同需求来进行配置,可以使用字符串与正则表达式匹配,
location ~* .*\.jsp$ {
proxy_pass http://tomcat_server;
}
location = / {
# 精确匹配 / ,主机名后面不能带任何字符串
[ configuration A ]
}
location / {
# 因为所有的地址都以 / 开头,所以这条规则将匹配到所有请求
# 但是正则和最长字符串会优先匹配
[ configuration B ]
}
location /documents/ {
# 匹配任何以 /documents/ 开头的地址,匹配符合以后,还要继续往下搜索
# 只有后面的正则表达式没有匹配到时,这一条才会采用这一条
[ configuration C ]
}
location ~ /documents/abc {
# 匹配任何以 /documents/abc 开头的地址,匹配符合以后,还要继续往下搜索
# 只有后面的正则表达式没有匹配到时,这一条才会采用这一条
[ configuration CC ]
}
location ^~ /images/ {
# 匹配任何以 /images/ 开头的地址,匹配符合以后,停止往下搜索正则,采用这一条。
[ configuration D ]
}
location ~* \.(gif|jpg|jpeg)$ {
# 匹配所有以gif,jpg或jpeg 结尾的请求
# 然而,所有请求 /images/ 下的图片会被config D 处理,因为 ^~ 到达不了这一条正则
[ configuration E ]
}
location /images/ {
# 字符匹配到 /images/,继续往下,会发现 ^~ 存在
[ configuration F ]
}
location /images/abc {
# 最长字符匹配到 /images/abc,继续往下,会发现 ^~ 存在
# F与G的放置顺序是没有关系的
[ configuration G ]
}
location ~ /images/abc/ {
# 只有去掉config D 才有效:先最长匹配config G 开头的地址,继续往下搜索,匹配到这一条正则,采用
[ configuration H ]
匹配顺序优先级:
(location =) > (location 完整路径) > (location ^~ 路径) > (location ~,~* 正则顺序) > (location 部分起始路径) > (/)
按照上面的location匹配,分析以下案例:
/ ->config A
精确完全匹配,即使/index.html也匹配不了
/downloads/download.html ->config B
匹配B以后,往下没有任何匹配,采用B
/images/1.gif -> config D
匹配到B,往下匹配到D,停止往下
/images/abc/def ->config D
最长匹配到G,往下匹配D,停止往下
你可以看到 任何以/images/开头的都会匹配到D并停止,FG写在这里是没有任何意义的,H是永远轮不到的,这里只是为了说明匹配顺序
/documents/document.html ->config C
匹配到C,往下没有任何匹配,采用C
/documents/1.jpg -> configuration E
匹配到C,往下正则匹配到E
/documents/abc ->config CC
最长匹配到C,往下正则顺序匹配到CC,往下到E
实际使用建议
所以实际使用中,个人觉得至少有三个匹配规则定义,如下:
#直接匹配网站根,通过域名访问网站首页比较频繁,使用这个会加速处理。这里是直接转发给后端应用服务器了,也可以是一个静态首页。
# 第一个必选规则
location = / {
proxy_pass http://tomcat:8080;
}
# 第二个必选规则是处理静态文件请求,这是nginx作为http服务器的强项
# 有两种配置模式,目录匹配或后缀匹配,任选其一或搭配使用
location ^~ /static/ {
root /usr/local/nginx/html/static/;
}
location ~* \.(gif|jpg|jpeg|png|css|js|ico)$ {
root /webroot/res/;
}
#第三个规则就是通用规则,用来转发动态请求到后端应用服务器,非静态文件请求就默认是动态请求,自己根据实际把握。
#毕竟目前的一些框架的流行,带.php,.jsp后缀的情况很少了
location / {
proxy_pass http://tomcat:8080;
}
二、Nginx Rewrite规则
Nginx Rewrite功能是使用nginx提供的全局变量或自己设置的变量,结合正则表达式和标志位实现URL重写以及重定向功能。Rewrite指令只能放在server{},location{},if{}中,并且只能对域名后边的除去传递的参数外的字符串起作用。
Nginx的Rewrite规则采用PCRE(Perl compatible Regular Expressions,Perl兼容正则表达式)的语法进行规则匹配,如果需要Nginx的Rewrite功能,在编译安装Nginx之前,必须安装PCRE库。
例如:http://www.crushlinux.com/a/we/index.php?id=1&u=admin只对URL中的/a/we/index.php等字符串起作用。
URL是Uniform Resource Location的缩写,译为“统一资源定位符”。
语法:
rewrite 正则表达式 更换目标 [标志位];
rewrite和location功能有点像,都能实现跳转。主要区别在于rewrite是在同一域名内更改获取资源的路径,而location是对路径做控制访问或反向代理,可以使用proxy_pass代理到其他机器。很多情况下rewrite也会写在location里,它们的执行顺序是:
- 执行server块的rewrite指令
- 执行location匹配
- 执行选定的location中的rewrite指令
注意:如果其中某步URI被重写,则重新循环执行1-3,直到找到真实存在的文件;循环超过10次,则返回500 Internal Server Error错误。
flag标志位
- last : 相当于Apache的[L]标记,表示完成rewrite
- break : 本条规则匹配完成后,终止匹配,不再匹配后面的规则
- redirect : 返回302临时重定向,浏览器地址栏会显示跳转后的URL地址
- permanent : 返回301永久重定向,浏览器地址栏会显示跳转后的URL地址
last一般写在server和if中,而break一般使用在location中
last不终止重写后的url匹配,即新的url会再从server走一遍匹配流程,而break终止重写后的匹配
break和last都能组织继续执行后面的rewrite指令
last和break用来实现URI重写,浏览器地址栏URL地址不变
redirect和permanent用来实现URL跳转,浏览器地址栏会显示跳转后的URL地址
if指令与全局变量
if判断指令
语法为if(condition){...},对给定的条件condition进行判断。如果为真,大括号内的rewrite指令将被执行,if条件(conditon)可以是如下任何内容:
当表达式只是一个变量时,如果其值为空或任何以0开头的字符串时都会当作条件为false
直接比较变量和内容时,
使用=或!=
-f和!-f 用来判断是否存在文件
-d和!-d 用来判断是否存在目录
-e和!-e 用来判断是否存在文件或目录
-x和!-x 用来判断文件是否可执行
例如: http://www.a.com/msie/a/b/test.html
if ($http_user_agent ~ MSIE) {
rewrite ^(.*)$ /msie/$1 break;
}
//如果UA包含"MSIE",rewrite请求到/msie/目录下
if ($request_method = POST) {
return 405;
} //如果提交方法为POST,则返回状态405(Method not allowed)。return不能返回301,302
注意:因为返回301和302不能只返回状态码,还必须有重定向的URL,所以return指令无法返回301,302。
if ($slow) {
limit_rate 10k;
} //限速,$slow可以通过 set 指令设置
if (!-f $request_filename){
break;
proxy_pass http://127.0.0.1;
} //如果请求的文件名不存在,则反向代理到localhost 。这里的break也是停止rewrite检查
if ($args ~ post=140){
rewrite ^ http://example.com/ permanent;
} //如果query string中包含"post=140",永久重定向到example.com
Nginx变量
下面是可以用作if判断的变量
$args: 记录请求行中的参数,同$query_string
$content_length: 记录请求头中的Content-length字段。
$content_type: 记录请求头中的Content-Type字段。
$document_root: 记录当前请求在root指令中指定的值。
$host : 记录请求主机头字段,否则为服务器名称。
$http_user_agent: 记录用于记录客户端浏览器的相关信息
$http_cookie: 记录客户端cookie信息
$limit_rate: 记录可以限制连接速率。
$request_method: 记录客户端请求的动作,通常为GET或POST。
$request_filename: 记录当前请求的文件路径,由root或alias指令与URI请求生成。
$scheme : 记录HTTP方法(如http,https)。
$server_protocol: 记录请求使用的协议,通常是HTTP/1.0或HTTP/1.1。
$server_addr: 记录服务器地址,在完成一次系统调用后可以确定这个值。
$server_name: 记录服务器名称。
$server_port: 记录请求到达服务器的端口号。
$request_uri: 记录包含请求参数的原始URI,不包含主机名,如:”/foo/bar.php?arg=baz”。
$uri: 记录不带请求参数的当前URI,$uri不包含主机名,如” /foo/bar.php”。
$document_uri: 与$uri相同。
$http_x_forwarded_for 记录远程客户端的ip地址
$remote_addr: 记录远程客户端的IP地址。
$remote_port: 记录远程客户端的端口。
$remote_user 记录远程客户端用户名称
$time_local 记录访问时间及时区
$request 记录请求的URL与HTTP协议
$status 记录请求的状态,例如成功时为200,页面找不到时为404
$body_byte_sent 记录发送给客户端的文件主体内容大小
$http_referer 记录是从哪个页面链接访问过来的
URL分析:
http://localhost:88/test1/test2/test.php
$host:localhost
$server_port:88
$request_uri:http://localhost:88/test1/test2/test.php
$documenturi:/test1/test2/test.php
$document_root:/var/www/html
$request_filename:/var/www/html/test1/test2/test.php
Nginx日志案例:
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
//IP地址-用户名 [本地时间] “请求”
//状态码主体内容大小“访问来源链接”
//”浏览器信息”“客户端IP地址”
192.168.200.2 - -[21/Nov/2016:10:14:57 +0800]"GET / HTTP/1.1"3040"-""Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.1; WOW64; Trident/4.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; InfoPath.3; .NET4.0C; .NET4.0E)"
示例,如果访问的URL以"*.sh" "*.bash"结尾,则返回状态码403
location ~ .*\.(sh|bash)?$
{
return 403;
}
将原来要访问/data目录重写为/bbs
rewrite ^/data/?$ /bbs/ permanent;
rewrite ^/data/(.*)$ /bbs/$1 permanent;
防止盗链
localtion ~*\.(gif|jpg|png|swf|flv)${
valid_referers none blocked www.test.com *.test.com;
if($incalid_referer){
rewrite ^/(.*) http://www.test.com/block.html break;
}
}
实现域名跳转
所有对www.360buy.com的访问,rewrite到www.jd.com
server {
listen 80;
server_name www.jd.com;
charset utf-8;
root html;
index index.html index.htm;
if ($host = "www.360buy.com") {
rewrite ^(.*)$ http://www.jd.com/$1 permanent;
}
}
将访问www.baidu.com下的所有请求转发到http://www.baidu.com@123/
if ($host = "www.baidu.com") {
rewrite ^(.*)$ http://www.baidu.com@123/$1 permanent;
}
三、Nginx静动分离
实验环境:两台服务器
192.168.200.111 Nginx服务器
192.168.200.112 LAMP服务器
LAMP rpm方式搭建
[root@localhost ~]# yum -y install httpd mariadb mariadb-devel mariadb-server php
[root@localhost ~]# systemctl start httpd
[root@localhost ~]# systemctl start mariadb
[root@localhost ~]# cat /var/www/html/index.php
<?php
phpinfo();
?>
宿主机测试:

配置Nginx动静分离
修改nginx.conf主配置文件
location ~* \.(png|bmp|jpg)$ {
root /usr/local/nginx/html/images;
}
location ~* \.php$ {
proxy_pass http://192.168.200.112;
}
浏览器访问测试图片文件:
[root@nginx ~]# cd /usr/local/nginx/html/
[root@nginx html]# tree
.
├── 50x.html
├── images
│?? └── linux.png
└── index.html
1 directory, 3 files

更多推荐



所有评论(0)