一、简介 Nginx 的负载均衡 ngx_http_upsteam_module 模块,默认编译安装。upstream 模块只能定义在 http 模块下。格式如下: http { .... upstream 名称 { server 地址:端口 非必传参数; } ... } 二、负载
一、简介
Nginx 的负载均衡 ngx_http_upsteam_module 模块,默认编译安装。upstream 模块只能定义在 http 模块下。格式如下:http {
....
upstream <名称> {
server <地址>:<端口> <非必传参数>;
}
...
}
二、负载均衡算法
本文将介绍轮询、权重轮询、IP_HASH、动态参数HASH,最小连接数、随机算法 6 种负载均衡算法。
1、轮询 Round Robin
轮询算法为 Nginx 默认的负载均衡算法。其按照客户端请求顺序逐个分配到不同的后端服务节点。upstream loadBalance {
server 127.0.0.1:8081;
server 127.0.0.1:8082;
server 127.0.0.1:8083;
}
每次请求由后端节点轮流处理。本次配置 3 个后端服务节点,所以每三次请求为一个循环。
2、权重轮询 Weight Round Robin
权重轮算算法配置,在 server <地址>:<端口>; 配置的基础上增加了权重参数 weight = 权重值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第一步: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,2
第四步:current_weight 2,-4,2 作为下次请求的初始 current_weight第一步:current_weight 初始为 2,-4,2 , 加上 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 ,完成一个负载循环。
3、IP_HASH
将请求来源的客户端 IP 通过哈希算法,得到一个 32 位的整数。使用该整数对 server 节点总数取模,根据取模的结果选择处理请求的后端节点。Nginx 的 ngx_http_upstream_ip_hash_module、ngx_http_upstream_hash_module 两个模块实现了哈希算法与一致性哈希算法。
请求来源如果为同一个 IP ,则一定被分配到同一个后端服务处理。可以解决 session 一致问题。
upstream loadBalance {
ip_hash;
server 127.0.0.1:8081;
server 127.0.0.1:8082;
server 127.0.0.1:8083;
}
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
4、动态参数 HASH
可以根据不同的请求内容进行哈希的负载算法。例如,针对 uri 地址进行 hash,保证同一个 uri 一定被同一个后端节点处理,可以针对不同的节点进行缓存处理。
upstream loadBalance {
server 127.0.0.1:8081;
server 127.0.0.1:8082;
server 127.0.0.1:8083;
hash $request_uri;
}
对于 IP_HASH 算法不对 IP 地址最后一字节处理的问题,可以通过 hash $remote_addr 的方式来实现对整个 IP 的哈希。
5、最少连接数
正常情况下,TCP 连接数越少,我们可以认为服务器的负载也越小。我们可以通过最小连接数算法,将请求分配到连接数最小的服务器进行处理。如果存在不止一个最小连接的节点,则继续对这些节点进行轮询算法。
upstream loadBalance {
server 127.0.0.1:8081;
server 127.0.0.1:8082;
server 127.0.0.1:8083;
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;
least_conn;
}
节点选择逻辑:
使用当前各节点的并发连接数乘以各节点的权重,使用乘积最小的节点处理请求。当最小乘积为两个节点时,同构轮询方式选择节点。
6、随机算法
随机选择一个节点处理请求。upstream loadBalance {
server 127.0.0.1:8081;
server 127.0.0.1:8082;
server 127.0.0.1:8083;
random;
}
先通过 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;
}
三、总结
本文介绍了 6 中负载均衡算法。其中 轮询、权重轮询、最少连接数、随机选择这 4 个算法,仅当服务为无差别服务时可使用。当服务只处理特定范围的请求时,可以使用 ip_hash、动态参数HASH 这 2 种算法。