玩转Nginx 04 --- 反向代理:给 nginx 接上后端
一、本课目标
让 nginx 把 /api/ 开头的请求转发 给一个真实的后端服务,并亲眼验证"请求穿过 nginx 到达后端、响应再带回来"。搭出生产环境标准架构:浏览器 → nginx → 后端服务。
二、核心概念:反向代理(一句话版)
nginx 收到访问 8081 且路径以 /api/ 开头的请求时,转手交给 8090 的服务处理。
yaml
浏览器 ──▶ 8081(nginx)
│ 命中 location /api/ { proxy_pass http://127.0.0.1:8090; }
▼
8090(后端服务)── 响应带回 ──▶ nginx ──▶ 浏览器
- 浏览器只敲 nginx 的门,不知道后端存在------后端换端口/换机器,浏览器无感
- 静态文件 nginx 自己发(第 2 课),动态请求转发给后端(本课)------混合编排
三、实验步骤
1. 造一个后端(Python 自带 HTTP 服务,无依赖)
~/桌面/work/Nginx-lab/backend.py:
python
from http.server import HTTPServer, BaseHTTPRequestHandler
import json
class Handler(BaseHTTPRequestHandler):
def do_GET(self):
body = json.dumps({"service": "backend", "path": self.path}).encode()
self.send_response(200)
self.send_header("Content-Type", "application/json")
self.send_header("Content-Length", str(len(body)))
self.end_headers()
self.wfile.write(body)
HTTPServer(("127.0.0.1", 8090), Handler).serve_forever()
作用:监听 8090 端口,谁来访问都回一句 JSON("我是后端,你访问的是 /xx 路径")。
2. 启动后端(后台运行)
bash
nohup python3 ~/桌面/work/Nginx-lab/backend.py > /tmp/backend.log 2>&1 &
sleep 1 && curl -i http://127.0.0.1:8090/api/hello
nohup ... &= 后台常驻(关终端不死);输出重定向到日志文件- 先直接访问后端,确认厨房自己工作正常
3. nginx 配置加转发包间
nginx
location /api/ {
proxy_pass http://127.0.0.1:8090;
}
- 写在
location /兜底之前 (普通前缀按"最长者胜":/api/...会命中/api/而不是/) proxy_pass后不带多余路径 = 原封不动转发(/api/hello送出去还是/api/hello)
4. 生效 + 验证
bash
sudo nginx -t && sudo systemctl reload nginx && curl -i http://127.0.0.1:8081/api/hello
四、实验结果解读(铁证)
arduino
HTTP/1.1 200 OK
Server: nginx/1.18.0 (Ubuntu) ← 浏览器见到的是 nginx(接待员)
Content-Type: application/json
{"service": "backend", "path": "/api/hello"} ← 内容是后端的(厨房的菜)
| 响应特征 | 说明 |
|---|---|
Server: nginx |
浏览器只认识接待员,后端被藏住了 |
Content-Type: application/json |
后端做的"菜"(nginx 自己只会发 HTML/静态文件) |
正文 {"service": "backend"...} |
后端处理的结果原样带回 |
五、本课踩的坑
- 端口冲突 :后端想用 9000,但被 MinIO 占用 (
OSError: [Errno 98] Address already in use)→ 换用 8090。启动失败先看日志:cat /tmp/backend.log - localhost vs 127.0.0.1 :后端只绑 IPv4
127.0.0.1,curl localhost可能解析到 IPv6::1而卡住;浏览器会自动回落 IPv4 所以正常。调试用127.0.0.1。
六、命令清单(本课新增)
| 命令/指令 | 作用 |
|---|---|
nohup python3 xxx.py > log 2>&1 & |
后台常驻运行 Python 服务 |
| `ps aux | grep backend.py` |
| `ss -tlnp | grep 8090` |
grep -n "proxy_pass" /etc/nginx/sites-available/site2 |
在配置文件里搜关键词+行号 |
proxy_pass http://127.0.0.1:8090; |
location 里把请求转发给后端 |
七、补充知识:为什么叫"反向代理"?(正向 vs 反向)
同一个"代理"动作,站在哪一边,就叫什么名字。
| 正向代理 | 反向代理(本课) | |
|---|---|---|
| 替谁干活 | 替客户端(用户)出门 | 替服务器(后端)接客 |
| 谁被藏起来 | 客户端(服务器只看到代理) | 后端(客户端只看到代理) |
| 部署在哪 | 用户侧:自己电脑上的代理软件、浏览器代理设置、公司出口代理 | 服务侧:后端前面的 nginx / 负载均衡器 |
| 生活比喻 | 你雇跑腿小哥去商店买东西 | 商店雇前台接待客人 |
| 典型例子 | 翻墙工具(HTTP/SOCKS 代理)、公司上网代理 | nginx、负载均衡器 |
细节:VPN 是加密隧道技术(网络层),HTTP/SOCKS 代理才是严格意义的"正向代理"(应用层),但定位一致------都站在用户这边替用户访问。
判断口诀(永远不错):
代理挡在谁前面,就是谁那边的代理。挡在用户前面(浏览器主动去找它)= 正向;挡在服务器前面(用户不知道它存在)= 反向。
正向代理(用户侧):你的电脑/浏览器 ──▶ 代理 ──▶ 外网服务
反向代理(服务侧):浏览器 ──▶ nginx ──▶ 后端服务
八、一句话总结
反向代理 = nginx 把
location匹配到的请求转交给后端服务,再把响应带回给浏览器。静态文件自己发(root),动态请求转发(proxy_pass)------浏览器只认识 nginx,后端随便换。
九、下一课预告
第 5 课:负载均衡 ------ 一个接待员,多个厨房 ⚖️
- 为什么需要多个后端:单点压力、扩容、高可用
upstream配置:一个名字管一群后端- nginx 的三种分流策略:轮询 / 权重 / IP 哈希
- 现场实验:两个后端轮流接客,浏览器无感