带有权重的服务器SLB的实现
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的实现的更多相关文章
- iOS:搭建本地的服务器
一.介绍 作为一个专业的程序员,不管你是前端还是移动端或者是后台,能够自己试着搭建一个本地的服务器还是很有必要的,有的时候,我们可以自己测试一些数据,很方便开发.其实,mac是自带有本地的服务器的,用 ...
- 搭建一个三台服务器的Memcached集群
关于memcached的基础知识可以查看博客其他博文,这里只记录了搭建的过程,谢谢! 1.分别在三台服务器上安装Memcached并启动 第一.由于memcached是基于libevent的事件处理, ...
- [link] 构建负载均衡服务器之一 负载均衡与集群详解
一.什么是负载均衡 首先我们先介绍一下什么是负载均衡: 负载平衡(Load balancing)是一种计算机网络技术,用来在多个计算机(计算机集群).网络连接.CPU.磁盘驱动器或其他资源中分配负载, ...
- CentOS FTP服务器系统套件全面讲解
对大家推荐很好使用的CentOS FTP系统,像让大家对CentOS FTP系统有所了解,然后对CentOS FTP系统全面讲解介绍,希望对大家有用. 1.vsFTPd,目前常用CentOS FTP服 ...
- [ntp]查看ntp服务器的连接情况
转自:http://www.cnblogs.com/liuyou/archive/2012/07/29/2614338.html 命令和工具 # watch ntpq -p # ntpq -p, /e ...
- 发生在阿里云 SLB 4 层的一次故障记录
阿里云 SLB 与 ECS 之间发生故事.环境如下: SLB api-node: 该 SLB 后端接着 10 台节点服务器 SLB sql-node: 该 SLB 后端接着 2 台节点服务器 问题描述 ...
- Vert.x HTTP 服务器与客户端
编写HTTP 服务器与客户端 Vert.x让编写非阻塞的HTTP 服务器与客户端变得非常轻松. 创建HTTP 服务器 缺省状况: HttpServer server = vertx.createHtt ...
- vnc服务器和windows2012密钥
[root@localhost ~]# vncserver #启动服务器 windows 2012 64位-server版本的密钥 Windows Server 2012 Standard 密钥:NB ...
- Css3 权重
Css权重 权重--很多规则应用到同一个元素上时,权重是决定哪个生效的(优先级) 权重等级与权值 行内样式(1000)>ID选择器(100)>类.属性选择器或伪类选择器(10)>元素 ...
随机推荐
- vue环境中生成二维码
<template><div><div id='code'></div><canvas id="canvas">< ...
- 基于.net standard 的动态编译实现
在前文[基于.net core 微服务的另类实现]结尾处,提到了如何方便自动的生成微服务的客户端代理,使对于调用方透明,同时将枯燥的东西使用框架集成,以提高使用便捷性.在尝试了基于 Emit 中间语言 ...
- Nginx自定义扩展模块
1. 概述 参考 Nginx开发HTTP模块入门 2. 扩展模块(假设根目录名称为nginx) nginx/configure文件中可以修改配置文件路径(编译时使用): 例如像把配置文件从默认的ngi ...
- 使用docker部署java项目
在接触了docker后,干什么都想用docker来弄.最近刚做完毕业设计,本来是说将项目简单在本地部署就行了,结果老师说如果部署在服务器的话有加加分,于是果断用docker来搞,多加点分. java项 ...
- RabbitMq初探——安装
rabbitmq Server安装 rabbitmq server安装很简单. 安装erlang环境 rpm -ihv erlang-18.1-1.el6.x86_64.rpm rpm -ihv ra ...
- MySQL开启日志记录查询/执行过的SQL语句
作为后端开发者,遇到数据库问题的时候应该通过分析SQL语句来跟进问题所在,该方法可以记录所有的查询/执行的SQL语句到日志文件. 方法有几种,但是个人觉得以下这种最简单,但是重启MySQL服务后需要重 ...
- 什么是cluster(群集)
一.群集的概念 在互联网应用中,随着站点对硬件性能.相应速度.服务稳定性.数据可靠性等要求越来越高,单台服务器力不从心,使用小型机或大型机价格还太昂贵,因此我们使用普通服务器来构建服务群集显然最划算. ...
- 虚拟机安装CentOS,网络配置
CentOS6和CentOS7,基础配置差不多. 安装CentOs6,过程:略: 安装完成后,系统默认启用动态ip,每次重启主机IP可能就会变化,搭配Xftp和Xshell工具会很难受,因此设置静态I ...
- luogu P1080国王游戏
贪心加高精 传送门:QWQ 先考虑两个人 a0 b0 p1 a1 b1 p2 a2 b2 那么满足:\(\huge ans1=\max(\frac{a0}{b1} , \frac{a0a1}{b2}) ...
- POJ1330 Nearest Common Ancestors (JAVA)
经典LCA操作.. 贴AC代码 import java.lang.reflect.Array; import java.util.*; public class POJ1330 { // 并查集部分 ...