實現一個簡單的輪詢演算法

weixin_33709364發表於2018-03-17

前言

負載均衡,大家應該聽的也不少了,也實踐過N次了。

當然也會知道,負載均衡是有不少演算法的:隨機,輪詢,加權輪詢,最少連線。。。。

本文重點說的是輪詢。

先舉個例子看看輪詢演算法是如何運作的。

假設我們的API站點有3臺負載(10.0.10.1,10.0.10.2和10.0.10.3),客戶端第一次請求API的時候,會訪問.1拿到結果,第二次會訪問.2拿到結果,第三次則會訪問.3拿到結果,後面就是依次類推。

在致就是這個樣子的訪問順序。

.1->.2->.3>.1>.2......

當然,上面的情況是太太太理想了!!只是能幫助我們理解輪詢是怎麼一回事!

下面是比較官方的描述:

按順序把每個新的連線請求分配給下一個伺服器,最終把所有請求平分給所有的伺服器。

下面來簡單看看如何實現

簡單實現

我們圍繞的重點如下:

  1. 伺服器列表
  2. 上一次訪問的是那臺機器
  3. 下一次要訪問的是那臺機器

下面是實現

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();
}

結果:

558945-20180317101934468-766903501.jpg

示例程式碼:

RoundRobinDemo

轉載於:https://www.cnblogs.com/catcher1994/p/simple_roundrobin.html

相關文章