Akvicor
Akvicor
发布于 2026-09-19 / 3 阅读
0
0

Nginx 负载均衡模块

项目仓库: https://github.com/gnosek/nginx-upstream-fair

已编译源: https://deb.ksyaki.com/nginx/

Nginx 内置的 upstream 负载均衡可以解决“把请求分给哪些后端”的问题,但默认策略对后端当前忙闲程度的感知有限。round robin 主要按顺序分配,权重只改变分配比例;当某个后端已经积压较多请求时,它仍可能继续收到新请求。

nginx-upstream-fair 用来解决这个问题。它会跟踪每个 upstream peer 当前正在处理的请求数量,并优先把新请求分配给更空闲的后端。当前维护版本基于 Debian libnginx-mod-http-upstream-fair,并应用了动态模块、OpenSSL 1.1+ 和 Nginx 1.11.6+ 兼容补丁。

与上游版本的差异

上游 a18b409 已经包含基础的忙闲调度、no_rrweight_mode 和共享内存配置。当前维护版本在这个基础上继续做了这些改动:

  • 应用 Debian 兼容补丁,支持动态模块、OpenSSL 1.1+ 和 Nginx 1.11.6+。

  • 增加与 nginx-healthcheck-module 的可选联动,可以在选择后端前过滤主动健康检查失败的 peer。

  • 将 peer 和主备分组状态拆分到独立模块,并加强主组、backup 组的调度边界。

  • 修复请求计数和 free 生命周期,避免计数、tried 位图、失败回报或 SSL session 归属到错误的组。

  • 必要计数和选路规则不再依赖 --with-debug,reload 生命周期也改为通过 Nginx 原生配置提交回调发布。

当前维护版本支持

  • 按后端当前忙闲程度分配请求

  • 默认调度、no_rrweight_mode=idleweight_mode=peak

  • 主组和 backup 组调度

  • nginx-healthcheck-module 联动,跳过主动健康检查失败的后端

  • 静态 down、主动 down、被动失败冷却和请求 tried 状态过滤

  • 静态模块和动态模块构建

  • 共享内存计数和安全的 reload 生命周期

编译安装

首先下载 Nginx 源码和模块源码:

git clone https://github.com/nginx/nginx.git
git clone https://github.com/Akvicor/nginx-upstream-fair.git

cd nginx
git checkout release-1.26.3

静态编译

./auto/configure --add-module=../nginx-upstream-fair
make
make install

如果需要动态模块,可以改用:

./auto/configure --add-dynamic-module=../nginx-upstream-fair
make
make install

动态模块还需要在 Nginx 配置中通过 load_module 加载生成的 .so 文件。动态构建只提供 fair-only 功能;如果需要 check 主动健康检查联动,请使用下文与 nginx-healthcheck-module 的共同静态构建方式。

基础配置

最简单的配置只需要在 upstream 中启用 fair

upstream backend {
    fair;
    server 127.0.0.1:5000;
    server 127.0.0.1:5001;
    server 127.0.0.1:5002;
}

server {
    listen 8080;

    location / {
        proxy_pass http://backend;
    }
}

启用后,模块会根据 peer 当前的在用请求数、历史分配情况和权重选择后端。正在处理请求较多的后端会少分到新请求,空闲后端会优先获得新请求。

调度模式

完整指令格式:

fair [no_rr] [weight_mode=idle|weight_mode=peak];

默认模式会综合考虑当前在用请求、请求分配历史和权重。只要存在空闲候选,模块会优先选择空闲候选;没有空闲候选时,其余合格候选继续参与 busy 评分。

no_rr 控制既有轮转游标策略,可以和两种 weight_mode 组合使用。

weight_mode=idle

upstream backend {
    fair weight_mode=idle;
    server 127.0.0.1:5000 weight=1;
    server 127.0.0.1:5001 weight=2;
}

idle 模式在选择空闲后端时,把 weight 作为当前在用请求的参考界限。超过参考界限的节点仍可能进入 busy 选择,不会因为暂时较忙就永久退出调度。配合 no_rr 时,会继续沿用对已轻载节点的既有偏好。

这个模式适合希望尽量让后端保持空闲余量的场景。

weight_mode=peak

upstream backend {
    fair weight_mode=peak;
    server 127.0.0.1:5000 weight=4;
    server 127.0.0.1:5001 weight=8;
    server 127.0.0.1:5002 backup;
}

peak 模式把 weight 当作多节点并发容量上限。主组容量都达到上限时,如果配置了 backup 组,请求可以进入 backup 组。

如果只有一个真实节点且没有 backup,模块保留原有的单节点特例,避免因为容量判断导致唯一后端不可用。

主组和 Backup 组

fair 支持 Nginx upstream 的主备模型:

upstream backend {
    fair;
    server 127.0.0.1:5000 weight=4;
    server 127.0.0.1:5001 weight=4;
    server 127.0.0.1:5002 backup;
}

每个新请求先从主组选择。只有主组没有合格候选时,请求才会进入 backup 组。已经进入 backup 组的请求会按照原生请求生命周期继续在该组重试;主组恢复后,新请求会重新优先进入主组。

配置中至少要有一个主节点。主节点可以配置为静态 down,但如果 upstream 中只有 backup 节点,配置会加载失败。

与主动健康检查联动

fair 本身负责忙闲调度,主动健康检查由 nginx-healthcheck-module 提供。两个模块共同静态编译后,可以在 fair upstream 中配置 check

upstream backend {
    fair;
    server 127.0.0.1:5000 weight=2 max_fails=2 fail_timeout=10s;
    server 127.0.0.1:5001;
    server 127.0.0.1:5002 backup;

    check type=tcp interval=3000 timeout=1000 rise=2 fall=5;
}

共同构建方式:

git clone https://github.com/nginx/nginx.git
git clone https://github.com/Akvicor/nginx-healthcheck-module.git
git clone https://github.com/Akvicor/nginx-upstream-fair.git

cd nginx
git checkout release-1.26.3
git apply ../nginx-healthcheck-module/nginx_healthcheck_for_nginx_1.26+.patch

./auto/configure \
    --with-stream \
    --add-module=../nginx-healthcheck-module \
    --add-module=../nginx-upstream-fair
make

配置了 check 后,显式 upstream 内主组和 backup 组的非静态 down 地址都会注册主动健康检查。主动检查失败的 peer 会在 fair 选择阶段被过滤;主动恢复为 up 后,也仍需要满足 Nginx 被动失败冷却状态,才会重新接收业务请求。

如果配置了检查但注册失败,当前配置会被拒绝加载。这可以避免 Nginx 以“看起来配置了健康检查,但实际没有生效”的状态运行。

状态过滤语义

fair 选择后端时会分别考虑以下状态:

  • 静态 down:配置中明确标记为 down 的 peer 不参与选择。

  • 主动 down:健康检查判定异常的 peer 不参与选择。

  • 被动失败冷却:业务请求失败触发的 Nginx 原生冷却仍然生效。

  • tried:当前请求已经尝试过的 peer 不会在同一个重试周期中重复选择。

这些状态是独立判断的。主动健康检查恢复为 up 只会更新主动健康状态,不会直接清除业务请求造成的被动失败冷却。

共享内存和 Reload

fair 使用共享内存保存 peer 计数。可以通过下面的指令调整共享区大小:

http {
    upstream_fair_shm_size 8m;
}

该指令位于 http 层级。默认值和最小值都是 8 个系统页,配置值会按页对齐。修改已有共享区大小需要重启 Nginx,而不是只执行 reload。

配置加载失败时,旧配置和原有 worker 会继续工作。加载成功后,新 worker 使用新配置,旧 worker 按 Nginx 原生优雅退出规则完成已有请求。

使用建议

  • 只想按忙闲分配请求时,直接使用默认 fair;

  • 希望 weight 表示空闲参考界限时使用 weight_mode=idle

  • 希望 weight 表示并发容量上限时使用 weight_mode=peak

  • 有 backup 组时,确认主组至少保留一个主节点。

  • 需要主动剔除故障后端时,与 nginx-healthcheck-module 共同静态构建。

  • 修改 upstream_fair_shm_size 后使用完整重启,而不是 reload。

  • 构建后先执行 nginx -t,再用实际 upstream 流量验证调度效果。


评论