Java 项目实战: 外卖平台优化-Nginx六种负载均衡策略对比与选型

接入 Nginx: 六种负载均衡策略原理与选型

纲要

Nginx 提供的负载均衡策略,把六种策略逐个拆开:

  • 轮询(默认):严格交替,无状态
  • weight 权重:按比例分发,适配异构机器
  • ip_hash :按客户端 IP 哈希,实现会话保持
  • least_conn:按最少连接数,适配长耗时请求
  • url_hash :按请求 URL 哈希,提升缓存命中率
  • fair:按响应时间,需第三方模块

#mermaid-svg-Ormz5cNuoAJeMOq9{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-Ormz5cNuoAJeMOq9 .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-Ormz5cNuoAJeMOq9 .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-Ormz5cNuoAJeMOq9 .error-icon{fill:#552222;}#mermaid-svg-Ormz5cNuoAJeMOq9 .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-Ormz5cNuoAJeMOq9 .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-Ormz5cNuoAJeMOq9 .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-Ormz5cNuoAJeMOq9 .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-Ormz5cNuoAJeMOq9 .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-Ormz5cNuoAJeMOq9 .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-Ormz5cNuoAJeMOq9 .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-Ormz5cNuoAJeMOq9 .marker{fill:#333333;stroke:#333333;}#mermaid-svg-Ormz5cNuoAJeMOq9 .marker.cross{stroke:#333333;}#mermaid-svg-Ormz5cNuoAJeMOq9 svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-Ormz5cNuoAJeMOq9 p{margin:0;}#mermaid-svg-Ormz5cNuoAJeMOq9 .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-Ormz5cNuoAJeMOq9 .cluster-label text{fill:#333;}#mermaid-svg-Ormz5cNuoAJeMOq9 .cluster-label span{color:#333;}#mermaid-svg-Ormz5cNuoAJeMOq9 .cluster-label span p{background-color:transparent;}#mermaid-svg-Ormz5cNuoAJeMOq9 .label text,#mermaid-svg-Ormz5cNuoAJeMOq9 span{fill:#333;color:#333;}#mermaid-svg-Ormz5cNuoAJeMOq9 .node rect,#mermaid-svg-Ormz5cNuoAJeMOq9 .node circle,#mermaid-svg-Ormz5cNuoAJeMOq9 .node ellipse,#mermaid-svg-Ormz5cNuoAJeMOq9 .node polygon,#mermaid-svg-Ormz5cNuoAJeMOq9 .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-Ormz5cNuoAJeMOq9 .rough-node .label text,#mermaid-svg-Ormz5cNuoAJeMOq9 .node .label text,#mermaid-svg-Ormz5cNuoAJeMOq9 .image-shape .label,#mermaid-svg-Ormz5cNuoAJeMOq9 .icon-shape .label{text-anchor:middle;}#mermaid-svg-Ormz5cNuoAJeMOq9 .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-Ormz5cNuoAJeMOq9 .rough-node .label,#mermaid-svg-Ormz5cNuoAJeMOq9 .node .label,#mermaid-svg-Ormz5cNuoAJeMOq9 .image-shape .label,#mermaid-svg-Ormz5cNuoAJeMOq9 .icon-shape .label{text-align:center;}#mermaid-svg-Ormz5cNuoAJeMOq9 .node.clickable{cursor:pointer;}#mermaid-svg-Ormz5cNuoAJeMOq9 .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-Ormz5cNuoAJeMOq9 .arrowheadPath{fill:#333333;}#mermaid-svg-Ormz5cNuoAJeMOq9 .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-Ormz5cNuoAJeMOq9 .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-Ormz5cNuoAJeMOq9 .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-Ormz5cNuoAJeMOq9 .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-Ormz5cNuoAJeMOq9 .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-Ormz5cNuoAJeMOq9 .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-Ormz5cNuoAJeMOq9 .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-Ormz5cNuoAJeMOq9 .cluster text{fill:#333;}#mermaid-svg-Ormz5cNuoAJeMOq9 .cluster span{color:#333;}#mermaid-svg-Ormz5cNuoAJeMOq9 div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-Ormz5cNuoAJeMOq9 .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-Ormz5cNuoAJeMOq9 rect.text{fill:none;stroke-width:0;}#mermaid-svg-Ormz5cNuoAJeMOq9 .icon-shape,#mermaid-svg-Ormz5cNuoAJeMOq9 .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-Ormz5cNuoAJeMOq9 .icon-shape p,#mermaid-svg-Ormz5cNuoAJeMOq9 .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-Ormz5cNuoAJeMOq9 .icon-shape .label rect,#mermaid-svg-Ormz5cNuoAJeMOq9 .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-Ormz5cNuoAJeMOq9 .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-Ormz5cNuoAJeMOq9 .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-Ormz5cNuoAJeMOq9 :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 否
是
是
能
不能
否
是
否
是
否
选择负载均衡策略
后端机器性能是否一致?
weight 权重
是否需要会话保持?
能否外置 Session?
Redis 共享 Session

  • 任意策略
    ip_hash
    请求耗时是否差异大?
    least_conn / fair
    是否需要缓存亲和?
    url_hash
    轮询(默认)

一、策略总览

策略 配置写法 特点 是否内置
轮询 默认,不写 依次分发,严格交替 ✓
weight server ... weight=10; 权重越大概率越高 ✓
ip_hash ip_hash; 同一 IP 固定到同一台 ✓
least_conn least_conn; 优先给连接数最少的 ✓
url_hash hash $request_uri; 同一 URL 固定到同一台 ✓(hash 指令)
fair fair; 优先给响应最快的 ✗ 第三方模块

二、轮询(Round Robin)

配置

不需要任何配置,写了 upstream 就是轮询:

nginx 复制代码
upstream targetserver {
    server 192.168.138.101:8080;
    server 192.168.138.101:8081;
}

行为

请求按顺序依次分发:

txt 复制代码
请求 1 → 8080
请求 2 → 8081
请求 3 → 8080
请求 4 → 8081
...

第 n 个请求落到第 n % N 台(N 为节点数)。

适用与局限

适用:所有后端机器性能一致、请求处理耗时接近的场景。这是最常见的情况,所以轮询作为默认值是合理的。

局限:它假设"每个请求的代价相同"。如果某些请求是耗时 5 秒的报表导出,某些是 10 毫秒的简单查询,轮询会导致某台机器恰好堆积了多个慢请求,而其他机器空闲。

与 weight 的关系

轮询其实是 weight 都等于 1 的特例。一旦给某个节点配了 weight,实际使用的就是**加权轮询(WRR)**算法。

三、权重(weight)

配置

nginx 复制代码
upstream targetserver {
    server 192.168.138.101:8080 weight=10;
    server 192.168.138.101:8081 weight=5;
}

行为

weight 默认值是 1。上面配置中 10 : 5 = 2 : 1,即 8080 收到的请求数约为 8081 的两倍。

实测刷新:

txt 复制代码
第 1 次:8080
第 2 次:8081
第 3 次:8080
第 4 次:8080
第 5 次:8081
第 6 次:8080

大致是 8080、8080、8081 的节奏。

重要:权重是概率而非严格比例

课程里特别强调了这一点------"它并不是严格的 2:1。当请求数量足够多的时候,它接近 2:1"。

如果只发 2 次请求,完全可能两次都打到 8080,这不代表配置错了。只有请求量足够大(数百、数千次)时,统计比例才会收敛到 2:1。

这是概率算法的共性:单次结果随机,大数定律下才显现规律。验证权重配置时别只看三五次刷新。

算法原理

Nginx 用的是平滑加权轮询 (Smooth Weighted Round-Robin),每轮选出"当前权重"最高的节点,然后将其当前权重减去总权重。这样能保证分发序列均匀分布而不是前几次全给高权重节点。

以 weight=10 与 weight=5 为例,理想序列:

txt 复制代码
A A B A A B A A B ...

而不是:

txt 复制代码
A A A A A A A A A A B B B B B  ← 会导致高权重节点瞬间被打爆

适用场景

后端机器性能不一致时。典型情况:

  • 新老机器混跑(新机器 32C64G,老机器 8C16G)
  • 灰度发布:给新版本 weight=1,稳定后逐步调大
  • 一部分流量需要打到专门的机器

灰度发布的标准操作:

nginx 复制代码
upstream targetserver {
    server 192.168.138.101:8080 weight=9;    # 稳定版,90%
    server 192.168.138.102:8080 weight=1;    # 灰度版,10%
}

观察灰度版无误后,逐步调成 7:3、5:5、0:10,最终全量。这比"一次性全量切换"安全得多。

四、ip_hash

配置

nginx 复制代码
upstream targetserver {
    ip_hash;
    server 192.168.138.101:8080;
    server 192.168.138.101:8081;
}

行为

对客户端 IP 地址计算哈希值,用哈希值对节点数取模,决定打到哪台:

txt 复制代码
hash(client_ip) % N = 目标节点下标

只要客户端 IP 不变,就始终打到同一台服务器。

作用:会话保持

这是 ip_hash 存在的唯一理由------让同一用户的请求固定到同一台,从而复用该机器内存中的 Session。

三个明显缺点

负载倾斜 。如果大量用户来自同一个出口 IP(公司 NAT、校园网、移动基站),会全部打到同一台机器。某运营商用户特别多时,这台机器可能过载而其他机器空闲。

IP 变化导致会话丢失 。用户从 WiFi 切到 4G,IP 变了,哈希结果变了,Session 就丢了。

节点增减导致大规模失效 。节点数 N 变化时,hash(ip) % N 的结果几乎全部改变------从 3 台扩到 4 台,约 75% 的用户会落到新节点,Session 全部失效。这就是为什么**ip_hash 不适合需要频繁扩缩容的场景**。

IPv6 与 CIDR 处理

Nginx 的 ip_hash 对 IPv4 只用前三个字节 (192.168.1.x → 192.168.1)计算,这样同一 C 段的用户会分到同一台。对 IPv6 用全部 16 字节。

与 weight 的兼容性

ip_hash 与 weight 可以同时使用:

nginx 复制代码
upstream targetserver {
    ip_hash;
    server 192.168.138.101:8080 weight=10;
    server 192.168.138.101:8081 weight=5;
}

此时权重影响的是哈希环上的节点分布密度。

但 ip_hash 与 backup 不兼容 ------ip_hash 场景下 backup 会被忽略。

现代建议

ip_hash 是"外置 Session 太麻烦"时代的产物。现在的首选是 Redis 共享 Session 或 JWT (见上一篇第七节),ip_hash 只作为临时过渡。

五、least_conn(最少连接)

配置

nginx 复制代码
upstream targetserver {
    least_conn;
    server 192.168.138.101:8080;
    server 192.168.138.101:8081;
}

行为

统计每个节点当前正在处理的活跃连接数,把新请求发给连接数最少的那台。

解决的问题

轮询假设"每个请求代价相同",least_conn 不假设这一点。它看的是实际负载而非请求计数。

适用场景

请求处理耗时差异大的场景:

  • 同一个接口,有的请求查缓存(10ms),有的查数据库(2s)
  • 长连接、长轮询、WebSocket
  • 大文件上传下载

#mermaid-svg-FHtpOU2WqyYiDpHX{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-FHtpOU2WqyYiDpHX .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-FHtpOU2WqyYiDpHX .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-FHtpOU2WqyYiDpHX .error-icon{fill:#552222;}#mermaid-svg-FHtpOU2WqyYiDpHX .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-FHtpOU2WqyYiDpHX .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-FHtpOU2WqyYiDpHX .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-FHtpOU2WqyYiDpHX .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-FHtpOU2WqyYiDpHX .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-FHtpOU2WqyYiDpHX .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-FHtpOU2WqyYiDpHX .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-FHtpOU2WqyYiDpHX .marker{fill:#333333;stroke:#333333;}#mermaid-svg-FHtpOU2WqyYiDpHX .marker.cross{stroke:#333333;}#mermaid-svg-FHtpOU2WqyYiDpHX svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-FHtpOU2WqyYiDpHX p{margin:0;}#mermaid-svg-FHtpOU2WqyYiDpHX .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-FHtpOU2WqyYiDpHX .cluster-label text{fill:#333;}#mermaid-svg-FHtpOU2WqyYiDpHX .cluster-label span{color:#333;}#mermaid-svg-FHtpOU2WqyYiDpHX .cluster-label span p{background-color:transparent;}#mermaid-svg-FHtpOU2WqyYiDpHX .label text,#mermaid-svg-FHtpOU2WqyYiDpHX span{fill:#333;color:#333;}#mermaid-svg-FHtpOU2WqyYiDpHX .node rect,#mermaid-svg-FHtpOU2WqyYiDpHX .node circle,#mermaid-svg-FHtpOU2WqyYiDpHX .node ellipse,#mermaid-svg-FHtpOU2WqyYiDpHX .node polygon,#mermaid-svg-FHtpOU2WqyYiDpHX .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-FHtpOU2WqyYiDpHX .rough-node .label text,#mermaid-svg-FHtpOU2WqyYiDpHX .node .label text,#mermaid-svg-FHtpOU2WqyYiDpHX .image-shape .label,#mermaid-svg-FHtpOU2WqyYiDpHX .icon-shape .label{text-anchor:middle;}#mermaid-svg-FHtpOU2WqyYiDpHX .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-FHtpOU2WqyYiDpHX .rough-node .label,#mermaid-svg-FHtpOU2WqyYiDpHX .node .label,#mermaid-svg-FHtpOU2WqyYiDpHX .image-shape .label,#mermaid-svg-FHtpOU2WqyYiDpHX .icon-shape .label{text-align:center;}#mermaid-svg-FHtpOU2WqyYiDpHX .node.clickable{cursor:pointer;}#mermaid-svg-FHtpOU2WqyYiDpHX .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-FHtpOU2WqyYiDpHX .arrowheadPath{fill:#333333;}#mermaid-svg-FHtpOU2WqyYiDpHX .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-FHtpOU2WqyYiDpHX .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-FHtpOU2WqyYiDpHX .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-FHtpOU2WqyYiDpHX .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-FHtpOU2WqyYiDpHX .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-FHtpOU2WqyYiDpHX .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-FHtpOU2WqyYiDpHX .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-FHtpOU2WqyYiDpHX .cluster text{fill:#333;}#mermaid-svg-FHtpOU2WqyYiDpHX .cluster span{color:#333;}#mermaid-svg-FHtpOU2WqyYiDpHX div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-FHtpOU2WqyYiDpHX .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-FHtpOU2WqyYiDpHX rect.text{fill:none;stroke-width:0;}#mermaid-svg-FHtpOU2WqyYiDpHX .icon-shape,#mermaid-svg-FHtpOU2WqyYiDpHX .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-FHtpOU2WqyYiDpHX .icon-shape p,#mermaid-svg-FHtpOU2WqyYiDpHX .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-FHtpOU2WqyYiDpHX .icon-shape .label rect,#mermaid-svg-FHtpOU2WqyYiDpHX .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-FHtpOU2WqyYiDpHX .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-FHtpOU2WqyYiDpHX .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-FHtpOU2WqyYiDpHX :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 新请求发给它
Nginx

least_conn
8080

活跃连接 3
8081

活跃连接 12
8082

活跃连接 1

与 weight 配合

nginx 复制代码
upstream targetserver {
    least_conn;
    server 192.168.138.101:8080 weight=2;
    server 192.168.138.101:8081 weight=1;
}

此时比较的不是绝对连接数,而是 连接数 / 权重 的比值,让高权重机器承担相对更多的连接。

局限

连接数不等于真实负载 。一个连接可能在处理耗时 5 秒的报表,也可能空闲等待。least_conn 无法区分。真正的负载指标是 CPU、响应时间------那需要 fair 策略。

六、url_hash

配置

Nginx 内置的是通用的 hash 指令,可以对任意变量哈希:

nginx 复制代码
upstream targetserver {
    hash $request_uri;
    server 192.168.138.101:8080;
    server 192.168.138.101:8081;
}

hash $request_uri 即按请求 URI 哈希,效果等同于 url_hash。

也可以对其他变量哈希:

nginx 复制代码
upstream targetserver {
    hash $request_uri consistent;   # consistent 启用一致性哈希
    server 192.168.138.101:8080;
    server 192.168.138.101:8081;
}

行为

对请求的 URL 计算哈希,相同 URL 的请求固定打到同一台服务器。

作用:提升缓存命中率

这是 url_hash 的核心价值。假设每台后端都有本地缓存(如 Caffeine、本地 Guava Cache):

  • 用轮询:GET /dish/123 第一次到 8080 缓存了,第二次到 8081 又要重新查库
  • 用 url_hash:GET /dish/123 永远到同一台,缓存命中率高

#mermaid-svg-qH9p10EQJFbUmgsU{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-qH9p10EQJFbUmgsU .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-qH9p10EQJFbUmgsU .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-qH9p10EQJFbUmgsU .error-icon{fill:#552222;}#mermaid-svg-qH9p10EQJFbUmgsU .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-qH9p10EQJFbUmgsU .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-qH9p10EQJFbUmgsU .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-qH9p10EQJFbUmgsU .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-qH9p10EQJFbUmgsU .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-qH9p10EQJFbUmgsU .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-qH9p10EQJFbUmgsU .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-qH9p10EQJFbUmgsU .marker{fill:#333333;stroke:#333333;}#mermaid-svg-qH9p10EQJFbUmgsU .marker.cross{stroke:#333333;}#mermaid-svg-qH9p10EQJFbUmgsU svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-qH9p10EQJFbUmgsU p{margin:0;}#mermaid-svg-qH9p10EQJFbUmgsU .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-qH9p10EQJFbUmgsU .cluster-label text{fill:#333;}#mermaid-svg-qH9p10EQJFbUmgsU .cluster-label span{color:#333;}#mermaid-svg-qH9p10EQJFbUmgsU .cluster-label span p{background-color:transparent;}#mermaid-svg-qH9p10EQJFbUmgsU .label text,#mermaid-svg-qH9p10EQJFbUmgsU span{fill:#333;color:#333;}#mermaid-svg-qH9p10EQJFbUmgsU .node rect,#mermaid-svg-qH9p10EQJFbUmgsU .node circle,#mermaid-svg-qH9p10EQJFbUmgsU .node ellipse,#mermaid-svg-qH9p10EQJFbUmgsU .node polygon,#mermaid-svg-qH9p10EQJFbUmgsU .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-qH9p10EQJFbUmgsU .rough-node .label text,#mermaid-svg-qH9p10EQJFbUmgsU .node .label text,#mermaid-svg-qH9p10EQJFbUmgsU .image-shape .label,#mermaid-svg-qH9p10EQJFbUmgsU .icon-shape .label{text-anchor:middle;}#mermaid-svg-qH9p10EQJFbUmgsU .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-qH9p10EQJFbUmgsU .rough-node .label,#mermaid-svg-qH9p10EQJFbUmgsU .node .label,#mermaid-svg-qH9p10EQJFbUmgsU .image-shape .label,#mermaid-svg-qH9p10EQJFbUmgsU .icon-shape .label{text-align:center;}#mermaid-svg-qH9p10EQJFbUmgsU .node.clickable{cursor:pointer;}#mermaid-svg-qH9p10EQJFbUmgsU .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-qH9p10EQJFbUmgsU .arrowheadPath{fill:#333333;}#mermaid-svg-qH9p10EQJFbUmgsU .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-qH9p10EQJFbUmgsU .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-qH9p10EQJFbUmgsU .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-qH9p10EQJFbUmgsU .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-qH9p10EQJFbUmgsU .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-qH9p10EQJFbUmgsU .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-qH9p10EQJFbUmgsU .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-qH9p10EQJFbUmgsU .cluster text{fill:#333;}#mermaid-svg-qH9p10EQJFbUmgsU .cluster span{color:#333;}#mermaid-svg-qH9p10EQJFbUmgsU div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-qH9p10EQJFbUmgsU .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-qH9p10EQJFbUmgsU rect.text{fill:none;stroke-width:0;}#mermaid-svg-qH9p10EQJFbUmgsU .icon-shape,#mermaid-svg-qH9p10EQJFbUmgsU .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-qH9p10EQJFbUmgsU .icon-shape p,#mermaid-svg-qH9p10EQJFbUmgsU .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-qH9p10EQJFbUmgsU .icon-shape .label rect,#mermaid-svg-qH9p10EQJFbUmgsU .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-qH9p10EQJFbUmgsU .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-qH9p10EQJFbUmgsU .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-qH9p10EQJFbUmgsU :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 轮询
/dish/123
8080

缓存未命中,查库
/dish/123
8081

缓存未命中,查库
/dish/123
8080

缓存命中
#mermaid-svg-sRdzdcWLzhuSWmYm{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-sRdzdcWLzhuSWmYm .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-sRdzdcWLzhuSWmYm .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-sRdzdcWLzhuSWmYm .error-icon{fill:#552222;}#mermaid-svg-sRdzdcWLzhuSWmYm .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-sRdzdcWLzhuSWmYm .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-sRdzdcWLzhuSWmYm .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-sRdzdcWLzhuSWmYm .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-sRdzdcWLzhuSWmYm .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-sRdzdcWLzhuSWmYm .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-sRdzdcWLzhuSWmYm .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-sRdzdcWLzhuSWmYm .marker{fill:#333333;stroke:#333333;}#mermaid-svg-sRdzdcWLzhuSWmYm .marker.cross{stroke:#333333;}#mermaid-svg-sRdzdcWLzhuSWmYm svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-sRdzdcWLzhuSWmYm p{margin:0;}#mermaid-svg-sRdzdcWLzhuSWmYm .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-sRdzdcWLzhuSWmYm .cluster-label text{fill:#333;}#mermaid-svg-sRdzdcWLzhuSWmYm .cluster-label span{color:#333;}#mermaid-svg-sRdzdcWLzhuSWmYm .cluster-label span p{background-color:transparent;}#mermaid-svg-sRdzdcWLzhuSWmYm .label text,#mermaid-svg-sRdzdcWLzhuSWmYm span{fill:#333;color:#333;}#mermaid-svg-sRdzdcWLzhuSWmYm .node rect,#mermaid-svg-sRdzdcWLzhuSWmYm .node circle,#mermaid-svg-sRdzdcWLzhuSWmYm .node ellipse,#mermaid-svg-sRdzdcWLzhuSWmYm .node polygon,#mermaid-svg-sRdzdcWLzhuSWmYm .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-sRdzdcWLzhuSWmYm .rough-node .label text,#mermaid-svg-sRdzdcWLzhuSWmYm .node .label text,#mermaid-svg-sRdzdcWLzhuSWmYm .image-shape .label,#mermaid-svg-sRdzdcWLzhuSWmYm .icon-shape .label{text-anchor:middle;}#mermaid-svg-sRdzdcWLzhuSWmYm .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-sRdzdcWLzhuSWmYm .rough-node .label,#mermaid-svg-sRdzdcWLzhuSWmYm .node .label,#mermaid-svg-sRdzdcWLzhuSWmYm .image-shape .label,#mermaid-svg-sRdzdcWLzhuSWmYm .icon-shape .label{text-align:center;}#mermaid-svg-sRdzdcWLzhuSWmYm .node.clickable{cursor:pointer;}#mermaid-svg-sRdzdcWLzhuSWmYm .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-sRdzdcWLzhuSWmYm .arrowheadPath{fill:#333333;}#mermaid-svg-sRdzdcWLzhuSWmYm .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-sRdzdcWLzhuSWmYm .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-sRdzdcWLzhuSWmYm .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-sRdzdcWLzhuSWmYm .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-sRdzdcWLzhuSWmYm .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-sRdzdcWLzhuSWmYm .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-sRdzdcWLzhuSWmYm .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-sRdzdcWLzhuSWmYm .cluster text{fill:#333;}#mermaid-svg-sRdzdcWLzhuSWmYm .cluster span{color:#333;}#mermaid-svg-sRdzdcWLzhuSWmYm div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-sRdzdcWLzhuSWmYm .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-sRdzdcWLzhuSWmYm rect.text{fill:none;stroke-width:0;}#mermaid-svg-sRdzdcWLzhuSWmYm .icon-shape,#mermaid-svg-sRdzdcWLzhuSWmYm .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-sRdzdcWLzhuSWmYm .icon-shape p,#mermaid-svg-sRdzdcWLzhuSWmYm .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-sRdzdcWLzhuSWmYm .icon-shape .label rect,#mermaid-svg-sRdzdcWLzhuSWmYm .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-sRdzdcWLzhuSWmYm .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-sRdzdcWLzhuSWmYm .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-sRdzdcWLzhuSWmYm :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} url_hash
/dish/123
8080

缓存未命中,查库
/dish/123
/dish/123
后续全部命中缓存

局限

热点 URL 会造成倾斜 。如果 /index 占了 80% 的流量,负责它的那台机器会过载。

节点增减同样导致大规模失效 ------除非启用 consistent(一致性哈希)。

一致性哈希

hash $request_uri consistent; 开启一致性哈希后,节点增减只影响 1/N 的键,而不是全部。这是分布式缓存的标准方案:

方式 3 台扩到 4 台时受影响的 URL 比例
普通哈希 约 75%
一致性哈希 约 25%

生产上用 hash 时强烈建议加 consistent。

注意

url_hash 与 ip_hash 不能同时使用------二者都是"哈希选节点"策略,语义冲突。

七、fair(响应时间)

配置

nginx 复制代码
upstream targetserver {
    fair;
    server 192.168.138.101:8080;
    server 192.168.138.101:8081;
}

行为

统计每个节点的平均响应时间,优先把请求发给响应最快的那台。

重要:这是第三方模块

fair 不是 Nginx 内置的 ,来自 nginx-upstream-fair 模块。直接用会报:

txt 复制代码
nginx: [emerg] unknown directive "fair"

需要下载模块源码,在编译 Nginx 时加进去:

bash 复制代码
./configure --prefix=/usr/local/nginx --add-module=/usr/local/src/nginx-upstream-fair
make && make install

为什么课程里"不演示"

正是因为它需要额外编译,环境依赖较重。课程只要求"了解即可"。

现代替代方案

现在的生产环境更倾向于用商业版 Nginx Plus 的主动健康检查 ,或者把负载均衡交给服务治理框架 (Spring Cloud LoadBalancer、 Nacos)或 Service Mesh (Istio),它们能基于更丰富的指标(CPU、错误率、延迟分位数)做决策,而不仅仅是响应时间。

八、策略对比与选型

对比总表

策略 依据 会话保持 负载均匀性 节点增减影响 需额外模块
轮询 请求顺序 ✗ 高 无影响 ✗
weight 权重比例 ✗ 中(按权重) 无影响 ✗
ip_hash 客户端 IP ✓ 低(可能倾斜) 大规模失效 ✗
least_conn 活跃连接数 ✗ 高 无影响 ✗
url_hash 请求 URL ✗(URL 亲和) 低(热点倾斜) 大规模失效(consistent 可缓解) ✗
fair 响应时间 ✗ 最高 无影响 ✓

选型决策树

#mermaid-svg-A4FFc4mXFWdSptk1{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-A4FFc4mXFWdSptk1 .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-A4FFc4mXFWdSptk1 .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-A4FFc4mXFWdSptk1 .error-icon{fill:#552222;}#mermaid-svg-A4FFc4mXFWdSptk1 .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-A4FFc4mXFWdSptk1 .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-A4FFc4mXFWdSptk1 .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-A4FFc4mXFWdSptk1 .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-A4FFc4mXFWdSptk1 .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-A4FFc4mXFWdSptk1 .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-A4FFc4mXFWdSptk1 .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-A4FFc4mXFWdSptk1 .marker{fill:#333333;stroke:#333333;}#mermaid-svg-A4FFc4mXFWdSptk1 .marker.cross{stroke:#333333;}#mermaid-svg-A4FFc4mXFWdSptk1 svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-A4FFc4mXFWdSptk1 p{margin:0;}#mermaid-svg-A4FFc4mXFWdSptk1 .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-A4FFc4mXFWdSptk1 .cluster-label text{fill:#333;}#mermaid-svg-A4FFc4mXFWdSptk1 .cluster-label span{color:#333;}#mermaid-svg-A4FFc4mXFWdSptk1 .cluster-label span p{background-color:transparent;}#mermaid-svg-A4FFc4mXFWdSptk1 .label text,#mermaid-svg-A4FFc4mXFWdSptk1 span{fill:#333;color:#333;}#mermaid-svg-A4FFc4mXFWdSptk1 .node rect,#mermaid-svg-A4FFc4mXFWdSptk1 .node circle,#mermaid-svg-A4FFc4mXFWdSptk1 .node ellipse,#mermaid-svg-A4FFc4mXFWdSptk1 .node polygon,#mermaid-svg-A4FFc4mXFWdSptk1 .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-A4FFc4mXFWdSptk1 .rough-node .label text,#mermaid-svg-A4FFc4mXFWdSptk1 .node .label text,#mermaid-svg-A4FFc4mXFWdSptk1 .image-shape .label,#mermaid-svg-A4FFc4mXFWdSptk1 .icon-shape .label{text-anchor:middle;}#mermaid-svg-A4FFc4mXFWdSptk1 .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-A4FFc4mXFWdSptk1 .rough-node .label,#mermaid-svg-A4FFc4mXFWdSptk1 .node .label,#mermaid-svg-A4FFc4mXFWdSptk1 .image-shape .label,#mermaid-svg-A4FFc4mXFWdSptk1 .icon-shape .label{text-align:center;}#mermaid-svg-A4FFc4mXFWdSptk1 .node.clickable{cursor:pointer;}#mermaid-svg-A4FFc4mXFWdSptk1 .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-A4FFc4mXFWdSptk1 .arrowheadPath{fill:#333333;}#mermaid-svg-A4FFc4mXFWdSptk1 .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-A4FFc4mXFWdSptk1 .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-A4FFc4mXFWdSptk1 .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-A4FFc4mXFWdSptk1 .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-A4FFc4mXFWdSptk1 .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-A4FFc4mXFWdSptk1 .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-A4FFc4mXFWdSptk1 .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-A4FFc4mXFWdSptk1 .cluster text{fill:#333;}#mermaid-svg-A4FFc4mXFWdSptk1 .cluster span{color:#333;}#mermaid-svg-A4FFc4mXFWdSptk1 div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-A4FFc4mXFWdSptk1 .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-A4FFc4mXFWdSptk1 rect.text{fill:none;stroke-width:0;}#mermaid-svg-A4FFc4mXFWdSptk1 .icon-shape,#mermaid-svg-A4FFc4mXFWdSptk1 .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-A4FFc4mXFWdSptk1 .icon-shape p,#mermaid-svg-A4FFc4mXFWdSptk1 .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-A4FFc4mXFWdSptk1 .icon-shape .label rect,#mermaid-svg-A4FFc4mXFWdSptk1 .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-A4FFc4mXFWdSptk1 .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-A4FFc4mXFWdSptk1 .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-A4FFc4mXFWdSptk1 :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 否(新老混跑/灰度)
是
是
能
不能(遗留系统)
否
是(报表/长连接)
否
是
否
开始
后端机器性能一致?
weight
需要会话保持?
能否改造成 Redis Session / JWT?
改造后回到轮询

★ 推荐
ip_hash

注意扩容问题
请求耗时差异大?
least_conn
后端有本地缓存?
hash $request_uri consistent
轮询(默认)

外卖平台的推荐配置

结合项目特点(常规 CRUD、耗时较均匀、Session 外置 Redis):

nginx 复制代码
upstream reggie_server {
    # 默认轮询即可,两配置相同的机器
    server 192.168.138.101:8080 weight=1 max_fails=3 fail_timeout=30s;
    server 192.168.138.102:8080 weight=1 max_fails=3 fail_timeout=30s;
}

配合 Session 外置 Redis,不需要 ip_hash,也不需要 least_conn。

如果要做灰度:

nginx 复制代码
upstream reggie_server {
    server 192.168.138.101:8080 weight=9;   # 稳定版
    server 192.168.138.102:8080 weight=1;   # 灰度版
}

九、验证权重策略的正确方法

不要靠手动刷新三五次判断,用脚本统计:

bash 复制代码
#!/bin/bash
# 统计 60 次请求在各节点的分布
URL=http://192.168.138.100:8080/hello

echo "发送 60 次请求,统计分布..."
for i in $(seq 1 60); do
    curl -s ${URL}
    echo ""
done | sort | uniq -c | sort -rn

输出示例(weight=10:5):

txt 复制代码
     40 8080
     20 8081

接近 2:1,说明权重配置生效。

如果只发 3 次就下结论,很可能得到 3:0 或 1:2 这种误导性结果。

API 速览

指令 / 参数 作用 备注
(无) 轮询,默认策略
weight=<n> 权重,默认 1 概率性,需大量请求才显现比例
ip_hash; 按客户端 IP 哈希 会话保持;与 backup 不兼容
least_conn; 按最少活跃连接 适配耗时差异大的场景
hash $request_uri; 按请求 URI 哈希 提升本地缓存命中率
hash $request_uri consistent; 一致性哈希 节点增减只影响 1/N
fair; 按响应时间 第三方模块,需重新编译
zone <name> <size>; 共享内存区,存节点状态 Nginx Plus 动态配置用
curl -s <url> 静默请求 配合循环做分布统计
`sort uniq -c` 统计结果分布

官方文档

总结

六种策略按"决策依据"可分为三类 :无状态计数类(轮询、weight)、哈希亲和类(ip_hash、url_hash)、实时负载类(least_conn、fair)。

默认轮询适用于大多数场景。只要后端机器配置一致、请求耗时接近,轮询就是最均匀也最简单的选择------这也是它作为默认值的原因。

weight 是概率性的,不是严格比例 。10:5 只在大请求量下趋近 2:1,只发两三次请求就下结论会得出错误判断。验证时用循环发几十上百次再统计分布。它的真正价值在于灰度发布------给新版本小权重,逐步放量。

ip_hash 和 url_hash 都有"节点增减导致大规模失效"的致命问题 。hash(ip) % N 在 N 变化时几乎全部重排。用 hash 时务必加 consistent 启用一致性哈希,把影响面从约 75% 降到约 25%。

fair 不是内置指令 ,来自第三方模块,直接用会报 unknown directive "fair",需要下载源码重新编译 Nginx。这也是课程只讲解不演示的原因。

选型的本质是权衡 :要会话保持就得接受负载倾斜和扩容困难;要缓存亲和就得接受热点倾斜;要实时负载就得接受更高的实现复杂度。现代架构的正确方向是把状态外置 (Redis Session / JWT),让后端无状态,从而可以自由使用最简单的轮询策略。

到这里 Nginx 的三大应用(静态资源、反向代理、负载均衡)全部讲完。下一篇进入 day03 的前后端分离开发:先讲开发模式对比、YApi 接口管理平台,再讲 Swagger 的接入与常用注解。

相关推荐
Wang's Blog1 小时前
Java 项目实战: 外卖平台优化-YApi接口管理平台与文档导入导出
java·开发语言·yapi
专业程序开发源1 小时前
django新闻推荐系统70655-计算机课程设计、毕业设计
java·javascript·spring boot·后端·python·django·课程设计
vx_Biye_Design1 小时前
springboot一站式旅游管理平台81037-计算机课程设计、毕业设计
java·vue.js·spring boot·后端·课程设计·express·旅游
写后端的胖头鱼1 小时前
时间复杂度 & 空间复杂度
java·数据结构·算法·时间复杂度·空间复杂度
嵌入式学习菌1 小时前
ESP32 ModbusTCP 分片缓存
java·后端·spring
vx_Biye_Design2 小时前
springboot宠物寄养服务预约与监管系统82684-计算机课程设计、毕业设计
java·vue.js·spring boot·elasticsearch·课程设计·express·宠物
程序员小杰@2 小时前
Spring Boot 常用注解分类速记
java·spring boot·后端
vx_Biye_Design2 小时前
springboot小学生英语学习APP62773-计算机课程设计、毕业设计
java·vue.js·spring boot·后端·python·学习·课程设计
吴声子夜歌2 小时前
Nginx应用与运维——Nginx日志管理
java·运维·nginx