赞
踩
目录
Nginx 的负载均衡 ngx_http_upsteam_module 模块,默认编译安装。upstream 模块只能定义在 http 模块下。格式如下:
- http {
- ....
- upstream <名称> {
- server <地址>:<端口> <非必传参数>;
- }
- ...
- 」
本文将介绍轮询、权重轮询、IP_HASH、动态参数HASH,最小连接数、随机算法 6 种负载均衡算法。本文使用的 Nginx 版本为 nginx/1.22.0 ,所有负载均衡算法默认情况下均可使用,不需要单独引入依赖包。
轮询算法为 Nginx 默认的负载均衡算法。其按照客户端请求顺序逐个分配到不同的后端服务节点。
本次通过本机的 3 个不同的端口作为不同后端服务节点的演示,每个请求我们输出对应的端口号,用于区分哪个节点处理的请求。
upstream 配置信息如下:
- upstream loadBalance {
- server 127.0.0.1:8081;
- server 127.0.0.1:8082;
- server 127.0.0.1:8083;
- }
每次请求由后端节点轮流处理。本次配置 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
权重轮询是在轮询算法的基础上增加了权重信息。可以根据服务器能性能决定权重值大小,性能高的服务器配置更大的权重,用于处理更多的请求。
权重轮算算法配置,在 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;
- }
权重轮询算法主要根据两个参数进行节点选择的判断。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 权重为例:
第一步: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
第一步: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
第一步: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
第一步: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
第一步: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
第一步: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
第一步: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
第一步:current_weight 初始为 3,-2,-1 , 加上 effective_weight 后, 权重为 8,0,0
第二步:选择权重最高(8)的 8081 节点处理请求
第三步:current_weight 减去 total_weight , 得到 0,0,0
因为我们设置的总权重 total_weight 为 8 ,八次请求后, current_weight 又回到了初始值 0 ,完成一个负载循环。
请求 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
处理请求的节点顺序:8081 - 8082 - 8081 - 8081 - 8083 - 8081 - 8082 - 8081,顺序与上一节的图示结果顺序一致。一次循环 8081 处理 5 次请求,8082 处理 2 次请求,8083 处理 1 次请求,与我们设置的权重一致。
将请求来源的客户端 IP 通过哈希算法,得到一个 32 位的整数。使用该整数对 server 节点总数取模,根据取模的结果选择处理请求的后端节点。
Nginx 的 ngx_http_upstream_ip_hash_module、ngx_http_upstream_hash_module 两个模块实现了哈希算法与一致性哈希算法。
请求来源如果为同一个 IP ,则一定被分配到同一个后端服务处理。可以解决 session 一致问题。
ip_hash 配置信息如下:
- upstream loadBalance {
- ip_hash;
- server 127.0.0.1:8081;
- server 127.0.0.1:8082;
- server 127.0.0.1:8083;
- }
- [root@shangliang sbin]# curl localhost
- 8081
- [root@shangliang sbin]# curl localhost
- 8081
- [root@shangliang sbin]# curl localhost
- 8081
- [root@shangliang sbin]# curl localhost
- 8081
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
可以根据不同的请求内容进行哈希的负载算法。例如,针对 uri 地址进行 hash,保证同一个 uri 一定被同一个后端节点处理,可以针对不同的节点进行缓存处理。
以 uri 作为参数进行哈希,对得到的哈希值取模后,分配到不同的处理节点
- upstream loadBalance {
- server 127.0.0.1:8081;
- server 127.0.0.1:8082;
- server 127.0.0.1:8083;
- hash $request_uri;
- }
同样的 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
对于 IP_HASH 算法不对 IP 地址最后一字节处理的问题,可以通过 hash $remote_addr 的方式来实现对整个 IP 的哈希。
正常情况下,TCP 连接数越少,我们可以认为服务器的负载也越小。我们可以通过最小连接数算法,将请求分配到连接数最小的服务器进行处理。如果存在不止一个最小连接的节点,则继续对这些节点进行轮询算法。
- upstream loadBalance {
- server 127.0.0.1:8081;
- server 127.0.0.1:8082;
- server 127.0.0.1:8083;
- least_conn;
- }
因为配置验证的各节点均在同一个服务器,请求为逐个进行请求的,最终结果也是所有节点逐个进行处理。
- [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
与权重轮询算法同时使用。配置示例:
- 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;
- }
节点选择逻辑:
使用当前各节点的并发连接数乘以各节点的权重,使用乘积最小的节点处理请求。当最小乘积为两个节点时,同构轮询方式选择节点。
随机选择一个节点处理请求。
- upstream loadBalance {
- server 127.0.0.1:8081;
- server 127.0.0.1:8082;
- server 127.0.0.1:8083;
- random;
- }
- [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
先通过 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 种算法。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。