Le RabbitMQ non évident dans Yii2 ou pourquoi RabbitMQ écrit dans toutes les files d'attente à la fois


Je veux partager le problème pratique de la configuration du courtier de files d'attente RabbitMQ dans Yii2. Je préviens le lecteur que je n'ai pas d'avis d'expert sur le travail avec ce courtier de file d'attente, mais je veux vraiment combler les lacunes dans la documentation Yii2 et corriger le résultat de mon propre tourment. Donc, si vous avez déjà rencontré un problème d'envoi de messages à toutes les files d'attente qui se trouvent sur le serveur de file d'attente, vous convenez que c'est un problème et ne comprenez pas pourquoi cela se produit, alors je demande un chat.

Pourquoi pourriez-vous rencontrer ce comportement? Par exemple, si vous, comme moi, n'avez pas travaillé avec RabbitMQ auparavant, mais avez travaillé par exemple avec Gearman. Gearman lui-même, simple comme un chemin de fer ( emprunté à un personnage bien connu et respecté sur Internet ). Vous créez une file d'attente avec un certain nom, y mettez les données. Le travailleur lit dans la file d'attente portant le même nom. Tout est simple. Il est maintenant temps d'utiliser la technologie de la mode, sans comprendre pourquoi vous choisissez RabbitMQ. Ensuite, vous êtes heureux que Yii2 possède une abstraction prête à l'emploi pour de nombreux courtiers de files d'attente populaires. La documentation limitée indique la configuration par défaut pour tout démarrer:

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:', ], ], ]; 

Il semblerait que tout soit incroyablement simple, voici la ligne familière avec queueName , copiez-collez, corrigez-la , exécutez-la - cela fonctionne! Nous faisons des files d'attente pour d'autres composants du système. Nous parallélisons avec ce que notre php peut. Commit, Push satisfait nous avons mis la tâche en QA et nous allons lire un habr ( à la pause déjeuner ).

Ici, sur la partie la plus intéressante, QA nous interrompt dans le chat et dit que quelque chose d'étrange se passe. Pour une raison quelconque, les données que les travailleurs (cosumers) écrivent sont dupliquées. Quoi quoi Ça ne peut pas être comme ça. Nous allons vérifier les journaux. Nous voyons que le message est écrit dans la file d'attente, avec laquelle la file d'attente est sélectionnée correctement, le hachage jobId est reçu. Non, non, nous n'avons pas d'erreurs. Nous écrivons des QA satisfaits, vérifiez encore une fois, cela ne peut pas être le cas, nous nous en sortons bien.

Littéralement après une demi-heure, nous avons de nouveau été distraits, l'erreur s'est répétée, puis une notification est tombée sur le savon - la tâche a été renvoyée au travail. Eh bien, je suis programmeur, maintenant nous allons le découvrir. RabbitMQ, contrairement à Gearman, possède une interface Web dans laquelle il y a beaucoup d'informations sur le serveur. Ce miracle ressemble à ceci:



Nous jetons quelques messages supplémentaires dans la file d'attente, nous voyons dans le webmord que nos messages arrivent et sont traités par le travailleur. Un look décontracté remarque que lorsque nous jetons un message dans la file d'attente, le graphique «Taux de messages» saute dans toutes les files d'attente.



Nous vérifions la configuration cent fois, relisons la documentation limitée de Yii. Nous avons tout bien fait. Nous allons lire la documentation sur le site du lapin. Après quelques dizaines de minutes d'errance dans le noir, nous tombons sur un tutoriel . Immédiatement après le premier paragraphe, nous nous familiarisons avec la raison de nos malentendus - Échanges. Je ne répéterai pas la documentation, très brièvement.

Dans RabbitMQ, nous n'écrivons pas de message dans la file d'attente, nous l'écrivons pour échanger, une sorte de proxy qui reçoit nos messages à une extrémité et communique avec les files d'attente sur le serveur à l'autre extrémité. Il est en son pouvoir de décider dans quelle file d'attente mettre nos données. Fait intéressant, il n'y a pas une seule ligne à ce sujet dans la documentation Yii. À première vue, la configuration de l'échange n'est pas claire, nous plongons dans les tripes et dans le fichier vendor / yiisoft / yii2-queue / src / drivers / amqp_interop / Queue.php: 176, nous trouvons une propriété chérie qui peut être remplie. Ici, je dois dire qu'il existe de nombreux pilotes pour RabbitMQ, dans mon cas, enqueue / amqp-lib est utilisé . Nous définissons exchangeName , test, rien ne change. Eh bien, nous sommes comme un véritable ingénieur russe, nous essayons d'abord, puis nous reprenons la lecture de la documentation. Nous le lisons à nouveau attentivement, puis allons sur le visage Web de lapin et voyez ce qui suit:



Plusieurs de nos files d'attente sont associées au même échange. Bingo! Voilà la raison, un «mais», je ne les ai pas liés. On rentre dans l'intestin du driver, on retrouve la ligne de méthode setupBroker 392

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

Il s'agit d'une liaison non gérée.

Et donc, sans réfléchir longtemps, nous arrivons à la conclusion que pour chaque file d'attente un échange doit être déclaré, alors la connexion sera correcte et un échange n'aura qu'une seule file d'attente connectée. de cette façon, nous obtenons un comportement Gearman similaire. Soit dit en passant, la documentation décrit en détail pourquoi l'échange a été effectué, et si je comprends bien, l'une des raisons est la possibilité de lier plusieurs files d'attente à l'échange. Mais je n'ai pas trouvé un cas comme celui-ci quand cela pourrait être nécessaire, les gars écrivent dans les commentaires. Et écrivez, avez-vous rencontré la situation décrite ci-dessus ou est-ce que je fais tout mal?

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


All Articles