2010-04-21 7 views
7

J'ai besoin d'écrire un algorithme round robin pour planifier la charge à n points de terminaison?Planification du chargement avec un algorithme Round Robin?

Donc, si j'ai serveurs A, B et C

Je voulais vous assurer de la ronde à travers eux pour chaque demande que je reçois. Comment est-ce que je fais cela en C#?

+1

Sera-t-il une charge constante ou une distribution uniforme de la charge? – Avitus

+0

Je pense que 'round robin' indique qu'il n'y a pas de tentative de distribution uniforme de la charge. –

Répondre

18

Pour la petite histoire, la définition du tournoi à la ronde:

http://en.wikipedia.org/wiki/Round-robin_scheduling

Il suffit d'utiliser une file d'attente. Enlevez-en une, utilisez-la et remettez-la. Cela garantit que le dernier utilisé sera toujours le dernier à être ramassé.

Queue<Server> q = new Queue<Server>(); 

//get the next one up 
Server s = q.DeQueue(); 


//Use s; 


//put s back for later use. 
q.Enqueue(s); 

Lien vers la classe de file d'attente:

http://msdn.microsoft.com/en-us/library/7977ey2c.aspx

+0

Je voudrais défier une personne qui a dit qu'il voulait mettre en place un tournoi à la ronde pour déterminer si elles veulent vraiment dire round robin. – Tim

+2

Il est utilisé dans la distribution de charge du serveur tout le temps. – kemiller2002

+1

Lors de l'utilisation de ce modèle, il peut être utile d'immédiatement mettre en file d'attente le serveur avant de l'utiliser (ou de mettre la file d'attente dans un bloc finally). De cette façon, les exceptions levées lors de "l'utilisation" du serveur ne peuvent pas entraîner la suppression complète du serveur de la rotation. – bvoyelr

1

Si vos points de terminaison sont accessibles via une liste ou un tableau, il vous suffit d'incrémenter un indice de manière circulaire:

public class RoundRobinIndex 
{ 
    volatile int index = 0; 
    int count; 

    public int Next 
    { 
     get 
     { 
      if (index == count) 
      { 
       index = 0; 
      } 
      return index++; 
     } 
    } 

    public RoundRobinIndex(int countArg) 
    { 
     count = countArg; 
    } 
} 
+0

L'utilisation de cela provoquera une exception IndexOutOfRangeException – IBootstrap

+0

@IBootstrap - Cela ne provoque pas d'exception IndexOutOfRangeException. L'avez-vous réellement testé? –

+0

Suivant peut également être atteint en utilisant: (index + 1)% count; – Aerokneeus

6

Même idée que ebpower, mais en mettant l'accent sur ce qui est l'élément suivant plutôt que sur l'indice de l'élément suivant.

public class RoundRobinList<T> 
{ 
    private readonly IList<T> _list; 
    private readonly int _size; 
    private int _position; 

    public RoundRobinList(IList<T> list) 
    { 
     if (!list.Any()) 
      throw new NullReferenceException("list"); 

     _list = new List<T>(list); 
     _size = _list.Count;    
    } 

    public T Next() 
    { 
     if (_size == 1) 
      return _list[0]; 

     Interlocked.Increment(ref _position); 
     var mod = _position % _size; 
     return _list[mod]; 
    } 
} 
+0

passer IEnumerable pour construire et enregistrer mod avant Incrementing _position, et c'est de l'argent. – JJS