Was sind Warteschlangenmechanismen für die Implementierung von Round-Robin-Warteschlangen?

8

Ich habe mehrere Aufgabenersteller, die Arbeit zu einer Warteschlange hinzufügen. Ich habe auch mehrere Verbraucher, die diese Warteschlange ausfüttern. Da diese Warteschlangen FIFO sind, werden sie in der gleichen Reihenfolge, in der sie hinzugefügt wurden, aus der Warteschlange entfernt.

In meinem Szenario werden Aufgaben aus HTTP-Anfragen zur Warteschlange hinzugefügt. Jede Aufgabe ist einem Konto zugeordnet, und es gibt keine Ratenbegrenzung. Daher ist es möglich, dass Tasks von einem Konto die Nachrichtenwarteschlange überfluten.

Um das zu lösen, habe ich nach einer Warteschlangenimplementierung gesucht, die es mir ermöglicht, in Warteschlangen befindliche Aufgaben aus mehreren Konten fair zu bearbeiten.

Ich habe zur Zeit Redis mit einigen Lua-Skripten verwendet, um eine Round-Robin-Warteschlange zu emulieren, aber ich frage mich, ob es dafür Warteschlangentopologien gibt.

    
Mridang Agarwalla 07.10.2016, 09:40
quelle

4 Antworten

2

Jede verpackte Lösung wird mit viel überflüssigem Aufwand verbunden sein. Ich glaube, dies ist das Muster, auf das Sie sich konzentrieren möchten . RabbitMQ hat zum Beispiel eine Routing-Queue-Lösung. Und ActiveMQ unterstützt dieses Muster auch .

Ich würde es selbst schreiben, aber es ist nicht so schwer.

    
fedup 13.10.2016 14:10
quelle
2

Normalerweise mache ich das so:

  • Anstatt Aufgaben direkt in die Arbeitswarteschlange zu stellen, erstellen Sie für jedes Konto eine separate Aufgabenwarteschlange. Bei jeder Anfrage wird eine Aufgabe in ihre Kontowarteschlange gestellt, und wenn die Kontowarteschlange von leer auf nicht leer wechselt, wird die Kontowarteschlange in die globale Arbeitswarteschlange

  • gestellt
  • Arbeiter nehmen Warteschlangen aus der Arbeitswarteschlange zur Kenntnis, wenn sie für weitere Arbeit bereit sind. Wenn ein Sachbearbeiter eine Kontowarteschlange nimmt, nimmt er die erste Aufgabe heraus und der Worker setzt die Kontowarteschlange sofort an das Ende der Arbeitswarteschlange zurück, wenn sie nicht leer ist . Dann führt der Arbeiter die Aufgabe aus.

Bei Verwendung dieses Systems befindet sich jede Kontowarteschlange höchstens einmal in der Arbeitswarteschlange, und alle Konten mit zugehöriger Arbeit werden in der Arbeitswarteschlange gleichermaßen dargestellt.

Dies ist ziemlich einfach zu implementieren, aber Sie müssen vorsichtig sein, wenn Sie eine Konto-Warteschlange in die Warteschlange stellen müssen, da es zwei Threads geben kann, die diese Entscheidung gleichzeitig treffen. Ich möchte, dass die Kontowarteschlange zweimal eingeht.

Ich mache es so einfach:

  • Halten Sie in jeder Kontowarteschlange einen atomaren Booleschen Wert, der überwacht, ob er sich in der Arbeitswarteschlange befindet oder nicht. Der Worker setzt dies sofort nach dem Entfernen der Kontowarteschlange auf false. Wenn jemand feststellt, dass die Kontowarteschlange nicht leer ist, können sie versuchen, diesen booleschen Wert auf "wahr" zu setzen und, falls erfolgreich, die Kontowarteschlange in die Arbeitswarteschlange zu legen.

  • Es besteht eine geringe Chance, dass eine Kontowarteschlange in die Arbeitswarteschlange gelangt, wenn sie leer ist. Stellen Sie sicher, dass dies harmlos ist - wenn ein Worker eine Aufgabe aus einer Kontowarteschlange nicht übernehmen kann, sollte er dies einfach vergessen und eine neue Kontowarteschlange aus der Arbeitswarteschlange nehmen.

Matt Timmermans 15.10.2016 23:57
quelle
1

Ich weiß, dass WebSphere in Version 5.1 (sehr alt) eine solche Queue bereitstellt, dass eine einzelne Queue Dienste mit Unterwarteschlangen bereitstellen kann, dh dass Sie in Ihrem Fall für jeden Client eine Unterwarteschlange erstellen und im Grunde eine Runde abfragen könnten Ähnlich wie jede Unterwarteschlange für eine nächste Aufgabe. Aber ich kenne die Details nicht und würde WebSphere im Allgemeinen nicht empfehlen (aus Erfahrung). Aber ich denke, programmatisch können Sie eine Liste von Warteschlangen oder einer Warteschlangenwarteschlange verwalten, wobei jede Warteschlange auf einer niedrigeren Ebene eine Warteschlange von Aufgaben von einem bestimmten Client darstellt. Und dann können Sie Ihre eigene Logik verwenden, um Aufgaben in einer Tarifreihenfolge aus der richtigen Warteschlange zu übernehmen. Natürlich müssen Sie Ihre Warteschlangen managen, d. H. Leere Warteschlangen bereinigen, und nach Erhalt einer neuen Aufgabe prüfen, ob dieser Client bereits eine dedizierte Warteschlange hat oder nicht, und Ihre Aufgabe entsprechend zu einer neuen oder bestehenden Warteschlange hinzufügen.

    
Michael Gantman 09.10.2016 10:58
quelle
1

Mit RabbitMQ Direct Exchange und Spring AMQP können Sie eine Warteschlangentopologie implementieren, die eine Warteschlange für jedes Konto enthält, das mit einer einzelnen Exchange verbunden ist. Senden Sie Nachrichten an die Vermittlungsstelle mit dem Kontonamen als Routing-Schlüssel und mit einem einzelnen Verbraucher , der an mehrere Warteschlangen gebunden ist, erhält der Verbraucher die Nachrichten round robin (siehe "Direkter Austausch und Lastausgleich") .

>

Das Problem mit diesem Setup ist, dass Sie möglicherweise einige Warteschlangen (eine für jedes Konto) und zumindest in meiner Implementierung (als einfache Spring Boot-Anwendung unten angehängt) haben, müssen Sie die "neu starten" Benutzer jedes Mal, wenn ein neues Konto eingeht, da dies bedeutet, dass Sie eine neue Warteschlange haben, an die Sie den Verbraucher anschließen können. Ich weiß nicht, ob das sehr gut funktioniert. Überprüfen Sie diesen Post für die maximale Anzahl von Warteschlangen in RabbitMQ und wenn dich das beeinflussen könnte.

%Vor%

Die Anzahl der Aufgaben ist in diesem Beispiel willkürlich - aber ich wollte die "erwartete" Reihenfolge hinzufügen, um zu sehen, ob die Ausgabe unseren Erwartungen entspricht.

Die Ausgabe des Tests lautet:

%Vor%

was ich denke ist was du wolltest ...

    
Michael Lihs 15.10.2016 23:14
quelle

Tags und Links