带有权重的服务器SLB的实现
生活随笔
收集整理的這篇文章主要介紹了
带有权重的服务器SLB的实现
小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
1)參考了網(wǎng)絡(luò)上的算法,但是那個(gè)算法僅僅是用于展示“權(quán)重輪循”的意圖,在真正的網(wǎng)絡(luò)下,因?yàn)槭遣⑿械?#xff0c;所以不可能單純一個(gè)簡(jiǎn)單的循環(huán)可以解決問(wèn)題。
2)用lock的話性能顯然有損失。
3)想了一陣,結(jié)合CAS和volatile等細(xì)粒度的鎖的方式,一個(gè)真正可以用軟件描述SLB帶有權(quán)重的算法大概是這個(gè)樣子(如下):
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading;namespace WBasedRobin {/// <summary>/// 用于計(jì)算WeightRobin的數(shù)據(jù)結(jié)構(gòu)/// </summary>public class WeightedRobin{private readonly int _weight;private int _count;/// <summary>/// 命中次數(shù)(累加)/// </summary>public int ChoosenCount{get{return ++_count;}}/// <summary>/// 權(quán)重/// </summary>public int Weight{get{return _weight;}}/// <summary>/// 輸出當(dāng)前的權(quán)重/// </summary>public override string ToString(){return "Weight:" + Weight.ToString() + "\tCount:" + _count.ToString();}/// <summary>/// 初始化每一個(gè)Server的內(nèi)部值/// </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>/// 初始化權(quán)重服務(wù)器,至少2臺(tái)服務(wù)器。/// </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;//當(dāng)服務(wù)器數(shù)量發(fā)生變化的時(shí)候,鎖住該服務(wù)直到完畢。reloop: while (_isServerChanging) ;for (;;){//拷貝本地的index,用做同步copyIndex = _index;//計(jì)算輪詢(xún)的時(shí)候下一個(gè)的值copyIndexNext = (copyIndex + 1) % _servers.Count;//同步作用copycw = _currentWeight;//假定輪詢(xún)后的Next=0,說(shuō)明完成一輪輪詢(xún),權(quán)重減去最大公約數(shù)if (copyIndexNext == 0){copycw -= _gcdWeight;//如果權(quán)重已經(jīng)扣完,重新從大的開(kāi)始if (copycw <= 0){copycw = _maxWeight;}}//如果copyIndex和_index相同,說(shuō)明是同一個(gè)線程搶到的,那么直接用本地的替換index進(jìn)行替換if (Interlocked.CompareExchange(ref _index, copyIndexNext, copyIndex) == copyIndex){_currentWeight = copycw;try{//如果輪詢(xún)的權(quán)重大于等于本地權(quán)重,選中它即可。if (_servers[copyIndexNext].Weight >= copycw){int t = _servers[copyIndexNext].ChoosenCount;break;}}//如果是Index溢出,那么說(shuō)明服務(wù)器數(shù)量肯定發(fā)生變化了,所以跳過(guò)此次輪詢(xún),等下一輪,不處理。catch (IndexOutOfRangeException){goto reloop;}}}}/// <summary>/// 移除指定的服務(wù)器/// </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>/// 增加新的服務(wù)器/// </summary>public void AddNewServer(int weight){_isServerChanging = true;_servers.Add(new WeightedRobin(weight, 0));_gcdWeight = GetTotalGCD();_maxWeight = GetMaxWeight(_servers);_isServerChanging = false;}/// <summary>/// 格式化輸出結(jié)果/// </summary>public override string ToString(){StringBuilder sbu = new StringBuilder(10);foreach (WeightedRobin wr in _servers){sbu.AppendLine(wr.ToString() + Environment.NewLine);}return sbu.ToString();}} }調(diào)用測(cè)試代碼如下:
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("移除了服務(wù)器:"+removedS); }, null, 2050, Timeout.Infinite);t = new Timer((o) => { wr.AddNewServer(6); Console.WriteLine("新增加服務(wù)器了。"); }, null, 3000, Timeout.Infinite);Parallel.For(1, 1001, (num) => {Thread.Sleep(r.Next(100, 500));Rounding(wr);});Console.WriteLine(wr);Console.ReadLine();}} }轉(zhuǎn)載于:https://www.cnblogs.com/ServiceboyNew/p/7156449.html
總結(jié)
以上是生活随笔為你收集整理的带有权重的服务器SLB的实现的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: Sqlserver 查询语句性能测试
- 下一篇: DataSet导出Excel,比以往的方