尧图网站建设 尧图网络
  • 首页
  • 关于我们
  • 服务项目
  • 案例展示
  • 建站流程
  • 资讯中心
  • 联系我们
首页/资讯中心/详情

Nginx 反向代理与负载均衡实战(基于陶辉《深入理解 Nginx》第三章)

Nginx 反向代理与负载均衡实战(基于陶辉《深入理解 Nginx》第三章)
📅 发布时间:2026/7/27 0:26:30

Nginx 反向代理与负载均衡实战(基于陶辉《深入理解 Nginx》第三章)

本文所有命令输出均来自两台真实云服务器(Ubuntu 24.04.4 / nginx 1.24.0)的现场回显,未做任何编造。
拓扑目标:一台代理层把流量按多种策略转发给上游的多个后端,并具备故障自动转移能力。


一、实验拓扑

公网 / 客户端 │ ┌────────▼────────┐ │ 代理层 PROXY │ 139.9.***.*** (公网) │ 192.168.0.149 │ nginx 1.24.0 │ upstream + │ │ proxy_pass │ └────────┬─────────┘ 内网 192.168.0.x(VPC 互通,走内网不占公网带宽) │ ┌────────▼────────┐ │ 上游层 UPSTREAM │ 119.3.***.*** (公网) │ 192.168.0.113 │ nginx 1.24.0 │ 3 个后端: │ │ 8081/8082/8083 │ └──────────────────┘
  • 代理层:承担「反向代理 + 负载均衡」,对外只暴露 80/443,内网回源走192.168.0.113。
  • 上游层:用 3 个独立server块模拟 3 台应用服务器,各自返回可区分的身份头X-Backend,方便观察分发结果。

二、环境准备(两台机器)

两台均用发行版自带的 nginx(apt 安装,无需编译),版本与运行状态如下:

$ nginx-vnginx version: nginx/1.24.0(Ubuntu)$ systemctl is-active nginx active $ ss-ltn|grep':80'LISTEN05110.0.0.0:800.0.0.0:* LISTEN0511[::]:80[::]:*

上游层部署 3 个后端(/etc/nginx/conf.d/backends.conf节选):

server { listen 8081; server_name _; default_type text/plain; add_header X-Backend "backend-8081"; location / { return 200 "backend-8081 served at $time_local\n"; } } # 8082 / 8083 结构相同,仅端口与标识不同

本地验证三个后端均可独立响应:

$curl-s-ihttp://127.0.0.1:8081/|head-8HTTP/1.1200OK Server: nginx/1.24.0(Ubuntu)Content-Type: text/plain X-Backend: backend-8081 $curl-shttp://127.0.0.1:8082/api/health OK backend-8082 $ ss-ltn|grep-E':808[123]'LISTEN05110.0.0.0:80810.0.0.0:* LISTEN05110.0.0.0:80830.0.0.0:* LISTEN05110.0.0.0:80820.0.0.0:*

代理层先确认能通过内网访问到上游(这是生产最佳实践:回源走内网,省公网带宽、低延迟):

$curl-s-ihttp://192.168.0.113:8081/|head-6HTTP/1.1200OK Server: nginx/1.24.0(Ubuntu)Content-Type: text/plain Content-Length:50Connection: keep-alive

三、反向代理基础:proxy_pass

反向代理的核心只有一行proxy_pass,它把客户端请求转发给 upstream 定义的后端组:

# /etc/nginx/conf.d/proxy_upstreams.conf upstream backend_rr { zone backend_rr 64k; server 192.168.0.113:8081; server 192.168.0.113:8082; server 192.168.0.113:8083; }
# /etc/nginx/conf.d/proxy_lb.conf server { listen 80; server_name _; add_header X-Upstream $upstream_addr always; # 透出实际选中的后端 location / { proxy_pass http://backend_rr; 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三件套非常关键:

  • X-Real-IP/X-Forwarded-For:把真实客户端 IP 透传给后端,否则后端access.log里全是代理 IP。
  • Host $host:保留原始 Host,避免后端因 Host 不匹配而走默认站点。
  • X-Forwarded-Proto:告知后端原始协议(http/https),对生成重定向链接、校验安全 cookie 很重要。

从公网直接访问代理的 80 端口,请求被转发到内网后端并回传身份头:

$curl-s-ihttp://139.9.***.***/|grep-iE'X-Backend|X-Upstream|HTTP/'HTTP/1.1200OK X-Backend: backend-8081 X-Upstream:192.168.0.113:8081

X-Backend来自上游后端,X-Upstream来自代理层$upstream_addr——两个头合起来,一条请求从「客户端 → 代理 → 哪个后端」的链路就一目了然。


四、负载均衡算法逐一验证

代理层同时开了 4 个端口,分别绑定不同算法的 upstream,便于横向对比:

端口算法upstream
80默认轮询 round-robinbackend_rr
8091加权轮询 weightedbackend_weighted
8092ip_hash 一致性哈希backend_iphash
8093最少连接 least_connbackend_leastconn

⚠️踩坑与最佳实践:最开始我没有给upstream加zone指令,结果多 worker 下轮询状态各自独立,连续 9 次请求里 8 次都打到了backend-8081:

--1-- X-Backend: backend-8081 / X-Upstream: 192.168.0.113:8081 ...(2~8 同样) --9-- X-Backend: backend-8082 / X-Upstream: 192.168.0.113:8082

加上zone backend_rr 64k;后,把节点状态放进共享内存,分发立刻均衡(见下)。生产环境强烈建议所有 upstream 都加zone,它还能支持运行时增删节点(upstream_conf)。

1) 默认轮询(round-robin)

$foriin$(seq130);docurl-s-ihttp://127.0.0.1:80/|grep-i'X-Backend'|tr-d'\r';done|sort|uniq-c10X-Backend: backend-808110X-Backend: backend-808210X-Backend: backend-8083

三个后端严格 1:1:1,符合 round-robin 的加权轮询(默认权重相等)。

2) 加权轮询(weight)

upstream backend_weighted { zone backend_weighted 64k; server 192.168.0.113:8081 weight=3; server 192.168.0.113:8082 weight=1; server 192.168.0.113:8083 weight=1; }
$foriin$(seq120);docurl-s-ihttp://127.0.0.1:8091/|grep-i'X-Backend'|tr-d'\r';done|sort|uniq-c12X-Backend: backend-80814X-Backend: backend-80824X-Backend: backend-8083

12:4:4 = 3:1:1,与配置权重完全吻合。当某台机器性能好、或某实例权重高时,用weight把更多流量分给它。

3) 最少连接(least_conn)

upstream backend_leastconn { zone backend_leastconn 64k; least_conn; server 192.168.0.113:8081; server 192.168.0.113:8082; server 192.168.0.113:8083; }
$foriin$(seq130);docurl-s-ihttp://127.0.0.1:8093/|grep-i'X-Backend'|tr-d'\r';done|sort|uniq-c10X-Backend: backend-808110X-Backend: backend-808210X-Backend: backend-8083

本例请求都极轻量,连接数始终为 0,所以退化为均匀分发。least_conn的真正价值在「请求耗时不均」的场景:谁最闲分谁,避免慢请求把某台机器堆满。它同样常与zone搭配。

4) ip_hash 一致性哈希

upstream backend_iphash { zone backend_iphash 64k; ip_hash; server 192.168.0.113:8081; server 192.168.0.113:8082; server 192.168.0.113:8083; }
$foriin1234;docurl-s-ihttp://127.0.0.1:8092/|grep-i'X-Backend'|tr-d'\r';doneX-Backend: backend-8083 X-Backend: backend-8083 X-Backend: backend-8083 X-Backend: backend-8083

同一客户端 IP 始终落到同一后端——这正是「会话保持 / 粘性」的需求场景(如未做分布式 Session 时,让用户总是命中同一台缓存了状态的应用)。注意ip_hash是按$remote_addr哈希,若前端还有 CDN/反向代理,需配合X-Forwarded-For的real_ip模块才能拿到真实客户端 IP。


五、故障自动转移(failover)

负载均衡不只是「分发」,更是「容错」。当某后端不可达时,Nginx 默认通过proxy_next_upstream把请求重试到下一个健康节点。

我们在上游层用iptables把 8082 端口「拒绝」掉,模拟该后端宕机:

$ iptables-IINPUT-ptcp--dport8082-jREJECT;echoadded added $ iptables-LINPUT-n|grep8082REJECT6--0.0.0.0/00.0.0.0/0 tcp dpt:8082 reject-with icmp-port-unreachable

此时从代理层连续请求 12 次:

$foriin$(seq112);docurl-s-ihttp://127.0.0.1:80/|grep-i'X-Backend'|tr-d'\r';done|sort|uniq-c6X-Backend: backend-80816X-Backend: backend-8083

死掉的8082一次都没出现,流量被自动切到8081与8083。恢复后移除规则:

$ iptables-DINPUT-ptcp--dport8082-jREJECT;echoremoved removed $ iptables-LINPUT-n|grep8082||echonone none

说明:开源版 Nginx 没有「主动健康检查」(health_check需商业版 Nginx Plus)。这里的 failover 依赖被动健康检查——只有当连接/超时/返回错误(proxy_next_upstream默认的error timeout)发生时才换节点。生产环境可结合max_fails/fail_timeout让节点被「熔断」一段时间,或用第三方模块做主动探活。


六、小结

  • 反向代理:proxy_pass+proxy_set_header(透传 Host / 真实 IP / 协议)即可,回源优先走内网。
  • 负载均衡:round-robin 默认均分;weight调权重;least_conn按连接数选闲;ip_hash做会话保持。四者都在upstream块内声明。
  • 两个关键经验:
    1. upstream务必加zone—— 否则多 worker 下分发会严重偏斜(实测 9 次里 8 次打同一台)。
    2. failover 默认开启(proxy_next_upstream),但属于被动健康检查;高可用需额外探活机制。

下一篇我们将基于这套拓扑,继续实战反向代理缓存与HTTPS + HTTP/2。

相关新闻

  • 三合一协议支持:LuckyLilliaBot如何重新定义QQ机器人开发体验
  • AccelStepper终极指南:Arduino步进电机控制库的完整教程
  • AI生成内容检测工具与算法更新的技术博弈

最新新闻

  • TFLite GPU Delegate 在 Android 嵌入式板上的优化:OpenCL 内核选择与调优经验总结
  • 2026 年新发布:全南专业的护栏网直销厂家联系方式,你家后院那圈不起眼的围栏,竟是能省出半年物业费的隐形帮手? - 企业推荐官【认证】
  • 2026哈尔滨区域钢结构正规厂家实力排行解析 - 起跑123
  • TI SM320F28335-HT DSC:极端温度下电机控制与数字电源的实战设计
  • 2026年华东地区选二手优精特钻攻机实地走访记录 - 起跑123
  • AI 驱动的家庭场景识别:自动切换影音、休息与工作模式界面

日新闻

  • OpenClaw开源智能体网关:AI助手与即时通讯的完美融合
  • 写一个简单的sh脚本
  • 2026年 西安缝隙天线厂家:5G通信与车载天线专业定制供应商深度分析 - 卓企推荐

周新闻

  • 大连理工大学与东京大学联手打造的“主动型AI助手“
  • 170.2026年国家级科研瓶颈:超精密单点金刚石切削(SPDT)光学表面生成
  • SongBloom:革命性歌曲生成框架深度解析——如何通过交织自回归与扩散模型创作完整音乐

月新闻

  • 2026年6月公司网站搭建最新热门渠道测评:四大低成本/零代码平台对比+避坑
  • 【Linux】Linux arm 编译QT程序,出现expected “}“报错
  • 【MATLAB例程】四基站二维AOA定位与距离辅助增强对比仿真。基于角度观测和测距修正的固定目标平面定位精度分析

关于尧图

  • 公司简介
  • 团队介绍
  • 企业文化
  • 荣誉资质

服务项目

  • 定制开发
  • 电商建站
  • UI 设计
  • 运维服务

快速链接

  • 案例展示
  • 建站流程
  • 常见问题
  • 资讯中心

联系方式

  • 📍北京市朝阳区互联网产业园 A 座 10 层
  • 📞400-888-8888
  • ✉️contact@rkmt.cn
  • 🕐周一至周日 9:00-21:00

© 2024 北京尧图网络科技有限公司 版权所有 | 京 ICP 备 XXXXXXXX 号