跳到正文
Nginx 反向代理:站在所有服务前面的门卫,和那个末尾斜杠
Nginx 反向代理:站在所有服务前面的门卫,和那个末尾斜杠

Nginx 反向代理:站在所有服务前面的门卫,和那个末尾斜杠

服务跑在 8000、8080,直接暴露既难看又难管。这篇不讲配置大全,讲浏览器不该直连后端、proxy_pass 末尾斜杠那个绊脚点,以及「先验后发」的 reload 纪律。

速读#

反向代理不是为了好看,而是把对外入口统一起来,让浏览器别直接和后端进程对话。这篇最该记住三点:转发头要传对,proxy_pass 末尾斜杠别乱玩,改完先 nginx -t 再 reload。

为什么要反代#

收益含义
统一入口用户记域名,不记端口
隐藏后端后端可绑回环,不直接暴露
集中加 HTTPS / 负载放在入口层,后端不用各管各的

反向代理不是为了好看,是把「对外的一致性」和「对内的多样性」分开——对外一个域名 + HTTPS,对内一堆不同端口的服务。

正反代理:替谁出门#

  • 正向代理:替客户端出门(翻墙)
  • 反向代理:替服务器接客

用户只跟 Nginx 打交道,Nginx 再转给后面服务。用「替谁出门」记就不混。

一份反代配置,和栽过的转发头#

server {
listen 80;
server_name app.example.com;
location / {
proxy_pass http://127.0.0.1:8000;
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;
}
}

不传这些头,后端只看到 Nginx 本地 IP,拿不到访客真实 IP 和协议。原因在反代的本质:后端收到的连接是 Nginx 发起的,不是用户发起的。 用户是谁、走没走 HTTPS,这些信息断在了 Nginx 这一跳,只能靠头显式传下去。

X-Forwarded-Proto 我栽过——漏了它,上 Cloudflare HTTPS 后 WordPress 无限重定向:用户明明走着 HTTPS,后端看到的却是 HTTP,于是执着地往 HTTPS 跳,跳完还是这样,循环。这行不是模板自带的装饰,是踩坑才认识价值。

末尾斜杠:不熟别玩花活#

proxy_pass 末尾带不带斜杠,行为不同。以 location /api/ 收到请求 /api/users 为例:

proxy_pass 写法后端收到
http://127.0.0.1:8000(不带)/api/users
http://127.0.0.1:8000/(带)/users

一个斜杠,决定 location 前缀剥不剥离。被人问过这个,我当时答不上来。

后来的判断:简单反代不带斜杠、location 用 /;需要路径改写时再查文档现核对。 不熟的时候别玩花活——这种一个字符改变语义的地方,靠印象写等于埋雷。

先验后发:-t && reload#

Terminal window
nginx -t && systemctl reload nginx
步骤作用
nginx -t语法检查;报错时旧配置仍生效
reload平滑重载,不断已有连接

改完别急着 reload。用 && 连成一条命令:只有测试通过才 reload,手不会比脑子快。

和 SSH 改配置「留当前会话」、防火墙启用前「先放行 SSH」同源:可能搞挂自己的操作前,先留活路 / 先验证。 Nginx 在这条纪律上还更友好——-t 失败时旧配置照常跑着,你有充足时间改。

后面加服务就是改端口#

  • 对内:proxy_pass 指向绑回环(127.0.0.1)的容器或进程,公网摸不到后端
  • 对外:HTTPS 统一加在这一层,后端全走明文回环
  • 协议头:前面还有 CDN / 隧道时,X-Forwarded-Proto 要如实往后传,别让协议信息在中间断掉。真实 IP 同理——每多一跳,$remote_addr 就只是上一跳的地址,访客是谁全靠转发头逐跳接力

Nginx 是接客的门卫,它的质量决定后面所有服务对外的体验。 不管后面是 Spring Boot、Django 还是 Node,思路一样——改的只是 proxy_pass 后面那个端口。

版权许可

CC BY-NC-SA 4.0 本作品采用知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议进行许可。

相关文章

s1oopX

登录 s1oopX