1)参考了网络上的算法,但是那个算法仅仅是用于展示“权重轮循”的意图,在真正的网络下,因为是并行的,所以不可能单纯一个简单的循环可以解决问题。

2)用lock的话性能显然有损失。

3)想了一阵,结合CAS和volatile等细粒度的锁的方式,一个真正可以用软件描述SLB带有权重的算法大概是这个样子(如下):

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading; namespace WBasedRobin
{
/// <summary>
/// 用于计算WeightRobin的数据结构
/// </summary>
public class WeightedRobin
{
private readonly int _weight;
private int _count;
/// <summary>
/// 命中次数(累加)
/// </summary>
public int ChoosenCount
{
get
{
return ++_count;
}
}
/// <summary>
/// 权重
/// </summary>
public int Weight
{
get
{
return _weight;
}
}
/// <summary>
/// 输出当前的权重
/// </summary>
public override string ToString()
{
return "Weight:" + Weight.ToString() + "\tCount:" + _count.ToString();
}
/// <summary>
/// 初始化每一个Server的内部值
/// </summary>
public WeightedRobin(int weight, int count = )
{
_weight = weight;
_count = count;
}
} public class WeightRobinRule
{
private List<WeightedRobin> _servers = null; private volatile int _index = -;
private volatile int _currentWeight = ;
private volatile bool _isServerChanging = false; private volatile int _maxWeight = ;
private volatile int _gcdWeight = ; private int GetMaxWeight(IEnumerable<WeightedRobin> weights)
{
return weights.Max(w => w.Weight);
} private int GetGCDWeight(int big, int small)
{
if (big < small)
{
big ^= small;
small ^= big;
big ^= small;
} if (big % small == )
{
return small;
}
return GetGCDWeight(small, big % small);
} private int GetTotalGCD()
{
int gcd = GetGCDWeight(_servers[].Weight, _servers[].Weight); for (int i = ; i < _servers.Count; ++i)
{
gcd = GetGCDWeight(gcd, _servers[i].Weight);
} return gcd;
} /// <summary>
/// 初始化权重服务器,至少2台服务器。
/// </summary>
public WeightRobinRule(int totalServers = )
{
Random r = new Random();
_servers = new List<WeightedRobin>(totalServers); for (int i = ; i < totalServers; i++)
{
_servers.Add(new WeightedRobin(r.Next(, totalServers+),));
}
_maxWeight = GetMaxWeight(_servers);
_gcdWeight = GetTotalGCD();
} public void DoRolling()
{
int copyIndex = ;
int copyIndexNext = ;
int copycw = ; //当服务器数量发生变化的时候,锁住该服务直到完毕。
reloop: while (_isServerChanging) ; for (;;)
{
//拷贝本地的index,用做同步
copyIndex = _index;
//计算轮询的时候下一个的值
copyIndexNext = (copyIndex + ) % _servers.Count;
//同步作用
copycw = _currentWeight; //假定轮询后的Next=0,说明完成一轮轮询,权重减去最大公约数
if (copyIndexNext == )
{
copycw -= _gcdWeight; //如果权重已经扣完,重新从大的开始
if (copycw <= )
{
copycw = _maxWeight;
}
} //如果copyIndex和_index相同,说明是同一个线程抢到的,那么直接用本地的替换index进行替换
if (Interlocked.CompareExchange(ref _index, copyIndexNext, copyIndex) == copyIndex)
{
_currentWeight = copycw; try
{
//如果轮询的权重大于等于本地权重,选中它即可。
if (_servers[copyIndexNext].Weight >= copycw)
{
int t = _servers[copyIndexNext].ChoosenCount;
break;
}
}
//如果是Index溢出,那么说明服务器数量肯定发生变化了,所以跳过此次轮询,等下一轮,不处理。
catch (IndexOutOfRangeException)
{
goto reloop;
} }
}
}
/// <summary>
/// 移除指定的服务器
/// </summary>
public WeightedRobin RemoveByIndex(int index)
{
_isServerChanging = true;
var removedServer = _servers[index];
_servers.RemoveAt(index);
_gcdWeight = GetTotalGCD();
_maxWeight = GetMaxWeight(_servers);
_isServerChanging = false;
return removedServer;
}
/// <summary>
/// 增加新的服务器
/// </summary>
public void AddNewServer(int weight)
{
_isServerChanging = true;
_servers.Add(new WeightedRobin(weight, ));
_gcdWeight = GetTotalGCD();
_maxWeight = GetMaxWeight(_servers);
_isServerChanging = false;
}
/// <summary>
/// 格式化输出结果
/// </summary>
public override string ToString()
{
StringBuilder sbu = new StringBuilder(); foreach (WeightedRobin wr in _servers)
{
sbu.AppendLine(wr.ToString() + Environment.NewLine);
}
return sbu.ToString();
}
}
}

调用测试代码如下:

using System;
using System.Threading;
using System.Threading.Tasks; namespace WBasedRobin
{
class Program
{
static Random r = new Random(); static void Rounding(WeightRobinRule wr)
{
wr.DoRolling();
}
static void Main(string[] args)
{
WeightRobinRule wr = new WeightRobinRule(); Timer t = new Timer((j) => { var removedS = wr.RemoveByIndex(); Console.WriteLine("移除了服务器:"+removedS); }, null, , Timeout.Infinite); t = new Timer((o) => { wr.AddNewServer(); Console.WriteLine("新增加服务器了。"); }, null, , Timeout.Infinite); Parallel.For(, , (num) =>
{
Thread.Sleep(r.Next(, ));
Rounding(wr);
});
Console.WriteLine(wr);
Console.ReadLine();
}
}
}

带有权重的服务器SLB的实现的更多相关文章

  1. iOS:搭建本地的服务器

    一.介绍 作为一个专业的程序员,不管你是前端还是移动端或者是后台,能够自己试着搭建一个本地的服务器还是很有必要的,有的时候,我们可以自己测试一些数据,很方便开发.其实,mac是自带有本地的服务器的,用 ...

  2. 搭建一个三台服务器的Memcached集群

    关于memcached的基础知识可以查看博客其他博文,这里只记录了搭建的过程,谢谢! 1.分别在三台服务器上安装Memcached并启动 第一.由于memcached是基于libevent的事件处理, ...

  3. [link] 构建负载均衡服务器之一 负载均衡与集群详解

    一.什么是负载均衡 首先我们先介绍一下什么是负载均衡: 负载平衡(Load balancing)是一种计算机网络技术,用来在多个计算机(计算机集群).网络连接.CPU.磁盘驱动器或其他资源中分配负载, ...

  4. CentOS FTP服务器系统套件全面讲解

    对大家推荐很好使用的CentOS FTP系统,像让大家对CentOS FTP系统有所了解,然后对CentOS FTP系统全面讲解介绍,希望对大家有用. 1.vsFTPd,目前常用CentOS FTP服 ...

  5. [ntp]查看ntp服务器的连接情况

    转自:http://www.cnblogs.com/liuyou/archive/2012/07/29/2614338.html 命令和工具 # watch ntpq -p # ntpq -p, /e ...

  6. 发生在阿里云 SLB 4 层的一次故障记录

    阿里云 SLB 与 ECS 之间发生故事.环境如下: SLB api-node: 该 SLB 后端接着 10 台节点服务器 SLB sql-node: 该 SLB 后端接着 2 台节点服务器 问题描述 ...

  7. Vert.x HTTP 服务器与客户端

    编写HTTP 服务器与客户端 Vert.x让编写非阻塞的HTTP 服务器与客户端变得非常轻松. 创建HTTP 服务器 缺省状况: HttpServer server = vertx.createHtt ...

  8. vnc服务器和windows2012密钥

    [root@localhost ~]# vncserver #启动服务器 windows 2012 64位-server版本的密钥 Windows Server 2012 Standard 密钥:NB ...

  9. Css3 权重

    Css权重 权重--很多规则应用到同一个元素上时,权重是决定哪个生效的(优先级) 权重等级与权值 行内样式(1000)>ID选择器(100)>类.属性选择器或伪类选择器(10)>元素 ...

随机推荐

  1. vim command

    问题:对多行缩进 简述:向左缩是<,向右缩是> 详述:在命令状态,按v进入visual状态,选中多行,再按>,相当于一个TAB键:再选中多行,按<试试 ------------ ...

  2. C# 调用带输入输出参数的存储过程

    //调用存储过程执行类似于2//select count(*) from userinfo where username=username and pwd=pwd and grade=grade3// ...

  3. delphi弹出选择对话框选择目录|SelectDirectory 函数(转)

    SelectDirectory 函数 通过显示一个对话框来让用户选择一个目录.注意:在使用前要在Uses 语句中添加包含FileCtrl 的说明.函数原型如下:function SelectDirec ...

  4. xml构建

    <a target="_blank" href="http://wpa.qq.com/msgrd?v=3&uin=346252320&site=qq ...

  5. mysql group by 详解

    GROUP BY X意思是将所有具有相同X字段值的记录放到一个分组里. 那么GROUP BY X, Y呢? GROUP BY X, Y意思是将所有具有相同X字段值和Y字段值的记录放到一个分组里.

  6. 【项目总结】扯一扯电商网站前端css的整体架构设计(1)

    最近半忙不忙的写了一个外包网站,网站主要功能是艺术品竞拍和艺术衍生品的销售.工程已经完成了80%左右,现在前后端代码量已经50W行左右,我主要负责的是前端设计和前端布局.下面就先放一个网站的设计图吧, ...

  7. Django 标签过滤器

    django内置标签 autoescape 控制当前的自动转义行为.这个标记可以作为参数打开或关闭,它决定自动转义是否在块内有效.块使用endautoescape结束标记关闭. 当自动转义生效时,所有 ...

  8. IO模型《五》异步IO

    Linux下的asynchronous IO其实用得不多,从内核2.6版本才开始引入.先看一下它的流程: 用户进程发起read操作之后,立刻就可以开始去做其它的事.而另一方面,从kernel的角度,当 ...

  9. “全栈2019”Java第六十四章:接口与静态方法详解

    难度 初级 学习时间 10分钟 适合人群 零基础 开发语言 Java 开发环境 JDK v11 IntelliJ IDEA v2018.3 文章原文链接 "全栈2019"Java第 ...

  10. Leetcode 856. Score of Parentheses 括号得分(栈)

    Leetcode 856. Score of Parentheses 括号得分(栈) 题目描述 字符串S包含平衡的括号(即左右必定匹配),使用下面的规则计算得分 () 得1分 AB 得A+B的分,比如 ...