1 加权轮询算法背景
轮询算法没有考虑每台服务器的处理能力,实际情况是每台服务器的配置、安装的业务应用等不同,其处理能力会不一样。所以,加权轮询算法的原理就是:根据服务器的不同处理能力,给每个服务器分配不同的权值,使其能接受相应权值数的服务请求。
首先看一个简单的Nginx负载均衡配置。
http {
upstream cluster {
server a weight=1;
server b weight=2;
server c weight=4;
}
...
}
按照上述配置,Nginx每收到7个客户端的请求,会把其中的1个转发给后端a,把其中的2个转发给后端b,把其中的4个转发给后端c。
2 加权轮询算法描述
假设有 N 台实例 S = {S1, S2, …, Sn},配置权重 W = {W1, W2, …, Wn},有效权重 CW = {CW1, CW2, …, CWn}。每个实例 i 除了存在一个配置权重 Wi 外,还存在一个当前有效权重 CWi,且 CWi 初始化为 Wi;指示变量 currentPos 表示当前选择的实例 ID,初始化为 -1;所有实例的配置权重和为 weightSum;
那么,调度算法可以描述为:
- 初始每个实例 i 的 当前有效权重 CWi 为 配置权重 Wi,并求得配置权重和 weightSum;
- 选出 当前有效权重 最大 的实例,将 当前有效权重 CWi 减去所有实例的 权重和 weightSum,且变量 currentPos 指向此位置;
- 将每个实例 i 的 当前有效权重 CWi 都加上 配置权重 Wi;
- 此时变量 currentPos 指向的实例就是需调度的实例;
- 每次调度重复上述步骤 2、3、4;
上述 3 个服务,配置权重和 weightSum 为 7,其调度过程如下:
请求 | 选中前的当前权重 | currentPos | 选中的实例 | 选中后的当前权重 |
---|---|---|---|---|
1 | {4, 2, 1} | 0 | a | {-3, 2, 1} |
2 | {1, 4, 2} | 1 | b | {1, -3, 2} |
3 | {5, -1, 3} | 0 | a | {-2, -1, 3} |
4 | {2, 1, 4} | 2 | c | {2, 1,-3 } |
5 | {6, 3, -2} | 0 | a | {-1, 3, -2} |
6 | {3, 5, -1} | 1 | b | {3, -2, -1} |
7 | {7, 0, 0} | 0 | a | {0, 0, 0} |
生成的序列是{a, b, a, c, a, b, a},发给后端的服务都分散开了,不在连续了。
3 代码实现
#include <iostream>
#include <string>
#include <vector>
#include <numeric>
using namespace std;
typedef struct
{
int weight;
int cur_weight;
string name;
}server;
vector<server> initServers(vector<string>& names, vector<int> weights)
{
int i = 0;
vector<server> ss(weights.size());
for (i = 0; i < weights.size(); i++)
{
ss[i].weight = weights[i];
ss[i].name = names[i];
ss[i].cur_weight = 0;
}
return ss;
}
int getNextServerIndex(vector<server>& ss, int total)
{
int i;
int index = -1;
for (i = 0; i < ss.size(); i++)
{
ss[i].cur_weight += ss[i].weight;
if (index == -1 || ss[index].cur_weight < ss[i].cur_weight)
{
index = i;
}
}
ss[index].cur_weight -= total;
return index;
}
void wrr_nginx(vector<server>&ss, vector<int > weights)
{
int i = 0;
int index = -1;
int sum = accumulate(weights.begin(),weights.end(),0);
for (i = 0; i < sum; i++)
{
index = getNextServerIndex(ss, sum);
printf("%s ", ss[index].name.c_str());
}
printf("\n");
}
int main()
{
int i = 0;
vector<int > weights = { 4, 2, 1 };
vector<string > SerVerNames = { "a", "b", "c" };
vector<server> ss = initServers(SerVerNames, weights);
printf("server is : \n ");
for (i = 0; i < ss.size(); i++)
{
printf("server %s weight = %d\n ", ss[i].name.c_str(), ss[i].weight);
}
printf("\n");
printf("\nwrr_nginx sequence is : ");
wrr_nginx(ss, weights);
system("pause");
return 0;
}
来源:CSDN
作者:good-destiny
链接:https://blog.csdn.net/tuwenqi2013/article/details/104703057