「云原生 | Nginx」upstream 模块负载均衡算法详解

2 篇文章 0 订阅
2 篇文章 0 订阅

目录

一、简介

二、负载均衡算法

2.1 轮询 Round Robin

2.1.1 配置示例

2.1.2 算法验证

2.2 权重轮询 Weight Round Robin

2.2.1 配置示例

2.2.2 轮询原理

2.2.3 算法验证

2.3 IP_HASH

2.3.1 配置示例

2.3.2 算法验证

2.3.3 注意事项

2.4 动态参数 HASH

2.4.1 配置示例

2.4.2 算法验证

2.4.3 其他参数

2.5 最少连接数

2.5.1 配置示例

2.5.2 算法验证

2.5.3 组合用法

2.6 随机算法

2.6.1 配置示例

2.6.2 算法验证

2.6.3 组合用法

三、总结


一、简介

        Nginx 的负载均衡 ngx_http_upsteam_module 模块,默认编译安装。upstream 模块只能定义在 http 模块下。格式如下:

http {
    ....
    upstream <名称> {
        server <地址>:<端口> <非必传参数>;
    }
    ...
」

二、负载均衡算法

        本文将介绍轮询、权重轮询、IP_HASH、动态参数HASH,最小连接数、随机算法 6 种负载均衡算法。本文使用的 Nginx 版本为 nginx/1.22.0 ,所有负载均衡算法默认情况下均可使用,不需要单独引入依赖包。

2.1 轮询 Round Robin

        轮询算法为 Nginx 默认的负载均衡算法。其按照客户端请求顺序逐个分配到不同的后端服务节点。

2.1.1 配置示例

        本次通过本机的 3 个不同的端口作为不同后端服务节点的演示,每个请求我们输出对应的端口号,用于区分哪个节点处理的请求。

upstream 配置信息如下:

upstream loadBalance {
    server 127.0.0.1:8081;
    server 127.0.0.1:8082;
    server 127.0.0.1:8083;
}

2.1.2 算法验证

        每次请求由后端节点轮流处理。本次配置 3 个后端服务节点,所以每三次请求为一个循环。

[root@shangliang sbin]# curl localhost
8081
[root@shangliang sbin]# curl localhost
8082
[root@shangliang sbin]# curl localhost
8083
[root@shangliang sbin]# curl localhost
8081
[root@shangliang sbin]# curl localhost
8082
[root@shangliang sbin]# curl localhost
8083

2.2 权重轮询 Weight Round Robin

        权重轮询是在轮询算法的基础上增加了权重信息。可以根据服务器能性能决定权重值大小,性能高的服务器配置更大的权重,用于处理更多的请求。

2.2.1 配置示例

        权重轮算算法配置,在 server <地址>:<端口>; 配置的基础上增加了权重参数 weight = 权重值

        8081 节点权重为 5 ,8082 节点权重为 2, 8083 节点权重为 1

upstream loadBalance {
    server 127.0.0.1:8081 weight=5;
    server 127.0.0.1:8082 weight=2;
    server 127.0.0.1:8083 weight=1;
}

2.2.2 轮询原理

        权重轮询算法主要根据两个参数进行节点选择的判断。current_weight , effective_weight, total_weight

        current_weight 是一个动态的值,初始为 0 ;

        effective_weight 为我们给每个节点设置的权重 weight;

        total_weight 为我们设置的每个节点的权重和。

节点选取原理

第一步:每节点的初始 current_weight 加上各节点的 effective_weight,作为当前 current_weight

第二步:根据 current_weight 每节点的权重,选择权重最大的节点处理请求

第三步:将第二步选择处理请求节点的 current_weight 减去 total_weight

第四步:将三步的结果 current_weight,作为下次请求的初始 current_weight

以我们配置的三个节点 5,2,1 权重为例:

第一次请求
第一次请求 8081 节点处理

第一步:current_weight 初始为 0,0,0 , 加上 effective_weight 后, 权重为 5,2,1

第二步:选择权重最高(5)的 8081 节点处理请求

第三步:current_weight 减去 total_weight , 得到 -3,2,1

第四步:current_weight -3,2,1 作为下次请求的初始 current_weight 

第二次请求
第二次请求 8082 节点处理

第一步:current_weight 初始为 -3,2,1 , 加上 effective_weight 后, 权重为 2,4,2

第二步:选择权重最高(4)的 8082 节点处理请求

第三步:current_weight 减去 total_weight , 得到 2,-4,1

第四步:current_weight 2,-4,1 作为下次请求的初始 current_weight 

第三次请求
第三次请求 8081 节点处理

 第一步:current_weight 初始为 2,-4,1 , 加上 effective_weight 后, 权重为 7,-2,3

第二步:选择权重最高(7)的 8081 节点处理请求

第三步:current_weight 减去 total_weight , 得到 -1,-2,3

第四步:current_weight -1,-2,3 作为下次请求的初始 current_weight 

第四次请求
第四次请求 8081 节点处理

第一步:current_weight 初始为 -1,-2,3 , 加上 effective_weight 后, 权重为 4,0,4

第二步:选择权重最高(4)的 8081 节点处理请求

第三步:current_weight 减去 total_weight , 得到 -4,0,4

第四步:current_weight -4,0,4 作为下次请求的初始 current_weight 

第五次请求
第五次请求 8083 节点处理

第一步:current_weight 初始为 -4,0,4 , 加上 effective_weight 后, 权重为 1,2,5

第二步:选择权重最高(5)的 8083 节点处理请求

第三步:current_weight 减去 total_weight , 得到 1,2,-3

第四步:current_weight 1,2,-3 作为下次请求的初始 current_weight 

第六次请求
第六次请求 8081 节点处理

第一步:current_weight 初始为 1,2,-3 , 加上 effective_weight 后, 权重为 6,4,-2

第二步:选择权重最高(6)的 8081 节点处理请求

第三步:current_weight 减去 total_weight , 得到 -2,4,-2

第四步:current_weight -2,4,-2 作为下次请求的初始 current_weight 

第七次请求
第七次请求 8082 节点处理

第一步:current_weight 初始为 -2,4,-2 , 加上 effective_weight 后, 权重为 3,6,-1

第二步:选择权重最高(6)的 8082 节点处理请求

第三步:current_weight 减去 total_weight , 得到 3,-2,-1

第四步:current_weight 3,-2,-1 作为下次请求的初始 current_weight 

第八次请求 8081 节点处理
第八次请求 8081 节点处理

 第一步:current_weight 初始为 3,-2,-1 , 加上 effective_weight 后, 权重为 8,0,0

第二步:选择权重最高(8)的 8081 节点处理请求

第三步:current_weight 减去 total_weight , 得到 0,0,0

因为我们设置的总权重 total_weight8 ,八次请求后, current_weight 又回到了初始值 0 ,完成一个负载循环。

2.2.3 算法验证

请求 8 次服务,分析返回情况。

[root@shangliang sbin]# curl localhost
8081
[root@shangliang sbin]# curl localhost
8082
[root@shangliang sbin]# curl localhost
8081
[root@shangliang sbin]# curl localhost
8081
[root@shangliang sbin]# curl localhost
8083
[root@shangliang sbin]# curl localhost
8081
[root@shangliang sbin]# curl localhost
8082
[root@shangliang sbin]# curl localhost
8081

处理请求的节点顺序:80818082 - 8081 - 8081 - 8083 - 8081 - 8082 - 8081,顺序与上一节的图示结果顺序一致。一次循环 8081 处理  5 次请求,8082 处理 2 次请求,8083 处理 1 次请求,与我们设置的权重一致。

2.3 IP_HASH

        将请求来源的客户端 IP 通过哈希算法,得到一个 32 位的整数。使用该整数对 server 节点总数取模,根据取模的结果选择处理请求的后端节点。

        Nginx 的 ngx_http_upstream_ip_hash_modulengx_http_upstream_hash_module 两个模块实现了哈希算法与一致性哈希算法。

        请求来源如果为同一个 IP ,则一定被分配到同一个后端服务处理。可以解决 session 一致问题。

2.3.1 配置示例

        ip_hash 配置信息如下:

upstream loadBalance {
    ip_hash;
    server 127.0.0.1:8081;
    server 127.0.0.1:8082;
    server 127.0.0.1:8083;
}

2.3.2 算法验证

[root@shangliang sbin]# curl localhost
8081
[root@shangliang sbin]# curl localhost
8081
[root@shangliang sbin]# curl localhost
8081
[root@shangliang sbin]# curl localhost
8081

2.3.3 注意事项

ip_hash 算法,针对 IPv4 和 IPv6 是两套不同的处理逻辑

IPv4:计算 hash 值的时候,会忽略最后一个字节。如 IP 地址格式为 A.B.C.D , 则 A.B.C.1 ~ A.B.C.255 IP 段通过 hash 算法会的到同一个 hash 值。

IPv6:使用全部 16 个字节进行 hash

2.4 动态参数 HASH

       可以根据不同的请求内容进行哈希的负载算法。例如,针对 uri 地址进行 hash,保证同一个 uri 一定被同一个后端节点处理,可以针对不同的节点进行缓存处理。

2.4.1 配置示例

        以 uri 作为参数进行哈希,对得到的哈希值取模后,分配到不同的处理节点

upstream loadBalance {    
    server 127.0.0.1:8081;
    server 127.0.0.1:8082;
    server 127.0.0.1:8083;
    hash $request_uri;
}

2.4.2 算法验证

同样的 uri ,处理请求的后端节点为同一个。

[root@shangliang sbin]# curl localhost/y
8081
[root@shangliang sbin]# curl localhost/z
8082
[root@shangliang sbin]# curl localhost/6
8083
[root@shangliang sbin]# curl localhost/8
8083
[root@shangliang sbin]# curl localhost/1
8081
[root@shangliang sbin]# curl localhost/1
8081
[root@shangliang sbin]# curl localhost/8
8083

2.4.3 其他参数

        对于 IP_HASH 算法不对 IP 地址最后一字节处理的问题,可以通过 hash $remote_addr 的方式来实现对整个 IP 的哈希。

2.5 最少连接数

        正常情况下,TCP 连接数越少,我们可以认为服务器的负载也越小。我们可以通过最小连接数算法,将请求分配到连接数最小的服务器进行处理。如果存在不止一个最小连接的节点,则继续对这些节点进行轮询算法。

2.5.1 配置示例

 upstream loadBalance {
    server 127.0.0.1:8081;
    server 127.0.0.1:8082;
    server 127.0.0.1:8083;
    least_conn;
}

2.5.2 算法验证

因为配置验证的各节点均在同一个服务器,请求为逐个进行请求的,最终结果也是所有节点逐个进行处理。

[root@shangliang sbin]# curl localhost
8081
[root@shangliang sbin]# curl localhost
8082
[root@shangliang sbin]# curl localhost
8083
[root@shangliang sbin]# curl localhost
8081
[root@shangliang sbin]# curl localhost
8082
[root@shangliang sbin]# curl localhost
8083

2.5.3 组合用法

与权重轮询算法同时使用。配置示例:

 upstream loadBalance {
    server 127.0.0.1:8081 weight=5;
    server 127.0.0.1:8082 weight=2;
    server 127.0.0.1:8083 weight=1;
    least_conn;
}

节点选择逻辑:

使用当前各节点的并发连接数乘以各节点的权重,使用乘积最小的节点处理请求。当最小乘积为两个节点时,同构轮询方式选择节点。

2.6 随机算法

        随机选择一个节点处理请求。

2.6.1 配置示例

 upstream loadBalance {
    server 127.0.0.1:8081;
    server 127.0.0.1:8082;
    server 127.0.0.1:8083;
    random;
}

2.6.2 算法验证

[root@shangliang sbin]# curl localhost
8083
[root@shangliang sbin]# curl localhost
8081
[root@shangliang sbin]# curl localhost
8083
[root@shangliang sbin]# curl localhost
8083
[root@shangliang sbin]# curl localhost
8083
[root@shangliang sbin]# curl localhost
8083
[root@shangliang sbin]# curl localhost
8083
[root@shangliang sbin]# curl localhost
8081
[root@shangliang sbin]# curl localhost
8082

2.6.3 组合用法

        先通过 random 算法选取 2 个节点,再根据了轮询算法或加权轮询算法从选取的 2 个节点里面选择并发连接数最少的那个节点来处理请求。

配置示例

 upstream loadBalance {
    server 127.0.0.1:8081;
    server 127.0.0.1:8082;
    server 127.0.0.1:8083;
    random two least_conn;
}
 upstream loadBalance {
    server 127.0.0.1:8081 weight=5;
    server 127.0.0.1:8082 weight=2;
    server 127.0.0.1:8083 weight=1;
    random two least_conn;
}

三、总结

本文介绍了 6 中负载均衡算法。其中 轮询、权重轮询、最少连接数、随机选择这 4 个算法,仅当服务为无差别服务时可使用。当服务只处理特定范围的请求时,可以使用 ip_hash、动态参数HASH 这 2 种算法。 

  • 8
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值