带有权重的服务器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 = 0){_weight = weight;_count = count;}}public class WeightRobinRule{private List<WeightedRobin> _servers = null;private volatile int _index = -1;private volatile int _currentWeight = 0;private volatile bool _isServerChanging = false;private volatile int _maxWeight = 0;private volatile int _gcdWeight = 0;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 == 0){return small;}return GetGCDWeight(small, big % small);}private int GetTotalGCD(){int gcd = GetGCDWeight(_servers[0].Weight, _servers[1].Weight);for (int i = 2; i < _servers.Count; ++i){gcd = GetGCDWeight(gcd, _servers[i].Weight);}return gcd;}/// <summary>/// 初始化权重服务器,至少2台服务器。/// </summary>public WeightRobinRule(int totalServers = 2){Random r = new Random();_servers = new List<WeightedRobin>(totalServers);for (int i = 0; i < totalServers; i++){_servers.Add(new WeightedRobin(r.Next(2, totalServers+1),0));}_maxWeight = GetMaxWeight(_servers);_gcdWeight = GetTotalGCD();}public void DoRolling(){int copyIndex = 0;int copyIndexNext = 0;int copycw = 0;//当服务器数量发生变化的时候,锁住该服务直到完毕。reloop: while (_isServerChanging) ;for (;;){//拷贝本地的index,用做同步copyIndex = _index;//计算轮询的时候下一个的值copyIndexNext = (copyIndex + 1) % _servers.Count;//同步作用copycw = _currentWeight;//假定轮询后的Next=0,说明完成一轮轮询,权重减去最大公约数if (copyIndexNext == 0){copycw -= _gcdWeight;//如果权重已经扣完,重新从大的开始if (copycw <= 0){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, 0));_gcdWeight = GetTotalGCD();_maxWeight = GetMaxWeight(_servers);_isServerChanging = false;}/// <summary>/// 格式化输出结果/// </summary>public override string ToString(){StringBuilder sbu = new StringBuilder(10);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(5);Timer t = new Timer((j) => { var removedS = wr.RemoveByIndex(0); Console.WriteLine("移除了服务器:"+removedS); }, null, 2050, Timeout.Infinite);t = new Timer((o) => { wr.AddNewServer(6); Console.WriteLine("新增加服务器了。"); }, null, 3000, Timeout.Infinite);Parallel.For(1, 1001, (num) => {Thread.Sleep(r.Next(100, 500));Rounding(wr);});Console.WriteLine(wr);Console.ReadLine();}} }
转载于:https://www.cnblogs.com/ServiceboyNew/p/7156449.html
带有权重的服务器SLB的实现相关推荐
- 多个网站共用一个服务器权重,一个服务器多个站点会不会分散权重
一个服务器多个站点会不会分散权重 内容导读:同个网站服务器不会因为有多个网站而分散权重,因为服务器本身没有权重.网站权重是针对具体单个的网站而言的,权重的分散通常也是在页面内部,包括对本页面关键词权重 ...
- 服务器开发设计之算法宝典
作者:lynhlzou,腾讯 IEG 后台开发工程师 孙子云:"上兵伐谋,其次伐交,其次伐兵,其下攻城",最上乘行军打仗的方式是运用谋略,下乘的方式才是与敌人进行惨烈的厮杀.同样的 ...
- soul带权重的RoundRobin算法
soul的divide插件负载均衡算法之权重轮询算法 众所周知,轮询算法是每一次请求访问的服务器是在上一次请求访问的服务器的下一个位置. 而soul网关提供了带有权重的轮询. public class ...
- 阿里云SLB负载均衡配置方法(云起实验室)
阿里云SLB负载均衡实验 (云起实验室) 简介: 负载均衡的可以降低单台云服务器 ECS出现异常时对业务的冲击.其实就是多台服务器互为备胎,一台寄掉了换另一台.下面我简单说说怎么在阿里云上配置SLB负 ...
- K3服务器端可用电脑系统,k3服务器 客户端配置
k3服务器 客户端配置 内容精选 换一换 Kudu是专为Apache Hadoop平台开发的列式存储管理器.Kudu具有Hadoop生态系统应用程序的共同技术特性:可水平扩展,并支持高可用性操作.已安 ...
- LVS详解及基于LVS实现web服务器负载均衡
前言 LVS(Linux Virtual Server)Linux虚拟服务器,是一个虚拟的服务器集群系统.本项目在1998年5月由章文嵩博士成立,是中国国内最早出现的自由软件项目之一.通过LVS提供的 ...
- 微软私有云系列----域服务器准备
安装系统版本要求: 选择:Windows Server 2012 R2 Datacenter (带有GUI的服务器). 选择:"自定义硬盘分区". 设定administrator的 ...
- vsFTPd 服务器初学者指南
作者:北南南北,正在修订之中 来自:LinuxSir.Org 摘要:vsFTPD是一款小巧易用FTP服务器程序:本文面向初学者的一点疑问,能让初学者在最短的时间内学会最简单的vsftpd服务器的架设: ...
- 服务器系统2012怎么多人连接,windows2012服务器TCP连接数
windows2012服务器TCP连接数 内容精选 换一换 使用远程登录方式连接登录Windows云服务器时出现如下错误:由于没有远程桌面授权服务器可以提供许可证,远程会话被中断,请跟服务器管理员联系 ...
最新文章
- JDK 源码 Integer解读之一(toString)
- 第四周项目五-用递归方法求解(求1*3*5*...*n的递归式)
- webrtc rtsp播放
- TF之VGG系列:利用预先编制好的脚本data_convert .py文件将图片格式转换为tfrecord 格式
- OutOFMemoryError
- [转]TCP协议中的三次握手和四次挥手(图解)
- 数据源管理 | 分布式NoSQL系统,Cassandra集群管理
- Execution failed for task ':app:mergeDebugResources
- linux中用shell脚本对tomcat和nginx做日志切割
- python数据分析系列教程——NumPy全解
- 如何用计算机计算概率,计算器怎么算概率里面的A和C
- 英语3500词(15/20)crime主题(2022.1.27)
- 复习笔记1-java基础
- cron表达式及其验证方法
- Foxmail.exe -损坏的映像 错误修复
- 中国各个省份的id代号是多少?各省简称是什么?
- Java笨狗groovy学习笔记—Regular Expressions
- The Devil Wears Prada-9
- Python AutoCAD 块组
- R2S:年轻人的第一台软路由