张啸


世界上最快乐的事,莫过于为理想而奋斗。


Web(4) Nginx设置动态Proxy_Pass

前端开发过程中,我们为了避免与后端进行接口联调时反复修改请求地址,通常会采用服务器地址相对路径的方法,以../rest/api/的模式请求前端文件所在服务器的http://192.168.1.100/rest/api接口。这样可以规避开发阶段(develop)和生产阶段(production)代码不一致的问题,但是在接口联调阶段(debug),特别是前后端由不同的人开发的情况下,则需要使用代理服务器进行转发。


一、问题所在

通常情况下我们的nginx配置如下

1
2
3
4
5
6
7
8
9
10
11
12
server {
listen 80;
server_name localhost;

location / {
root D:\project\branch;
}

location /rest/api/ {
proxy_pass http://192.168.1.100/rest/api/;
}
}

在接口复杂的情况下,我们的location匹配地址可能会出现较多个。而且因为工作需要,我们可能会同时与多个后台开发者进行接口联调,那么可能会出现如下的nginx配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
server {
listen 80;
server_name localhost;

location / {
root D:\project\branch;
}

location /rest/api/ {
proxy_pass http://192.168.1.100/rest/api/;
#proxy_pass http://192.168.1.101/rest/api/;
}

location /rest2/api2/ {
proxy_pass http://192.168.1.100/rest2/api2/;
#proxy_pass http://192.168.1.101/rest/api/;
}

location /rest3/api3/ {
proxy_pass http://192.168.1.100/rest3/api3/;
#proxy_pass http://192.168.1.101/rest/api/;
}
}

二、修改方法

为了工作方便,我们可能会将不同后台开发人员的地址以注释的方式记录在nginx配置文件内,需要切换后台服务器时,修改配置项中的注释内容,然后执行nginx -s reload来重启nginx服务。

那么,既然配置文件中有大量的重复地址信息,比如http://192.168.1.100,我们是不是可以把它提取出来作为nginx变量呢?然后proxy_pass读取它,这样在修改文件时只需要修改一个地方即可。

按照如下方式进行测试

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
server {
listen 80;
server_name localhost;

set $host '192.168.1.100';
#set $host '192.168.1.101';

location / {
root D:\project\branch;
}

location /rest/api/ {
proxy_pass http://$host/rest/api/;
}

location /rest2/api2/ {
proxy_pass http://$host/rest2/api2/;
}

location /rest3/api3/ {
proxy_pass http://$host/rest3/api3/;
}
}

重启服务后,nginx不报错,但是代理无效,无法访问。接着使用geomap均无法正常进行代理转发

最后发现可以使用upstream模式实现此项功能,修改后的配置文件如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
upstream host {
server 192.168.1.100;
#server 192.168.1.101;
}

server {
listen 80;
server_name localhost;

location / {
root D:\project\branch;
}

location /rest/api/ {
proxy_pass http://host;
}

location /rest2/api2/ {
proxy_pass http://host;
}

location /rest3/api3/ {
proxy_pass http://host;
}
}

再次精简一点,采用正则匹配的方式进行修改

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
upstream host {
server 192.168.1.100;
#server 192.168.1.101;
}

server {
listen 80;
server_name localhost;

location / {
root D:\project\branch;
}

location ~ /rest(.*)/api(.*)/ {
rewrite /rest(.*)/api(.*)/ /rest$1/api$2/ break;
proxy_pass http://host;
}
}

这样采用正则匹配方式后,不仅可以匹配原有的/rest1/api1//rest2/api2//rest3/api3/,还可以匹配诸如/project/rest1/api1/等等前面含有项目文件路径的location

等后期有时间,再研究一下nginx的rewriteupstream详细使用方法。


参考文献

  1. proxy_set_header设置Host为$proxy_host,$host与$local_host的区别

  2. Nginx中的proxy_pass和rewrite