Nginx功能篇22—负载规则

概述

本章,您将学习到负载均衡中的负载规则(负载策略、负载算法)。

在 代理服务 文章中提到了负载规则,其主要目的是根据业务场景的不同来分发流量,实现流量的均衡分布。在社区版 Nginx 中,可用的基础负载规则有:

  • 轮询(Round Robin)- 若不指定任何规则,则默认使用该规则
  • 加权轮询(Weighted Round Robin)
  • 最小连接(Least Connections)
  • IP 哈希(IP Hash)
  • 随机(Random)

提示
需要说明的是,反向代理 ≠ 负载均衡。反向代理是七层(应用层)负载均衡的基础,两者不是同一个概念,反向代理关注 "请求与转发",负载均衡关注 "转发给谁(选择后端节点)"。反向代理可以不做负载均衡,比如后端服务器只有一台的情况,此时不存在选择节点的问题。实现负载均衡的效果也不一定非要使用反向代理,现代架构中,专用的工作在第四层(传输层,如 TCP/UDP)的硬件负载均衡设备(如 F5、A10),直接基于 IP + 端口做流量分发,不涉及 HTTP 请求转发,性能极强而且非常昂贵(随便一台中端硬件设备都是十几万起步,高端的都是百万级的价格)。

上游服务器(Upstream Server):指一组后端服务器。当代理服务器拦截到客户端请求后,就会根据负载规则将这些请求转发给这些后端服务器。需要注意的是,在标准的生产环境中,后端服务器的数量通常建议大于等于 3 台(当然这不是强制的,1 台 或 2 台都是被允许的),以保证足够的性能、冗余以及可用性。在主配置文件 nginx.conf 中可通过 upstream 上下文来定义一组后端服务器,需要注意 upstream 上下文只能配置在 http 上下文中。

社区版可用的负载策略

轮询

轮询是分发请求的默认规则,每个请求会按照先后顺序分配到不同的后端服务器上。在‌硬件同构‌的生产环境中,‌轮询‌是最高效、最稳健且资源消耗最低的负载均衡规则。

硬件同构
因为企业购买的服务器都是同一品牌同一批次同一型号的,不存在性能的高低差问题,往专业点的方向说,这就是硬件同构(Homogeneous Hardware)环境。

例如:

...
events {
    ...
}

http {
    ...
    # 定义了名为 backend1 的一组后端服务器(未指定任何负载策略,默认使用轮询)
    upstream backend1 {
        server 192.168.100.30;
        server 192.168.100.35;
        server 192.168.100.40;
    }
    ...
    server {
        ...
        location / {
            ...
        }
    }
}

第一个请求会被 192.168.100.30 后端服务器进行处理,第二个请求会被 192.168.100.35 后端服务器进行处理,第三个请求会被 192.168.100.40 后端服务器进行处理,如此往复循环。

在生产环境下,前面的配置搭配几个关键参数还可提升健壮性:

...
events {
    ...
}

http {
    ...
    # 定义了名为 backend1 的一组后端服务器(未指定任何负载策略,默认使用轮询)
    upstream backend1 {
        server 192.168.100.30 max_fails=3 fail_timeout=60s;
        server 192.168.100.35 max_fails=3 fail_timeout=60s;
        server 192.168.100.40 max_fails=3 fail_timeout=60s;
    }
    ...
    server {
        ...
        location / {
            ...
        }
    }
}

参数说明:

  • max_fails=3 - 在 fail_timeout 参数指定的时间内与后端服务器的通信次数上限,当到达上限次数后,将认为对应的后端服务器处于临时不可用状态且不可用的时间同样由 fail_timeout 参数决定
  • fail_timeout=40s - 在指定的时间内与后端服务器进行通信的次数上限;后端服务器临时不可用的时间

根据 max_fails 和 fail_time 参数设置的不同,您还应该调整与连接相关的指令参数,即:

  • proxy_connect_timeout
  • proxy_send_timeout
  • proxy_read_timeout
  • proxy_next_upstream

比如配置 max_fails=3 和 fail_timeout=60s,则:

proxy_connect_timeout 5s;
proxy_read_timeout 10s;
proxy_send_timeout 10s;
proxy_next_upstream error timeout http_502 http_504;
提升
在 upstream 上下文中,默认启用了 TCP Keepalive(从 Nginx 1.29.7 版本开始),即在 upstream 上下文中隐式配置了 keepalive 32 local;

加权轮询

所谓加权轮询,即在轮询的基础之上添加权重参数,适合后端服务器性能不统一的情况(即所谓的硬件异构环境)。权重数字越高,分配的请求量越大。比如后端服务器 A(192.168.100.30)性能最高,配置的权重参数为 4;后端服务器 B(192.168.100.35) 性能次之,配置的权重参数为 2;后端服务器 C (192.168.100.40)性能最差,配置的权重参数为 1。在一个完整的时间范围内,后端服务器 A 会拿到 4 倍于后端服务器 C 的请求量。

在一个完整的时间周期范围内(比如 1 星期),理论上分配的请求量如下表所示:

服务器 IP 地址 权重 请求占比计算 理论上分配请求流量的比例
192.168.100.30 4 4/7 约 57.1%
192.168.100.35 2 2/7 约 28.6%
192.168.100.40 1 1/7 约 14.3%

配置示例如下所示:

...
events {
    ...
}

http {
    ...
    # 定义了名为 backend1 的一组后端服务器
    upstream backend1 {
        # 性能最高,权重设为 4
        server 192.168.100.30 weight=4 max_fails=3 fail_timeout=60s;

        # 性能次之,权重设为 2
        server 192.168.100.35 weight=2 max_fails=3 fail_timeout=60s;

        # 性能最差,权重设为 1
        server 192.168.100.40 weight=1 max_fails=3 fail_timeout=60s;
    }
    ...
    server {
        ...
        location / {
            ...
        }
    }
}

当需要上线新的后端服务器节点或旧后端服务器节点从故障中恢复时,如果还按照原始的配置分配流量,可能会遭遇流量洪峰的冲击导致实际的业务响应缓慢或崩溃,为了防止这种情况,您还可以根据后端服务器性能的不同差异化配置 slow_start 参数,如:

...
events {
    ...
}

http {
    ...
    # 定义了名为 backend1 的一组后端服务器
    upstream backend1 {
        # 性能最高,权重设为 4,配置慢启动的时间应该最长
        server 192.168.100.30 weight=4 max_fails=3 fail_timeout=60s slow_start=30s;

        # 性能次之,权重设为 2
        server 192.168.100.35 weight=2 max_fails=3 fail_timeout=60s slow_start=20s;

        # 性能最差,权重设为 1,配置慢启动的时间应该最短
        server 192.168.100.40 weight=1 max_fails=3 fail_timeout=60s slow_start=10s;
    }
    ...
    server {
        ...
        location / {
            ...
        }
    }
}

术语说明
流量洪峰:指在短时间内遇到远超日常的突发海量请求,瞬间突破服务器能处理的阈值上限。

参数说明:

  • slow_start=30s - 慢启动时间,即表示在 30 秒内,该后端服务器的权重从 0 逐渐增加到设定值 4,防止流量洪峰的情况出现。需要注意该参数不能与 IP 哈希(IP Hash)、随机(Random)负载策略一起使用。

IP 哈希

IP 哈希:一种基于客户端 IP 地址(IPv4 和 IPv6 都支持)的负载策略,即通过判断客户端的 IP 地址来决定将请求分发给哪个后端服务器。具体原理:

  • IPv4 - 取 IPv4 地址的前 24 bit 做为哈希键参与运算
  • IPv6 - 将整个 128 bit 作为哈希键参与运算

配置示例如下:

...
events {
    ...
}

http {
    ...
    # 定义了名为 backend1 的一组后端服务器
    upstream backend1 {
        ip_hash;

        server 192.168.100.30 max_fails=3 fail_timeout=60s;
        server 192.168.100.35 max_fails=3 fail_timeout=60s;
        server 192.168.100.40 max_fails=3 fail_timeout=60s;
    }
    ...
    server {
        ...
        location / {
            ...
        }
    }
}

指令说明:

  • ip_hash 指令 - 启用 IP 哈希负载规则,只能配置在 upstream 上下文中
提示
在使用 IP 哈希这种负载规则时,应保证后端服务器数量相对稳定,防止因后端服务器数量变动导致哈希值被重新计算,客户端的请求可能会分发到其他的后端服务器上。

最少连接

最少连接:一种负载策略,其核心思想是将新请求分发给当前活跃 TCP 连接数(即已建立但尚未完成响应的连接)最少的后端服务器上。这种负载策略可以有效平衡后端服务器的负载情况:

  • 避免一个或多个后端服务器因请求过多处于过载状态
  • 避免一个或多个后端服务器因请求过少处于空闲状态

启用该负载策略后,可有效提升后端服务器整体的资源利用率与请求效率。

配置示例如下:

...
events {
    ...
}

http {
    ...
    # 定义了名为 backend1 的一组后端服务器
    upstream backend1 {
        least_conn;

        server 192.168.100.30 max_fails=3 fail_timeout=60s;
        server 192.168.100.35 max_fails=3 fail_timeout=60s;
        server 192.168.100.40 max_fails=3 fail_timeout=60s;
    }
    ...
    server {
        ...
        location / {
            ...
        }
    }
}

指令说明:

  • least_conn 指令 - 启用最少连接负载策略

假设:

  • 192.168.100.30 当前有 10 个活跃 TCP 连接
  • 192.168.100.35 当前有 5 个活跃 TCP 连接数
  • 192.168.100.40 当前有 8 个活跃 TCP 连接数

当有新的客户端请求到达 Nginx 代理服务器时,该请求会分发给 192.168.100.35 这台后端服务器上。

随机

随机:一种负载策略,其通过特有的随机函数使请求均匀分发在不同的后端服务器上,特别适用于硬件同构‌的生产环境中。只要请求的数量样本足够多,从统计概率上来说就是均匀分发请求。需要注意的是,早期的一些中文资料或文档提到 Nginx 社区版原生不支持这种负载策略,这是不正确的。

Nginx 社区版的相关指令:

  • 使用 random 指令,语法为 random [two [method]];

    • two 参数 - 指随机选择两台后端服务器
    • method 参数 - 替换为具体的负载策略,社区版只能默认为 least_conn。least_time 为 Nginx 商业版(Nginx Plus)的专属功能

以下的配置都可以被接受:

  • random; - 不书写参数,则随机选择一台后端服务器。若后端服务器配置了权重参数(weight=Number),则选择一台后端服务器的概率会等于权重比例
  • random two; 或 random two least_conn; - 随机选择两台服务器,然后根据默认的 least_conn 负载策略进一步选择其中一台后端服务器来处理请求

配置示例一:

...
events {
    ...
}

http {
    ...
    # 定义了名为 backend1 的一组后端服务器
    upstream backend1 {
        # 启用随机负载策略
        random;

        server 192.168.100.30 weight=4 max_fails=3 fail_timeout=60s; # 4/7 的概率被选择
        server 192.168.100.35 weight=2 max_fails=3 fail_timeout=60s; # 2/7 的概率被选择
        server 192.168.100.40 weight=1 max_fails=3 fail_timeout=60s; # 1/7 的概率被选择
    }
    ...
    server {
        ...
        location / {
            ...
        }
    }
}

配置示例二:

...
events {
    ...
}

http {
    ...
    # 定义了名为 backend1 的一组后端服务器
    upstream backend1 {
        # 启用随机负载策略
        random two least_conn;

        server 192.168.100.30 max_fails=3 fail_timeout=60s;
        server 192.168.100.35 max_fails=3 fail_timeout=60s;
        server 192.168.100.40 max_fails=3 fail_timeout=60s;
    }
    ...
    server {
        ...
        location / {
            ...
        }
    }
}
Avatar photo

关于 陸風睿

GNU/Linux 从业者、开源爱好者、技术钻研者,撰写文档既是兴趣也是工作内容之一。Q - "281957576";WeChat - "jiulongxiaotianci",Github - https://github.com/jimcat8
用一杯咖啡支持我们,我们的每一篇[文档]都经过实际操作和精心打磨,而不是简单地从网上复制粘贴。期间投入了大量心血,只为能够真正帮助到您。
暂无评论

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇