Location通用匹配的注意点


前提应知:

先说一下ContextPath:称为web应用的上下文路径,简单理解为web容器最开始路径,所有的web资源(路径)都要挂在它的下面,使用request.getContextPath()可获得,SpringBoot中的配置为server.servlet.context-path,ContextPath的值只能为以下两种形式:

  1. 空字符串:即长度为0的字符串
  2. /xxx:形如“/xxx”形式的字符串,可以是 /xxx、/xxx/yyy、/xx x/yyy,但 /xxx/在SpringBoot中最终会被处理成/xxx

在nginx反向代理的location中,我们都知道location的匹配格式(写法)决定了不同的匹配方式,从而影响最终的代理到的url。通用匹配是最常用的写法,比如为了方便管理,需要做一套应用的代理。一套应用意思就是几个项目互相依赖组成一个可用的应用,如分布式架构、sso等。这个时候我们需要将这些应用都挂到一个nginx(nginx服务器)的端口下,这样对用户来说好像就一直在访问一个应用。对外提供接口也比较方便,因为用的都是同一个端口。

在通用匹配中location和proxy_pass指令的写法还是有必要注意一下ContextPath的值的,避免掉坑。

都知道通用匹配形如

1
2
3
location /xxx {
proxy_pass http://ip:port/xxx;
}

此时若该location块所在的server块监听的端口为8000,那么上述写法可以这样理解:一个代理挂在了8000端口下的,名为 /xxx;因为假如现在需要在此时可以再加个location去代理其它的地址,端口依旧可以用8000,。

若location如下,

1
2
3
location / {
proxy_pass http://ip:port/xxx;
}

则可以这样理解:一个代理独占了8000端口;再加一个location去代理其它地址就不太好操作,搞不好容易出现代理错误的情况。

下面以上述两种location写法做个测试。

通用匹配测试

nginx服务器

IP:192.168.100.100

SpringBoot应用

IP:192.168.0.200;

一个控制层方法:

1
2
3
4
5
6
7
8
@RestController
public class NginxController {
@RequestMapping("/test")
public String test() {

return "test";
}
}

配置文件aplication.properties:

1
2
3
4
# web容器上下文路径,不写则默认为空字符串
server.servlet.context-path=/demo
# 应用服务 WEB 访问端口
server.port=8080

测试结果

context-path location proxy_pass 结果 描述
- / 192.168.0.200:8080 ok
- / 192.168.0.200:8080/ ok
- /app 192.168.0.200:8080 404 nginx最终代理到:192.168.0.200:8080/app/test
- /app 192.168.0.200:8080/ ok
/demo / 192.168.0.200:8080/demo 404 nginx最终代理到:192.168.0.200:8080/demotest
/demo / 192.168.0.200:8080/demo/ ok
/demo /app 192.168.0.200:8080/demo ok
/demo /app 192.168.0.200:8080/demo/ ok

可见,location的写法和要代理到的目标地址还是有讲究的,详细的话就不说了,为了防止出错,简单一句话总结:

proxy_pass = ip + port + ContextPath,要到的目标应用ContextPath为空字符串时,location写“/”,反之写ContextPath;

有域名的情况自行适配即可。