在大型网络架构上,负载均衡有多种方式,而负载均衡算法有有很多种,我们今天讲一下负载均衡算法之轮询法和加权轮询。
轮询法(Round Robin)
轮询法基本上是最简单的负载均衡算法,基本思路就是对所有的服务器节点按顺序分配,每个服务器的概率是等同的,这种情况适合于服务器的性能等指标一样的情况。
加权轮询法
在轮询基础上,我们对每个服务器加了权重比利,每个服务器是有高低贵贱之分的,性能强劲的服务器的权重就高一些,性能弱的权重就小一些,下面我们就贴上加权平均的测试算法
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
typedef struct
{
int weight;
char name[2];
}server;
int getsum(int *set, int size)
{
int i = 0;
int res = 0;
for (i = 0; i < size; i++)
res += set[i];
return res;
}
int gcd(int a, int b)
{
int c;
while(b)
{
c = b;
b = a % b;
a = c;
}
return a;
}
int getgcd(int *set, int size)
{
int i = 0;
int res = set[0];
for (i = 1; i < size; i++)
res = gcd(res, set[i]);
return res;
}
int getmax(int *set, int size)
{
int i = 0;
int res = set[0];
for (i = 1; i < size; i++)
{
if (res < set[i]) res = set[i];
}
return res;
}
int lb_wrr__getwrr(server *ss, int size, int gcd, int maxweight, int *i, int *cw)
{
while (1)
{
*i = (*i + 1) % size;
if (*i == 0)
{
*cw = *cw - gcd;
if (*cw <= 0)
{
*cw = maxweight;
if (*cw == 0)
{
return -1;
}
}
}
if (ss[*i].weight >= *cw)
{
return *i;
}
}
}
void wrr(server *ss, int *weights, int size)
{
int i = 0;
int gcd = getgcd(weights, size);
int max = getmax(weights, size);
int sum = getsum(weights, size);
int index = -1;
int curweight = 0;
for (i = 0; i < sum; i++)
{
lb_wrr__getwrr(ss, size, gcd, max, &(index), &(curweight));
printf("%s(%d) ", ss[index].name, ss[index].weight);
}
printf("\n");
return;
}
server *initServers(char **names, int *weights, int size)
{
int i = 0;
server *ss = calloc(size, sizeof(server));
for (i = 0; i < size; i++)
{
ss[i].weight = weights[i];
memcpy(ss[i].name, names[i], 2);
}
return ss;
}
int main()
{
int i = 0;
int weights[] = {1, 1, 5};
char *names[] = {"a", "b", "c"};
int size = sizeof(weights) / sizeof(int);
server *ss = initServers(names, weights, size);
printf("server is ");
for (i = 0; i < size; i++)
{
printf("%s(%d) ", ss[i].name, ss[i].weight);
}
printf("\n");
printf("\nwrr sequence is ");
wrr(ss, weights, size);
return;
}
算法基本思路就是,把服务器按权重展开成一个轮询序列,首先计算所有服务器权重的最大值max(S),以及所有服务器权重的最大公约数gcd(S).
index表示本次请求时选择的服务器索引,初始值-1,current_weight表示当前调度的权值,初始值为max(S).
当请求道来时,从index+1开始轮询服务器数组S,找到其中权重大于current_weight的第一个服务器,并记录服务器索引到学结果序列中。
在轮询服务器数组时,如果到达了数组末尾,从头重新开始搜索,并减少current_weight 以gcd(s)值:current_weight-=gcd(s).如果current_weight等于0,则再重置为max(S).
我们这个算法需要注意的是开始的服务器数组序列需要按权重从小大大排序好,否则最后算出来的服务器序列是不一样的!