实现一个简单的轮询算法

C#

浏览数:297

2019-5-4

AD:资源代下载服务

前言

负载均衡,大家应该听的也不少了,也实践过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();
}

结果:

示例代码:

RoundRobinDemo

作者:Catcher8