5.1 核心概念
- proxy_pass
- 把匹配到的请求转发到指定的后端地址(应用服务器或 upstream 组)。是反向代理的核心指令。
- upstream
- 定义一组后端服务器,供 proxy_pass 引用。可配置负载均衡策略、权重、健康检查(第 6 章详解)。
- X-Forwarded-For(XFF)
- 代理链上追加真实客户端 IP 的请求头。经过多层代理时,后端靠它拿到原始 IP 而非代理 IP。
- X-Real-IP
- 只携带直连客户端 IP 的头,比 XFF 简单,后端应用常用它记日志、做限流。
- proxy_buffering
- Nginx 是否先把后端响应缓冲到内存/磁盘再发给客户端。开启利于慢客户端场景;流式响应(SSE)需关闭。
- WebSocket 升级(Upgrade)
- WebSocket 握手时靠
Upgrade和Connection头把 HTTP 连接升级为长连接。代理时必须显式转发这两个头,否则握手失败。
5.2 最小反向代理
server {
listen 80;
server_name api.example.com;
location / {
proxy_pass http://127.0.0.1:3000;
}
}
请求打到 Nginx 的 80 端口,被原样转发到本机 3000 端口跑的 Node/Java 应用。客户端全程不知道后端在哪、有几台。但上面这份配置不完整——后端拿不到真实客户端信息。
5.3 正确传递请求头
默认转发时,后端看到的 Host 是空或代理地址,客户端 IP 变成了 Nginx 的 IP。必须手动补齐这些头:
location / {
proxy_pass http://127.0.0.1:3000;
# 把原始 Host 传给后端(虚拟主机、重定向需要)
proxy_set_header Host $host;
# 真实客户端 IP
proxy_set_header X-Real-IP $remote_addr;
# 代理链 IP 列表
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
# 原始协议(后端据此判断是否 HTTPS)
proxy_set_header X-Forwarded-Proto $scheme;
}
这组 proxy_set_header 几乎每个反代 location 都要写。把它们存进 /etc/nginx/snippets/proxy-headers.conf,各处 include 引入,既统一又不易漏。后端框架(Express/Spring)也要配置"信任代理"才会读这些头。
5.4 proxy_pass 的 URI 处理陷阱
proxy_pass 后面带不带路径,行为大不同:
不带路径(保留 URI)
location /api/ {
proxy_pass http://backend;
}
/api/users → /api/users
带路径(替换前缀)
location /api/ {
proxy_pass http://backend/;
}
/api/users → /users
规则:proxy_pass 的地址带了 URI 部分(哪怕只是一个 /),location 匹配的前缀就会被替换掉;不带 URI 则原样透传。这决定后端收到的路径,务必测清楚。
5.5 用 upstream 组织后端
http {
upstream app_backend {
server 127.0.0.1:3000;
server 127.0.0.1:3001;
keepalive 32; # 与后端保持长连接,减少握手开销
}
server {
listen 80;
location / {
proxy_pass http://app_backend;
proxy_http_version 1.1; # keepalive 需要 1.1
proxy_set_header Connection ""; # 清空以复用连接
proxy_set_header Host $host;
}
}
}
5.6 超时与缓冲
location / {
proxy_pass http://app_backend;
# 三类超时
proxy_connect_timeout 5s; # 与后端建连超时
proxy_send_timeout 60s; # 向后端发请求超时
proxy_read_timeout 60s; # 等后端响应超时
# 缓冲后端响应
proxy_buffering on;
proxy_buffers 8 16k;
proxy_buffer_size 16k;
}
Server-Sent Events(SSE)、大文件流式下载、LLM 逐字返回等场景,若开着 proxy_buffering on,Nginx 会攒够一批才发,用户感觉"卡住"。这些 location 要 proxy_buffering off;,让数据即产即发。
5.7 代理 WebSocket
WebSocket 需要把 HTTP 连接"升级"为持久连接,必须显式转发 Upgrade/Connection 头,并用 HTTP/1.1:
location /ws/ {
proxy_pass http://app_backend;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_set_header Host $host;
# WebSocket 是长连接,读超时要放大
proxy_read_timeout 3600s;
}
HTTP/1.1 里 Connection 是逐跳(hop-by-hop)头,Nginx 默认不透传。WebSocket 握手要求 Connection: upgrade,所以必须显式 proxy_set_header Connection "upgrade";,否则后端收不到升级请求,握手失败返回 400。
5.8 小结与下一步
- proxy_pass 转发请求;但要手动补 Host / X-Real-IP / X-Forwarded-For / X-Forwarded-Proto。
- proxy_pass 带不带 URI 决定后端收到的路径是否被替换前缀。
- upstream + keepalive + HTTP/1.1 复用后端连接,降低开销。
- 三类超时要合理设;流式响应记得关 proxy_buffering。
- WebSocket 必须转发 Upgrade/Connection 头并用 HTTP/1.1。
- 下一章把单个后端扩成多个——负载均衡。