前言
负载均衡,大家应该听的也不少了,也实践过N次了。
当然也会知道,负载均衡是有不少算法的:随机,轮询,加权轮询,最少连接。。。。
本文重点说的是轮询。
先举个例子看看轮询算法是如何运作的。
假设我们的API站点有3台负载(10.0.10.1,10.0.10.2和10.0.10.3),客户端第一次请求API的时候,会访问.1拿到结果,第二次会访问.2拿到结果,第三次则会访问.3拿到结果,后面就是依次类推。
在致就是这个样子的访问顺序。
.1->.2->.3>.1>.2......
当然,上面的情况是太太太理想了!!只是能帮助我们理解轮询是怎么一回事!
下面是比较官方的描述:
按顺序把每个新的连接请求分配给下一个服务器,最终把所有请求平分给所有的服务器。
下面来简单看看如何实现
简单实现
我们围绕的重点如下:
- 服务器列表
- 上一次访问的是那台机器
- 下一次要访问的是那台机器
下面是实现
public class RoundRobin{ //服务器列表 private readonly IList _items; //锁 private readonly object _syncLock = new object(); //当前访问的服务器索引,开始是-1,因为没有人访问 private int _currentIndex = -1; public RoundRobin(IEnumerable sequence) { _items = sequence.ToList(); if(_items.Count <= 0 ) { throw new ArgumentException("Sequence contains no elements.", nameof(sequence)); } } public T GetNextItem() { lock (this._syncLock) { _currentIndex++; //超过数量,索引归0 if (_currentIndex >= _items.Count) _currentIndex = 0; return _items[_currentIndex]; } }}
根据用户不同的设计,服务器有可能是一个字符串,也有可能是自定义的一个类,所以设计成泛型参数会比较合适。
下面测试一下
static void Main(string[] args){ //负载的api地址 var lbUrls = new List{ "http://10.0.10.1/api/values", "http://10.0.10.2/api/values", "http://10.0.10.3/api/values", "http://10.0.10.4/api/values", }; //构造轮询的对象 var robin = new RoundRobin (lbUrls); //访问次数 var visitCount = lbUrls.Count * new Random().Next(3, 5); //常规的情况 Console.WriteLine("begin one by one.."); for (int i = 0; i < visitCount; i++) { Console.WriteLine($"{i + 1}:Sending request to {robin.GetNextItem()}"); } //并行的情况 Console.WriteLine("begin parallel.."); Parallel.For(0, visitCount, i => { Console.WriteLine($"{i + 1}:Sending request to {robin.GetNextItem()}"); }); Console.ReadKey();}
结果:
示例代码: