Nginx反向代理、重定向


Posted in Servers onApril 13, 2022

前言:

我们访问一个网址,服务器返回对应的资源。那么一个网址是如何对应一个资源的呢?
用 Nginx 可以很好地帮我们实现路由功能,我们所有需要做的就是配置好 location 模块。

语法规则

 location [=|~|~*|^~] /uri/ {… }

符号 含义
= 精确匹配 
^~ 非正则匹配
~ 正则匹配(区分大小写)
~* 正则匹配(不区分大小写)
!~ 正则不匹配(区分大小写)
!~* 正则不匹配(不区分大小写)
  普通匹配(这里没有符号的时候)

匹配规则

1. 精准匹配命中时,停止location

2.一般匹配(普通和非正则)命中时,对比所有命中的一般匹配,选出最长的一条

3.如果最长的那一条为非正则匹配,直接匹配此条,停止location

4.如果最长的那一条为普通匹配,继续尝试正则location(以上至此都不存在代码顺序)

5.按代码顺序执行正则匹配,当第一条正则location命中时,停止location

示例:

想运行以下示例需先下载第三方模块echo-nginx-module:

#下载到/usr/local/src目录

wget https://github.com/openresty/echo-nginx-module/archive/v0.61.tar.gz

tar -zxvf v0.61.tar.gz                                 

#在Nginx源码目录nginx-1.15.8下配置,--add-module指向模块目录即会安装插件到nginx中

./configure --add-module=/usr/local/src/echo-nginx-module-0.61/

make && make install

#验证安装

nginx -V

Nginx反向代理、重定向

你还需要配置 C:\Windows\System32\drivers\etc\hosts 文件,添加“虚拟机ip 域名”到最后:

192.168.100.14 test.loaction.com

server {
 
	listen       80;
	server_name  test.location.com;
 
	#精准匹配测试
	#第1,2条虽然匹配,但第三条是精准匹配,出第三条结果
	#测试路径/equal/a/b/c
	location ~ /equal/* {
		echo '/equal/*';
	}
	location /equal/a/b {
		echo '/equal/a/b';
	}
	location = /equal/a/b/c {
		echo '/equal/a/b/c';
	}
 
	#普通匹配测试
	#第1,2条虽然匹配,第三条匹配更长,出第三条结果
	#测试路径/match/a/b/c
	location /match/a {
		return 200  "/match/a";
	}
	location /match/a/b {
		return 200  "/match/a/b";	
	}
	location /match/a/b/c {
		 return 200  "/match/a/b/c";
	}
	location /match/a/b/c/d {
		return 200  "/match/a/b/c/d"; 
	}
 
	#正则匹配覆盖普通匹配,不会覆盖非正则匹配
	#访问/re/a.htm,会被后面的正则覆盖
	#访问/re/a/b开头的路径,不会被后面的正则覆盖
	location /re/a.htm {
		 echo 'match /re/a.htm';
	}
	location ^~ /re/a/b {
		echo 'math ^~/re/a/b*';		
	}
	location ~ /re/(.*)\.(htm|js|css)$ {
		echo "cover /re/$1.$2";
	}
 
	#正则匹配成功一条后,便不再走其它正则
	#测试路径/rex/a/b/c.htm
	location ~ /rex/.*\.(htm|js|css)$ {
		echo "match first";
	}
	location ~ /rex/a/(.*)\.(htm|js|css)$ {
		echo "match second";
	}
	location ~ /rex/a/b/(.*)\.(htm|js|css)$ {
		echo "match third";
	}
}

结果:

精准匹配最优先:

Nginx反向代理、重定向

一般匹配选最长:

Nginx反向代理、重定向

正则覆盖普通匹:

Nginx反向代理、重定向

不能覆盖非正则

Nginx反向代理、重定向

正则匹配选首位:

Nginx反向代理、重定向

proxy_pass 代理转发

在上面的示例中,我们通过修改本机hosts文件,让本机访问 test.loaction.com 相当于访问 192.168.100.14。我们现在假设有一个服务在 192.168.100.15 这台机器上。我们能不能通过访问 test.loaction.com,访问到 192.168.100.15 上的资源呢?

这样的想法其实是在模拟实际做项目的时候,我们可以只购买一个域名,然后访问多个云服务器。我们要做的就是让域名对应的服务器具有代理转发的功能。这里是服务器作为代理,让客户端能通过访问代理服务器来访问其它服务器,所以是反向代理。

通过在 location 里配置 proxy_pass 就能实现代理转发功能,帮助我们将请求转发到别的服务器。

我们先看示例再看规则:

server {
        listen       80;
        server_name	test.location.com;
 
        本机ip地址:192.168.100.104
 
        #后端服务路径:
        http://192.168.100.105:8080/user/query?id=1
        
        #规则一:
        #访问路径:http://test.location.com/user/query?id=1
        location /user {
        #path1:/user path2:/query 
                          #ip:port 后面无 /
               proxy_pass http://192.168.0.105:8080;
        }
        
        规则二:
        #访问路径 :http://test.location.com/A/user/query?id=1
        location /A/user {
        #path1:/A/user path2:/query 
                           #ip:port 后面有 /xxx
                proxy_pass http://192.168.0.105:8080/user;
        }
       
    }

解读:

后端服务路径都是 http://192.168.100.105:8080/user/query?id=1。用规则一,可以使访问路径为 http://test.location.com/user/query?id=1;用规则二,可以使访问路径为 http://test.location.com/A/user/query?id=1。

规则:

1. 访问路径格式为 sever_name + path1 + path2 + ?param

2. location 后面的路径就是 path1,对照访问路径格式,path1 和 ?param 之间的为path2

3. 如果 proxy_pass 后面的值形如 http: // ip : port; 那么实际访问的地址是 http: // ip : port + path1 + path2 + ?param

4. 如果 proxy_pass 后面的值形如 http: // ip : port / xxx; (末尾相比上面有 /xxx)

    那么实际访问的地址是 http: // ip : port  + path2 + ?param

规则二的作用:

如果我们访问其它服务器都使用规则一,那么我们将无法直观地从 URL 确定这个服务属于那台机器或者哪种服务。

而如果使用规则二,我们可以通过合理的设置明确地知道,我们访问的是服务A。

root 与 index

nginx.conf 里的默认 location 如下:

location / {
            root   html;
            index  index.html;
        }

意思是资源文件的根目录在 nginx 程序所在文件夹下的 html 文件夹:

Nginx反向代理、重定向

如果我们没有写 URI,默认的资源是 html 文件夹下的 index.html

但是你如果这样配置:

location / {
            root   html;
            index  index.html;
        }
 
location /index.html {
                echo "index";
        }

最后访问 http://test.location.com/ 浏览器会输出 index:

Nginx反向代理、重定向

也就是说,虽然前面设置了 index ,但是如果它对应的地址有被 location 匹配到的话,会执行 location 匹配后的结果

但是,必须还是得有 index 对应的文件

为了验证上面这一点,我把 html 目录下的 index.html 改成 index,再 reload 并访问:

Nginx反向代理、重定向

root 与 alias

还是先看示例比较直观:

server {
        listen       80;
        server_name	test.local.com;
 
    #文件地址:/etc/nginx/html/static/a.html
 
	#访问路径:http://test.local.com/static/a.html 	
	location /static {
        #path1:/static path2:/a.html
        root /etc/nginx/html/;
        #文件地址:root + path1 + path2
        }
 
	#访问路径:http://test.local.com/target/a.html 
	location /target {
        #path1:/target path2:/a.html
        alias /etc/nginx/html/static/;
        #文件地址:alias + path2
        }	       
    }

解读:

文件地址一样,访问路径可以不同。

使用 root 声明的是根目录,经过 location 匹配后,直接去根目录下找访问路径中 sever_name 后面的文件地址。

使用 alias 声明的是别名目录,经过 location 匹配后,去别名目录下找访问路径中 sever_name 后面除去 location 匹配的地址的剩余地址。这就好像给 location 匹配的地址取了个别名一样。

规则

1. 访问路径格式为 sever_name + path1 + path2 

2.  location 后面的路径就是 path1,对照访问路径格式,path1 后面的就是 path2

3. 如果使用 root ,文件地址为:

    root + path1 +path2

4. 如果使用 alias ,文件地址为:

   alias + path2

location 执行过程

结合以上内容,就很容易理解 location 执行过程了,如下图

Nginx反向代理、重定向

rewrite 重定向

location 里还可以配置 rewrite 实现重定向:

rewrite regex replacement [flag];

其中:

regex:正则表达式

replacement :替换值flag:后续处理标识,可以为 break/last/permanent/redirect

重点在于 flag :

1. flag=break

发生 nginx 内部重定向,path值被更新,rewrite层面的命令会中断。原控制流程逻辑不变往下走

2. flag=last

发生nginx内部重定向,path值被更新,rewrite层面的命令会中断。控制流程刷新,重新进行整个location层的逻辑流程

3. flag= permanent/redirect

发生页面重定向(301永久重定向/302临时重定向),nginx流程结束,返回http响应到浏览器,页面url更新

4.flag为空

发生nginx内部重定向,path值被更新,rewrite层面的命令继续。最后一个rewrite完毕,刷新控制流程,重新进行location重匹配

示例:

server {
 
	listen       80;
	server_name  test.location.com;
 
	location /a.html {
		echo 'I am a.html';
	}
	location /b.html {
		echo 'I am b.html';
	}
 
	#此路径请求:http://test.location.com/aa.html
	location /aa.html {##内部重定向
		rewrite ^/  /a.html break;##不会执行下面的rewrite		
		rewrite ^/  /b.html break;	
		root   /etc/nginx/html/;
	}
	
 
	#此路径请求:http://test.location.com/ab.html
	location /ab.html {##内部重定向
		rewrite ^/  /a.html last;##不会执行下面的rewrite,但重新location匹配
		rewrite ^/  /b.html last;
		rewrite ^/  /c.html;
		root   /etc/nginx/html/;		
	}
 
	#此路径请求:http://test.location.com/ba
	location /ba {
		rewrite ^/  /b.html permanent;##301永久重定向
		root   /etc/nginx/html/;
	}
 
 
	#此路径请求:http://test.location.com/bb
	location /bb {
		rewrite ^/  /b.html redirect;##302临时重定向
		set $aa 12;
		root   /etc/nginx/html/;
	}
	
	#此路径请求:http://test.location.com/cc.html
	location /cc.html {
                rewrite ^/  /c.html;##指令不停,继续往下
                rewrite ^/  /b.html;
                rewrite ^/  /a.html;##最后一条,生效的是这条
                root   /etc/nginx/html/;
        }
 
}

结果:

访问 http://test.location.com/aa.html,直接寻找 root 目录下的 a.html,我没有写这个 html,所以是 404

Nginx反向代理、重定向

访问 http://test.location.com/ab.html,因为重新 location 匹配了,所以匹配到了上面的 /a.html,输出了一句话

Nginx反向代理、重定向

访问 http://test.location.com/ba,永久重定向,可以看到地址栏的网址都变了,是外部重定向

Nginx反向代理、重定向

访问 http://test.location.com/bb,临时重定向

Nginx反向代理、重定向

访问 http://test.location.com/cc.html,不是 404,也经过了重新 location 匹配

Nginx反向代理、重定向

Nginx 处理请求的11个阶段

Nginx反向代理、重定向

Nginx 处理请求的全过程一共划分为 11 个阶段(如图),按阶段由上到下依次执行 (上一阶段的所有指令执行完毕,才进入下一阶段)

各阶段的含义如下:

  • post_read: 接收到完整的 http 头部后处理的阶段,在uri重写之前。一般跳过
  • server_rewrite: location匹配前,修改uri的阶段,用于重定向,location块外的重写指令(多次执行)
  • find_config: uri 寻找匹配的location块配置项(多次执行)
  • rewrite:找到location块后再修改uri,location级别的uri重写阶段(多次执行)
  • post_rewrite:防死循环,跳转到对应阶段
  • preaccess: 权限预处理
  • access:判断是否允许这个请求进入
  • post_access: 向用户发送拒绝服务的错误码,用来响应上一阶段的拒绝
  • try_files: 访问静态文件资源
  • content : 内容生成阶段,该阶段产生响应,并发送到客户端
  • log:记录访问日志

到此这篇关于Nginx配置 location模块实现路由(反向代理、重定向)功能的文章就介绍到这了!

Servers 相关文章推荐
提升Nginx性能的一些建议
Mar 31 Servers
Nginx进程管理和重载原理详解
Apr 22 Servers
使用goaccess分析nginx日志的详细方法
Jul 09 Servers
Nginx+Windows搭建域名访问环境的操作方法
Mar 17 Servers
iSCSI服务器CHAP双向认证配置
Apr 01 Servers
idea下配置tomcat避坑详解
Apr 12 Servers
Nginx反向代理、重定向
Apr 13 Servers
nginx配置之并发频次限制
Apr 18 Servers
Nginx本地配置SSL访问的实例教程
May 30 Servers
windows server2008 开启端口的实现方法
Jun 25 Servers
阿里云服务器(windows)手动部署FTP站点详细教程
Aug 05 Servers
Fluentd搭建日志收集服务
Sep 23 Servers
Docker下安装Oracle19c
nginx location 带斜杠【 / 】与不带的区别
Apr 13 #Servers
Linux下使用C语言代码搭建一个简单的HTTP服务器
idea下配置tomcat避坑详解
CentOS安装Nginx并部署vue
CentOS7安装GlusterFS集群以及相关配置
Nginx+Tomcat负载均衡多实例详解
You might like
php 强制下载文件实现代码
2013/10/28 PHP
php加密解密函数authcode的用法详细解析
2013/10/28 PHP
memcache一致性hash的php实现方法
2015/03/05 PHP
PHP 7的一些引人注目的新特性简单介绍
2015/11/08 PHP
php简单中奖算法(实例)
2017/08/15 PHP
php记录搜索引擎爬行记录的实现代码
2018/03/02 PHP
laravel自定义分页的实现案例offset()和limit()
2019/10/15 PHP
laravel 数据验证规则详解
2019/10/23 PHP
Js+php实现异步拖拽上传文件
2015/06/23 Javascript
清除浏览器缓存的几种方法总结(必看)
2016/12/09 Javascript
Centos6.8下Node.js安装教程
2017/05/12 Javascript
详解jQuery同步Ajax带来的UI线程阻塞问题及解决办法
2017/08/09 jQuery
纯JavaScript实现实时反馈系统时间
2017/10/26 Javascript
vue源码解析之事件机制原理
2018/04/21 Javascript
JS实现随机抽取三人
2019/11/06 Javascript
vue props对象validator自定义函数实例
2019/11/13 Javascript
vue基于v-charts封装双向条形图的实现代码
2019/12/09 Javascript
vue根据条件不同显示不同按钮的操作
2020/08/04 Javascript
Python编程中的反模式实例分析
2014/12/08 Python
详解Python的Django框架中的模版继承
2015/07/16 Python
Python实现的RSS阅读器实例
2015/07/25 Python
Python实现统计文本文件字数的方法
2017/05/05 Python
django定期执行任务(实例讲解)
2017/11/03 Python
python和shell获取文本内容的方法
2018/06/05 Python
浅析Windows 嵌入python解释器的过程
2019/07/26 Python
详解python itertools功能
2020/02/07 Python
python数据预处理 :数据共线性处理详解
2020/02/24 Python
python用TensorFlow做图像识别的实现
2020/04/21 Python
CSS3 实现童年的纸飞机
2019/05/05 HTML / CSS
银行职员自我鉴定
2014/04/20 职场文书
怎样做好公众演讲能力?
2019/08/28 职场文书
python3使用diagrams绘制架构图的步骤
2021/04/08 Python
Java Socket实现多人聊天系统
2021/07/15 Java/Android
彻底解决MySQL使用中文乱码的方法
2022/01/22 MySQL
动画《平凡职业成就世界最强》宣布制作OVA
2022/04/01 日漫
SQL Server使用CROSS APPLY与OUTER APPLY实现连接查询
2022/05/25 SQL Server