Das nicht offensichtliche RabbitMQ in Yii2 oder warum RabbitMQ gleichzeitig in alle Warteschlangen schreibt


Ich möchte das praktische Problem der Konfiguration des RabbitMQ-Warteschlangenbrokers in Yii2 teilen. Ich warne den Leser, dass ich keine Expertenmeinung über die Arbeit mit diesem Warteschlangenbroker habe, aber ich möchte wirklich die Lücken in der Yii2-Dokumentation füllen und das Ergebnis meiner eigenen Qualen korrigieren. Wenn Sie also jemals auf ein Problem gestoßen sind, bei dem Nachrichten an alle Warteschlangen auf dem Warteschlangenserver gesendet werden, stimmen Sie zu, dass dies ein Problem ist, und verstehen nicht, warum dies geschieht. Dann frage ich nach einer Katze.

Warum könnten Sie auf dieses Verhalten stoßen? Zum Beispiel, wenn Sie, wie ich, noch nicht mit RabbitMQ gearbeitet haben, sondern zum Beispiel mit Gearman. Gearman selbst, so einfach wie eine Eisenbahn ( entlehnt von einem bekannten und angesehenen Internet-Charakter ). Sie erstellen eine Warteschlange mit einem bestimmten Namen und legen die Daten dort ab. Der Worker liest aus der gleichnamigen Warteschlange. Alles ist einfach. Jetzt ist es Zeit, Modetechnologie einzusetzen, ohne zu verstehen, warum Sie sich für RabbitMQ entscheiden. Dann sind Sie froh, dass Yii2 eine vorgefertigte Abstraktion für viele beliebte Warteschlangenmakler hat. In der spärlichen Dokumentation wird die Standardkonfiguration angegeben, um alles zu starten:

return [ 'bootstrap' => [ 'queue', // The component registers its own console commands ], 'components' => [ 'queue' => [ 'class' => \yii\queue\amqp_interop\Queue::class, 'port' => 5672, 'user' => 'guest', 'password' => 'guest', 'queueName' => 'queue', 'driver' => yii\queue\amqp_interop\Queue::ENQUEUE_AMQP_LIB, // or 'dsn' => 'amqp://guest:guest@localhost:5672/%2F', // or, same as above 'dsn' => 'amqp:', ], ], ]; 

Es scheint, dass alles wahnsinnig einfach ist. Hier ist die vertraute Zeile mit queueName , Kopieren und Einfügen, Reparieren , Ausführen - es funktioniert! Wir stellen Warteschlangen für andere Komponenten des Systems. Wir parallelisieren mit dem, was unser PHP kann. Commit, Push zufrieden, wir stellen die Aufgabe in die Qualitätssicherung und lesen einen Habr ( in der Mittagspause ).

Hier, am interessantesten, unterbricht uns die Qualitätssicherung im Chat und sagt, dass etwas Seltsames passiert. Aus irgendeinem Grund werden die Daten, die die Arbeiter (Kunden) schreiben, dupliziert. Wie bitte? Das kann nicht so sein. Wir gehen, um die Protokolle zu überprüfen. Wir sehen, dass die Nachricht in die Warteschlange geschrieben wird, mit der die Warteschlange korrekt ausgewählt wurde und die Hash-Job-ID empfangen wird. Nein, nein, wir haben keine Fehler. Wir schreiben zufriedene QAs, überprüfen Sie noch einmal, das kann nicht sein, es geht uns gut.

Buchstäblich nach einer halben Stunde waren wir wieder abgelenkt, der Fehler wiederholte sich und dann fiel eine Benachrichtigung auf die Seife - die Aufgabe wurde wieder an die Arbeit übertragen. Nun, ich bin ein Programmierer, jetzt werden wir es herausfinden. RabbitMQ verfügt im Gegensatz zu Gearman über eine Weboberfläche, in der viele Informationen zum Server enthalten sind. Dieses Wunder sieht so aus:



Wir werfen ein paar weitere Nachrichten in die Warteschlange, wir sehen im Webmord, dass unsere Nachrichten ankommen und vom Arbeiter verarbeitet werden. Ein lässiger Look stellt fest, dass beim Werfen einer Nachricht in die Warteschlange das Diagramm "Nachrichtenraten" in alle Warteschlangen springt.



Wir überprüfen die Konfiguration hundertmal und lesen die spärliche Dokumentation von Yii erneut. Wir haben alles richtig gemacht. Wir lesen die Dokumentation auf der Kaninchen-Website. Nach ein paar zehn Minuten im Dunkeln stoßen wir auf ein Tutorial . Unmittelbar nach dem ersten Absatz lernen wir den Grund für unser Missverständnis kennen - den Austausch. Ich werde die Dokumentation nicht sehr kurz wiederholen.

In RabbitMQ schreiben wir keine Nachricht in die Warteschlange, wir schreiben sie zum Austausch, eine Art Proxy, der unsere Nachrichten an einem Ende empfängt und mit den Warteschlangen auf dem Server am anderen Ende kommuniziert. Es liegt in seiner Macht zu entscheiden, in welche Warteschlange unsere Daten gestellt werden sollen. Interessanterweise gibt es in der Yii-Dokumentation keine einzige Zeile dazu. Auf den ersten Blick ist nicht klar, wie der Austausch konfiguriert werden soll. Wir tauchen in die Eingeweide ein und finden in der Datei Vendor / yiisoft / yii2-queue / src / drivers / amqp_interop / Queue.php: 176 eine geschätzte Eigenschaft, die sichtbar ist. Hier muss ich sagen, dass es viele Treiber für RabbitMQ gibt, in meinem Fall wird enqueue / amqp-lib verwendet . Wir setzen ExchangeName , testen, nichts ändert sich. Nun, wir sind wie ein echter russischer Ingenieur. Zuerst versuchen wir es und dann lesen wir nachdenklich die Dokumentation noch einmal. Wir lesen es noch einmal sorgfältig durch, gehen dann zum Webface von Kaninchen und sehen Folgendes:



Mehrere unserer Warteschlangen sind demselben Austausch zugeordnet. Bingo! Hier ist es der Grund, ein "aber", ich habe sie nicht gebunden. Wir gehen noch einmal in den Darm des Treibers, wir finden die setupBroker- Methodenzeile 392

 $this->context->bind(new AmqpBind($queue, $topic)); 

Dies ist eine nicht verwaltete Bindung.

Und so kommen wir, ohne lange nachzudenken, zu dem Schluss, dass für jede Warteschlange ein Austausch deklariert werden muss, dann ist die Verbindung korrekt und ein Austausch hat nur eine verbundene Warteschlange. Auf diese Weise erhalten wir ein ähnliches Gearman-Verhalten. Übrigens beschreibt die Dokumentation ausführlich, warum der Austausch durchgeführt wurde, und nach meinem Verständnis ist einer der Gründe die Möglichkeit, mehrere Warteschlangen mit dem Austausch zu verknüpfen. Aber ich habe mir keinen solchen Fall ausgedacht, wenn es nötig sein könnte, schreiben die Jungs in den Kommentaren. Und schreiben Sie, sind Sie auf die oben beschriebene Situation gestoßen oder mache ich alles falsch?

Source: https://habr.com/ru/post/de439080/


All Articles