CodeRoadMap
首页路线题库资源库文章社区
CodeRoadMap

程序员的学习成长路线图。内容免费开放,登录后可同步路线图与课时进度。

由 程序员柏风 独立维护 · 关于作者

学习

  • 路线图
  • 课程
  • 面试题
  • 文章
  • 我

更多

  • 资源
  • 社区
  • 关于作者
  • 内容说明

© 2026 CodeRoadMap

津ICP备2026012044号-1·津公网安备12011002026155号·coderoadmap@126.com
Nginx 反向代理入门/课时/负载均衡
RawBlame
课时目录12 节

Nginx 反向代理入门

  1. 01Nginx 是什么
  2. 02安装与 nginx -t
  3. 03配置文件结构
  4. 04静态资源
  5. 05反向代理基础
  6. 06双 upstream 架构
  7. 07HTTPS 与证书
  8. 08安全响应头
  9. 09缓存与性能
  10. 10负载均衡
  11. 11Nginx 与 Ingress
  12. 12综合练习

负载均衡

upstream 多后端、健康检查概念。

30 分钟

负载均衡

这一课你将能做到

  1. 在 upstream 中声明多个 server,并说明默认轮询、least_conn、ip_hash、权重各自适合什么
  2. 解释 CodeRoadMap 在 Sa-Token + Redis 会话 下为何通常 不需要 ip_hash
  3. 分清开源 Nginx 的 被动 max_fails/fail_timeout 与 K8s readiness 主动探针的差异

为什么要学

单机双进程够入门;流量上来要水平扩展。Nginx 的 upstream 多后端是最直观入口:改配置即可把请求洒到多台 Spring 或多台 Next。
选错策略会把有状态请求打飞(若会话粘在单机内存),或把慢实例打满。
本课建立「无状态 API + 共享会话」心智,并连到后续 Ingress/集群健康检查。

先建立图像

                 Nginx
                   │
         ┌─────────┼─────────┐
         ▼         ▼         ▼
     backend-1 backend-2 backend-3
      :8080     :8080     :8080
         │         │         │
         └─────────┴─────────┘
                   │
              Redis 会话 / MySQL
策略行为典型场景
默认轮询依次分发无状态 REST
least_conn最少活跃连接慢请求、长连接多
ip_hash同 IP 粘滞简易会话粘滞(次优)
weight按权重比例机器规格不均

人话:负载均衡是「多个柜台办理同一业务」;会话放 Redis,就像「叫号系统在云端」,换柜台也不丢号。

跟着做

步骤 1:读官方 upstream

打开 ngx_http_upstream_module,浏览 server 参数:weight、max_fails、fail_timeout、down 等。

步骤 2:写多实例 backend 草稿

upstream coderoadmap_backend {
    least_conn;
    # weight:大机器多接;max_fails/fail_timeout:被动摘除
    server 10.0.1.11:8080 weight=3 max_fails=3 fail_timeout=30s;
    server 10.0.1.12:8080 weight=1 max_fails=3 fail_timeout=30s;
    keepalive 32;
}

location /api/ {
    proxy_pass http://coderoadmap_backend/;
    proxy_http_version 1.1;
    proxy_set_header Connection "";
    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;
}

笔记:「当前生产可仍是单 127.0.0.1:8080;扩展时只改 upstream。」

步骤 3:platform 水平扩展注意点

upstream coderoadmap_platform {
    server 10.0.1.21:3000;
    server 10.0.1.22:3000;
    keepalive 64;
}

要求:

  • 各实例 同一构建版本(RSC/chunk hash 一致)
  • 无依赖单机内存的会话(或会话外置)
  • 静态资源路径一致

步骤 4:为何优先 Redis 而非 ip_hash

Spring 多实例 + Sa-Token Redis 时,任意节点可校验 token,不必把同一用户钉死在一台机。
ip_hash 的问题:NAT 出口大、换 IP、不均。
结论:本站推荐 无状态应用 + 共享会话存储。

步骤 5:健康检查现实

开源 Nginx:没有企业版那种主动 HTTP 健康检查;主要靠请求失败计数被动标记。
生产常见补位:

  • K8s readiness/liveness(kubernetes-essentials)
  • 外部探针 + 把坏节点 down
  • Nginx Plus / 第三方模块
# 探的是 Nginx 自己是否活着,不是 upstream 成员
location = /nginx-health {
    access_log off;
    default_type text/plain;
    return 200 "ok\n";
}

步骤 6:Compose scale 思维实验

docker compose up -d --scale backend=3

DNS 可能返回多 A 记录;裸机 Nginx 常 显式列出 各容器 IP,或使用支持 resolve 的方案。先理解「列表里每一行是一个后端」,再上动态发现。

步骤 7:把「无状态」写成上线条件

扩展 backend 前,对照清单打勾:

  1. 会话在 Redis(或等价共享存储),不是单机内存 Dao
  2. 上传/临时文件不落在单实例本地磁盘当唯一真相
  3. 定时任务有分布式锁或只在一个角色实例跑
  4. 配置与密钥通过环境变量/配置中心注入,各节点一致

缺任何一条就先补齐,再改 upstream 加机器——否则负载均衡只是把故障放大到更多节点。

步骤 8:观察与回滚

加完第二台 backend 后:

# 连续请求,观察 access 或应用日志是否落到不同实例(需在应用日志打 hostname)
for i in 1 2 3 4 5 6; do curl -sS -o /dev/null -w "%{http_code}\n" https://test.example/api/tracks; done

若新节点异常:先在 upstream 对该 server 加 down;,nginx -t 后 reload,流量回到健康节点;修好后再去掉 down。
这比「整台 Nginx restart」更可控,也是多后端运维的基本动作。

讲清楚要点

  1. 因为 upstream 可列多个 server,所以水平扩展入口往往只改这一块——location 语义不变。
  2. 因为默认轮询假设实例同质,所以机型不均时用 weight——大机器多接。
  3. 因为会话进 Redis,所以多 Spring 实例通常不需要 ip_hash——避免粘滞副作用。
  4. 因为开源版偏被动失败检测,所以关键服务要有外层健康机制——K8s 或运维探针。
  5. 因为 Next 多实例要共享同一构建,所以发布需同步滚动——避免 chunk 对不上。
  6. 因为 keepalive 与多后端同时存在,所以池大小要按总连接估算——别只抄数字。
  7. 因为官方策略指令有限但够用,所以先轮询/least_conn,再谈复杂一致性哈希——够用即止。

你可能会懵的地方

  • max_fails 失败是什么失败?
    与上游通信失败(连不上、超时等)会累计;应用返回 500 不一定算进(取决于版本与配置)。不要把它当成完整业务健康检查。

  • 能不能一半流量去新版本?
    可用 weight 做简易金丝雀;更细的灰度常在网关/Ingress/服务网格层做。

  • ip_hash 和 sticky cookie?
    开源 Nginx 的会话粘滞能力有限;共享会话存储仍是本站首选。

  • 一个 upstream 挂了会怎样?
    被动摘除后流量打到剩余节点;若全挂,客户端看到 502。监控与容量规划要提前。

  • weight 与 least_conn 能一起用吗?
    可以组合使用,但推理成本上升。入门阶段:机器同质用默认轮询或 least_conn;规格差异明显再用 weight。先保证会话外置与健康检查,再微调比例。

错法对照

错法问题正解
多实例仍用内存会话登录随机失效Sa-Token Redis 等共享会话
滥用 ip_hash 当银弹不均、NAT 问题无状态 + Redis
只扩容不监控坏节点仍接流外层健康检查 + 告警
platform 版本不一致前端资源错乱同步发布同一构建
把 /nginx-health 当 upstream 探针测错对象健康检查打到应用 readiness
新节点异常却不标记 down部分用户持续 502临时 down + reload,修好再摘
有本地上传目录当权威存储文件随机 404对象存储或共享卷 + 无状态节点

自测三问

  1. 默认轮询与 least_conn 各自适合什么?
  2. 为什么 CodeRoadMap 优先 Redis 会话而不是 ip_hash?
  3. 开源 Nginx 的 max_fails 与 K8s readiness 差在哪里?

小结一句话

upstream 多 server 即水平扩展入口;会话靠 Redis,健康检查交给 K8s 或运维,而不是神话 ip_hash。

官方延伸

  • ngx_http_upstream_module
  • Load Balancing(概念补充,注意与开源功能边界)
加载本节练习…
← 上一课缓存与性能下一课 →Nginx 与 Ingress