Nginx 反向代理生产配置:upstream 与缓存限流
Nginx 反向代理是生产环境最常见的流量入口:它把外部请求转发给后端应用服务器,再把响应回传给客户端。官方文档明确指出,代理经常被用来在多台服务器之间分发负载,或把请求交给非 HTTP 协议的应用服务器处理。相比Nginx 站点配置,反向代理更强调"转发"这一层,是流量治理的前置关口。
一、upstream:定义后端服务器组
upstream 定义一个后端服务器组,proxy_pass 指向该组时,Nginx 会按负载均衡算法把请求分发给组内服务器。
upstream backend_app {
server 127.0.0.1:3001;
server 127.0.0.1:3002;
server 127.0.0.1:3003 weight=2;
}
server {
listen 80;
server_name api.example.com;
location / {
proxy_pass http://backend_app;
}
}
默认算法是轮询(round-robin),可以通过 weight 调整权重——上面 3003 的 weight=2 意味着它承接约两倍的请求。需要会话保持的应用可以用 ip_hash 让同一客户端始终落在同一后端;后端处理能力差异明显时,least_conn(最少连接)往往比轮询更合理。proxy_pass 后面的地址如果不带 URI,Nginx 会把完整的原始请求 URI 透传给后端——这是最常见的用法,务必不要随手加 /。
二、透传请求头
默认情况下 Nginx 会把 Host 头改写为 $proxy_host,后端拿到的就不是真实域名了。要还原真实域名与客户端信息,需要显式设置:
location / {
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_pass http://backend_app;
}
X-Forwarded-For 是日志审计与安全分析的基础:没有它,后端只能看到 Nginx 自身的 IP,无法区分真实访客,限流、封禁、归属分析全都无从谈起。注意 $proxy_add_x_forwarded_for 会在原有值后面追加本次连接地址,多级代理场景下每一层都应这样追加,才能保留完整链路。
三、proxy_cache:反向代理缓存
Nginx 可以在反向代理层做内容缓存,把热点响应留在内存与磁盘里,显著减轻后端压力。用 proxy_cache_path 定义缓存目录与参数,在 location 中启用:
proxy_cache_path /var/cache/nginx levels=1:2
keys_zone=mycache:10m max_size=1g
inactive=60m use_temp_path=off;
location / {
proxy_cache mycache;
proxy_cache_valid 200 302 10m;
proxy_cache_valid 404 1m;
add_header X-Cache-Status $upstream_cache_status;
proxy_pass http://backend_app;
}
$upstream_cache_status 会返回 HIT/MISS/BYPASS/EXPIRED 等状态,配合 X-Cache-Status 响应头可以快速验证缓存是否生效、命中率是多少。开启缓存前要想清楚边界:只适合幂等的 GET 请求,涉及登录态、购物车、个性化内容的接口要显式 proxy_cache_bypass 或干脆不缓存。更细的缓存键设计可参考缓存键策略。
四、limit_req:限流防刷
limit_req_zone 定义限流速率,limit_req 在 location 中应用。典型的防刷配置如下:
limit_req_zone $binary_remote_addr zone=api_limit:10m rate=10r/s;
location /api/ {
limit_req zone=api_limit burst=20 nodelay;
proxy_pass http://backend_app;
}
rate=10r/s 表示平均每秒放行 10 个请求;burst=20 允许突发时多放行 20 个并排队处理,nodelay 则让这些突发请求立即放行但照常计数。两者组合,既不会误伤正常访问高峰,又能把脚本刷量挡在门外。若想让被限流的客户端得到标准化的响应,可以加一行 limit_req_status 429;。
五、TLS 终结
反向代理层是终结 TLS 的理想位置。证书可由 Let's Encrypt + Certbot 自动签发与续期(或参考一键申请脚本):
server {
listen 443 ssl http2;
server_name api.example.com;
ssl_certificate /etc/letsencrypt/live/api.example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/api.example.com/privkey.pem;
location / {
proxy_set_header X-Forwarded-Proto $scheme;
proxy_pass http://backend_app;
}
}
server {
listen 80;
server_name api.example.com;
return 301 https://$host$request_uri;
}
在 Nginx 层终结 TLS 后,内网后端可以用明文 HTTP 通信,证书只在一处集中管理,大大降低内网证书维护成本。X-Forwarded-Proto 对后端判断"是否 HTTPS"很关键,否则后端可能拼出错误的回调地址。完整 TLS 配置可参考CDN SSL/TLS 配置最佳实践;若已启用 HTTP/3,可进一步参考HTTP/3 加速指南。
六、缓冲区与超时
生产环境通常需要调整代理缓冲,避免慢客户端拖累后端:
location / {
proxy_buffering on;
proxy_buffers 16 4k;
proxy_buffer_size 8k;
proxy_connect_timeout 5s;
proxy_read_timeout 60s;
proxy_send_timeout 60s;
proxy_pass http://backend_app;
}
默认 Nginx 会缓冲后端响应,等整体接收后再发给客户端,这对慢速客户端是必要的优化;但对流式接口(如 SSE、实时推送),应关闭缓冲以保证首字节尽快到达。超时也要分层理解:proxy_connect_timeout 控制与后端建连的时间,proxy_read_timeout 控制两次读操作之间的间隔,并非整个请求的总时长。
七、结合容器部署
当后端跑在 Docker Compose 里时,Nginx 通常作为宿主机入口代理容器端口,可参考Docker Compose 生产部署。更底层的 Nginx 性能调优见Nginx 优化完全指南,LNMP 集成见LNMP 环境搭建。
常见排查场景
生产中最常见的三类"转发异常",通常都能在 Nginx 层快速定位:
- 后端日志里客户端 IP 全是 127.0.0.1:几乎可以断定是没配
X-Forwarded-For,后端拿到的是代理地址。 - 缓存似乎没生效:用
curl -I查看响应头里的X-Cache-Status,若一直是 MISS,检查proxy_cache_key是否因为带了$args而每请求都不同。 - 504 Gateway Timeout:多为
proxy_read_timeout过短,后端处理超过设定值就断连,调大超时或优化后端查询即可。
16IDC 观察
反向代理不是"转发一下"那么简单,它是流量治理的前置层:负载均衡让多实例分担压力,缓存让热点请求不打到后端,限流让异常流量被挡在门外,TLS 终结让证书管理集中化。把这四件事在 Nginx 层做好,后端应用就能专注业务逻辑,架构的健壮性会明显提升。
原文来源:https://docs.nginx.com/nginx/admin-guide/web-server/reverse-proxy/
参考:Nginx 官方内容缓存指南 https://docs.nginx.com/nginx/admin-guide/content-cache/content-caching/