在nginx里配置二级目录访问别的服务器,核心就是用location块配合proxy_pass指令,把指定目录的请求反向代理到目标服务器,这么配置直接、稳定,而且支持多级路径转发。
nginx二级目录代理配置的核心原理
先分清楚“二级目录”和“二级域名”
很多人在刚开始接触nginx配置时,会把二级目录和二级域名搞混。
- 二级域名:
app.example.com,这是独立的子域,配置时通常需要新建一个server块。 - 二级目录:
example.com/app/,这是主站域名下挂在根目录后面的路径。
这次聊的场景是二级目录,也就是在同一个域名下,把某个路径的流量转发给另一台服务器处理。
比如你现在的服务器上跑着主站,另一台机器上跑着一个用 8080 端口搭建的Java应用,主站用 https://example.com/backend/ 去访问这台Java应用的接口或页面,这种情况下,nginx就充当了一个反向代理的角色,把特定目录的请求“转交”给别的机器。
nginx如何匹配二级目录
nginx处理这种需求,靠的是 location 指令,nginx拿到用户的请求URL后,会和配置里的location规则做对比,匹配成功的规则就生效。
对于二级目录代理,最常见的写法是这样:
location /backend/ {
proxy_pass http://192.168.1.10:8080/;
}
这段配置的含义是:当用户访问 你的域名/backend/ 下的任何资源时,nginx会把请求原封不动地转发给 http://192.168.1.10:8080/。
但这里有个极其关键的细节:proxy_pass 后面是否带URI(即路径部分),直接决定了代理后URL的变化。
如果proxy_pass后面不带路径,比如这样:
location /backend/ {
proxy_pass http://192.168.1.10:8080;
}
那么用户请求 /backend/login,nginx转给后端服务器时,后端收到的请求路径仍然是 /backend/login,因为nginx只是把流量转发过去,没有对URL做任何改写。
如果proxy_pass后面带了路径,比如这样:
location /backend/ {
proxy_pass http://192.168.1.10:8080/;
}
那么用户请求 /backend/login,nginx转发给后端时,后端收到的路径就是 /login,因为/backend/ 这段已经在转发时被替换成了。
行业共识认为,带斜杠和不带斜杠是配置二级目录代理最容易翻车的地方,运维工程师排查问题时最先看的就是这个。
nginx反向代理二级目录的完整实操配置
应用场景假设
假设有一个线上项目,主站是 www.example.com,由nginx直接处理静态页面,现在开发了一个新系统,部署在另一台服务器 0.0.2 上,占用 8080端口,系统根路径访问本身是正常的。
现在需求是:用户访问 www.example.com/data/ 时,能用到 0.0.2:8080 这台机器上的服务。
第一步:确定目标服务器的路径结构
先去目标服务器确认一下,当前系统是否使用了/data/这个前缀,比如直接用IP访问 http://10.0.0.2:8080/data/health 和 http://10.0.0.2:8080/health,看哪个返回正常。
这一步决定了最终的写法:
- 如果后端系统本身没有
/data前缀,就用proxy_pass http://10.0.0.2:8080;(不带斜杠),这样nginx会保留用户请求里的
/data/,相当于后端收不到这个路径,导致404。 - 如果后端系统本身带有
/data前缀,就用proxy_pass http://10.0.0.2:8080;(不带斜杠),这样后端收到的路径是完整的/data/xxx,和直接访问效果一致。
多数情况下后端应用是独立部署的,本身不带外网映射的前缀,所以经常用不带斜杠的写法,这样后端完全感知不到外部代理的存在。
第二步:编写nginx配置
打开nginx配置文件,常见的路径是 /etc/nginx/conf.d/ 目录下新建一个配置文件,或者在 nginx.conf 的 http块内增加server配置。
如下:
server {
listen 80;
server_name www.example.com;
# 其他站点配置省略
location /data/ {
proxy_pass http://10.0.0.2:8080;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
这套配置里的几个proxy_set_header也很重要。
proxy_set_header Host $host; 这一行,把用户访问时候的域名信息透传给后端服务器,很多后端程序(比如Tomcat、Spring Boot)会根据Host头来生成跳转链接或者校验域名白名单,不设置的话容易导致后端返回的页面跳转地址错乱。
X-Real-IP 和 X-Forwarded-For 是为了让后端拿得到用户真实的IP地址,否则后端看到的来源IP全是nginx这台服务器的IP,会对日志分析、风控、审计造成麻烦。
第三步:修改后端应用的Context Path(如果需要)
如果后端应用本身采用的是全路径匹配路由,比如Spring Boot项目里配置了 server.servlet.context-path=/data,那么nginx配置就要写成:
location /data/ {
proxy_pass http://10.0.0.2:8080/data/;
}
这样nginx把 /data/xxx 转成后端 /data/xxx,后端能正确路由。
但更推荐的方案是后端不设置context-path,直接把处理逻辑写在根路径,nginx这边用不带头部的proxy_pass,这样前后端配置解耦,以后不管是改成二级域名还是换服务器都能平滑调整。
第四步:使用upstream精细化负载和备用节点
如果后端有多台服务器,或者要配置主备切换,可以使用 upstream 块来定义服务器池。
upstream data_backend {
server 10.0.0.2:8080 weight=3;
server 10.0.0.3:8080 weight=1;
}
server {
location /data/ {
proxy_pass http://data_backend;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
}
用upstream的好处是配置灵活,nginx会根据权重自动分发请求,而且一台服务器挂掉时能自动切换,不影响线上访问。
第五步:重启nginx并验证
配置写完,建议先检查语法:
nginx -t
这个命令会验证配置文件有没有语法错误,如果显示 syntax is ok,就可以平滑重启:
nginx -s reload
特别提醒:nginx的reload不会中断现有连接,对于持续运行的线上服务是安全的。
验证时可以这样检查是否匹配:
curl -I http://www.example.com/data/
重点看下面的情况:
- 返回 404
,说明目录匹配没问题,但后端没找到资源,查看后端日志或调整路径。
- 返回 502,说明nginx能匹配到规则,但连不上后端服务器,检查目标机器的防火墙、服务启动状态、端口占用。
- 返回 301/302,大概率是后端做了跳转,需要注意跳转的目的位置是否仍然指向后端内网地址。
如果确实发生了端口或路径错乱,通常优先检查proxy_pass的斜杠问题,这也是为什么问“nginx怎么配置二级目录访问别的服务器”时,老手都会先问你有没有带上斜杠的原因。
配置nginx二级目录时最常见的坑
静态资源加载不出来
这是最典型的场景。
用户访问 www.example.com/data/page,HTML页面被代理成功,但页面里引用的CSS、JS、图片路径是绝对路径,/static/css/main.css。
浏览器就会直接请求 www.example.com/static/css/main.css,这个请求不会匹配 location /data/,自然也就没有转发到后端服务器。
解决思路分两种:
一种是在页面上把所有资源路径都加上/data前缀,改为 /data/static/css/main.css,让资源请求同样走代理。
另一种是利用nginx的try_files或者额外的location块,把静态资源单独分流出来:
location /data/static/ {
proxy_pass http://10.0.0.2:8080/static/;
}
具体用哪种,主要看后端页面的路径设计,就实际经验来看,第一方的内部系统多用后者,第三方开源系统则往往在前端代码里就有兼容方案。
后端生成的跳转链接丢失目录前缀
后端应用在处理登录、重定向等逻辑时,经常会返回一个 Location 响应头,http://10.0.0.2:8080/login。
nginx直接把这个响应头原样返回给浏览器,浏览器就会直接跳转到 0.0.2:8080/login,完全绕过了二级目录,这就出问题了。
处理办法是在nginx响应阶段改写Location头:
proxy_redirect http://10.0.0.2:8080/ http://www.example.com/data/;
书写时要把对应的映射关系写完整,逗号前是后端返回的地址前缀,逗号后是希望用户访问的地址前缀。
环境变量和cookie路径的适配
有些后端应用会根据当前请求的路径来设置Cookie的Path属性,Cookie的Path如果不一致,可能导致用户在访问 /data/ 下功能时反复登录。
这类问题一般需要后端配合处理,nginx能做的事情有限,这也是业内通常不建议用二级目录去代理一套逻辑复杂应用的原因,综合来看,能用子域名尽量用子域名,二级目录只是特殊场景的妥协方案,如果整个站点是一个完整应用,架构上更推荐拆成子域名,这也是nginx运维圈子里的普遍共识。
nginx二级目录配置有哪些常用变体
带正则表达式的匹配
有些场景下需要匹配特定模式的目录,比如二级目录后面还有版本号:
location ~ ^/api/v[0-9]+/ {
proxy_pass http://10.0.0.2:8080;
}
这种写法用正则去匹配动态变化的目录结构,适合有多个版本并存的后端接口,注意正则location的匹配优先级高于普通字符串前缀匹配,配置时要注意别和其他location规则冲突。
同时限制来访IP
如果这个二级目录仅仅面向内部员工,可以在location里加一层访问控制:
location /admin/ {
allow 192.168.1.0/24;
deny all;
proxy_pass http://10.0.0.2:8080;
}
这个配置保证了只有内网网段的用户才能通过nginx访问到后端的 /admin/ 目录,其他人一律拒绝。
应对WebSocket协议
如果二级目录背后是WebSocket服务,需要额外设置升级相关的请求头:
location /ws/ {
proxy_pass http://10.0.0.2:8080;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
性价比比较高的做法是单独开一个 /ws/ 路径供WebSocket使用,不与普通HTTP请求混在一起,nginx对WebSocket的代理已经相当稳定,按照上面配置即可。
配置时选明文HTTP还是HTTPS
如果主站是HTTPS访问,而二级目录代理的内部服务器走的是HTTP,nginx与后端之间的通讯是内网链路,相对安全,可以直接配置HTTP。
跨机房或跨公网转发时,优先考虑在后端服务器上也启用HTTPS,然后在nginx里这样写:
location /data/ {
proxy_pass https://业务服务器地址;
}
相对复杂的微服务架构场景里,甚至可能有多级nginx代理,每一级都要把X-Forwarded-头正确地往下传,否则最末端应用拿到的IP信息会失真。
近年来,云环境里还有不少团队选择Nginx Ingress Controller来处理这类路径转发,本质上都是基于nginx的location+proxy_pass原理,万变不离其宗。
常见问题解答
nginx里按目录反代和按端口反代在配置上有什么区别?
最明显的区别是location匹配规则不一样。
按目录转发需要先配置 location /某路径/,而且要注意路径结尾的斜杠,nginx的location前缀匹配对斜杠很敏感,按端口转发则不需要location,直接用 proxy_pass http://内网IP:端口; 会把整台服务器的流量全部转发过去,按端口反代通常用于IP加端口访问不变、仅做代理的场景,比如把本机的80端口流量全量导给后端的8080服务。
为什么nginx配置好二级目录代理后,首页能打开但URL地址栏的路径消失了?
比较常见的原因是后端应用强制做了重定向。
比如你访问 www.example.com/data/,后端收到请求后返回了一个302跳转,目标是根路径 ,浏览器跟着跳转就丢掉了/data前缀,排查时先抓后端直接返回的响应头,确认有没有Location参数,再使用proxy_redirect来把后端返回的根路径修改为带/data/前缀的地址,这个问题在实际运维中很常见,只要抓包定位了重定向来源,逐一按来源配置反向映射即可。
宝塔面板环境下nginx二级目录反向代理怎么配置?
宝塔面板在网站设置里提供了“反向代理”功能入口,操作路径是:网站 -> 找到对应站点 -> 设置 -> 配置文件。
宝塔自动生成的反向代理配置里,proxy_pass默认写的是完整的后端地址,一般不需要手动修改,如果你需要修改location匹配的路径,直接在配置文件里找到对应的location块,把 改成你想要的二级目录路径,并同时调整proxy_pass后的URI即可,宝塔环境下存量配置会被面板覆盖,修改前记得备份一份原文件,避免失效后不好回滚。
nginx配置二级目录反向代理的硬核就两件事:location写法决定请求往哪走,proxy_pass写法决定路径要不要改,把这两条牢记在心,遇到404、502或丢路径时,先从斜杠和头部信息查起,八成问题能迎刃而解。
首发原创文章,作者:王坚,如若转载,请注明出处:https://idctop.com/article/710194.html





