前言
負載均衡,大家應該聽的也不少了,也實踐過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<T>
{
//伺服器列表
private readonly IList<T> _items;
//鎖
private readonly object _syncLock = new object();
//當前訪問的伺服器索引,開始是-1,因為沒有人訪問
private int _currentIndex = -1;
public RoundRobin(IEnumerable<T> 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<string>
{
"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<string>(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();
}
結果:
示例程式碼: