Est-ce la bonne façon d’utiliser une queue de messagerie?

Je suis nouveau dans les files d’attente de messagerie, et maintenant j’utilise ZeroMQ sur mon serveur Linux. J’utilise PHP pour écrire à la fois le client et le serveur. Ceci est principalement utilisé pour le traitement des notifications push.

J’utilise le motif de communication formel REQREP base sur des instances ZMQContext un ZMQContext thread I / O, comme ils l’ont démontré.

Voici le code zeromqServer.php réduit:

 include("someFile.php"); $context = new ZMQContext(1); // Socket to talk to clients $responder = new ZMQSocket($context, ZMQ::SOCKET_REP); $responder->bind("tcp://*:5555"); while (true) { $request = $responder->recv(); printf ("Received request: [%s]\n", $request); // ----------------------------------------------------------------- // Process push notifications here // sleep (1); // ----------------------------------------------------------------- // Send reply back to client $responder->send("Basic Reply"); } 

Et voici un client ZeroMQ réduit:

 $context = new ZMQContext(); // Socket to talk to server echo "Connecting to hello world server…\n"; $requester = new ZMQSocket($context, ZMQ::SOCKET_REQ); $check = $requester->connect("tcp://localhost:5555"); var_dump($check); $requester->send("json ssortingng payload with data required to process push notifications."); //$reply = $requester->recv(); 

Donc ce que je fais? zeromqServer.php le zeromqServer.php tant que service d’arrière-plan, en utilisant la commande linux

nohup php zeromqServer.php &

Cela l’exécute en tant que processus d’arrière-plan. Maintenant, lorsque le client l’appelle, il effectue le travail requirejs.

Mais le problème est que, je dois redémarrer le processus chaque fois qu’il y a un changement dans l’un des fichiers (y compris ceux include dans le fichier zeromqServer ).

De plus, après 2 ou 3 jours, il ne fonctionne plus. Le processus ne s’arrête pas, mais il cesse simplement de fonctionner.

J’ai l’impression que ce doit être un problème de socket, peut-être que le socket n’est plus ouvert. À ce moment, je dois redémarrer le processus de fichier zeromqServer.php .

Q1: Quel pourrait être le problème?

Q2: Et comment faire cela?

Ce n’est pas la bonne façon d’utiliser une queue de messagerie.

R1: Le problème est que votre serveur doit finalement bloquer, car le code client ne récupère aucune réponse lorsque le modèle REQ/REP requirejs. Le zeromqServer.php du côté REP ne tentera simplement pas de recv() un autre message d’un client associé (du côté REQ de la communication formelle) tant que le client n’a pas été physiquement livré (dans un tampon interne) et a recv() -ed le message “reply” du côté zeromqServer.php .

Les versions antérieures de ZeroMQ, ver. 2.1 et autres utilisaient un nombre illimité, illimité et illimité de dimensionnement par défaut des files d’attente de messages internes et de la gestion de la mémoire d’un nœud, utilisés pour une mise en mémoire tampon des E / S de niveau inférieur avant la copie des données dans le kernel O / S ressources et libéré de l’empreinte mémoire ZeroMQ.

Les nouvelles versions de ZeroMQ, ver 3.x +, ont par défaut les ” HWM -s” (alias High-Water-Mark-s) “juste” 1000 messages “courts”, après quoi la partie respective de cette ressource ZeroMQ démarre pour bloquer ou supprimer des messages.

Tandis qu’une tentative réactive pour augmenter explicitement la gestion des parameters HWM semble être une mauvaise façon de résoudre une erreur de conception principale, un autre avertissement ZeroMQ est correct sur ce point (ØMQ ne garantit pas que le socket acceptera comme beaucoup comme des messages ZMQ_SNDHWM , et la limite réelle peut être inférieure de 60 à 70% en fonction du stream de messages sur le socket).

Oublier ou être incapable de le faire ( Réf.: Comme le code OP a déjà démontré):

 //$reply = $requester->recv(); 

signifie que votre modèle de communication formel REQ/REP “pendule” devient irréversiblement bloqué (pour toujours).


A2: Basic REQ/REP Le modèle de communication formelle sonne droit, mais présente quelques caractéristiques dangereuses, le blocage observé en est une. Certaines étapes supplémentaires pourraient être entresockets en XREQ/XREP code, pour déployer XREQ/XREP , XREQ/XREP DEALER/ROUTER et d’autres outils, mais la conception devrait être révisée, et pas seulement SLOC par SLOC , car il semble y avoir beaucoup de choses à réaliser. avant de concevoir un code. L’une des principales erreurs consiste à supposer qu’un message est envoyé une fois qu’une méthode send() a été commandée. Ce n’est pas le cas dans ZeroMQ.

De plus, le code-design doit assumer le caractère incertain d’un message et gérer correctement à la fois le problème de message manquant et tout type d’incident de blocage de service dissortingbué (blocage, livelock, dépassement de tampon, ancien / nouveau-API). n’est pas une garantie explicite aucun de vos homologues de messagerie (il n’y a pas de courtier central dans ZeroMQ) a la même version de l’API / protocole ZeroMQ sur le côté localhost – il y a donc beaucoup de nouveaux points de vue, pendant la conception du code)


La meilleure façon de le faire

Si vous pouvez avoir confiance en une expérience pratique, la meilleure chose à faire est de télécharger et de lire le fabuleux livre de Pieter HINTJENS “Code Connected, Volume 1” , dans lequel Pieter a beaucoup de connaissances sur le traitement dissortingbué. , y compris de nombreux conseils et indications pour les patterns fiables, comme vous voudrez l’implémenter.

Si vous restz dans la conception de logiciels dissortingbués, alors n’hésitez pas à vous lancer dans un livre de recettes de plus de 400 pages du Master of Masters. , le Pieter HINTJENS hors de question est.

Pourquoi? Le monde réel est généralement beaucoup plus complexe

Juste une image, Fig.60 du livre mentionné ci-dessus pour oublier la réutilisation des archétypes individuels et pour réaliser la nécessité d’une perspective de conception de système dissortingbué de bout en bout, y compris des stratégies de blocage et de résolution des blocages :

Avion de transport + avion SIG

Juste pour avoir une idée, examinez l’exemple de code suivant, à partir d’une simple messagerie dissortingbuée, où aMiniRESPONDER processus aMiniRESPONDER utilise plusieurs canaux ZeroMQ.

entrer la description de l'image ici


Comment améliorer votre implémentation dans un domaine d’application PHP Web assez important?

Apprenez à prévenir et à gérer les deux autres types de collision.

PHP possède tous les constructeurs de syntaxe appropriés pour ce type d’algorithmisation, mais l’architecture et le design sont entre vos mains, du début à la fin.

Juste pour se rendre compte à quel point le style { try:, except:, finally: } d’un collimateur d’infrastructure de signalisation ZeroMQ / système / partie / ZeroMQ est plus grand, vérifiez le [SoW] uniquement par numéro de ligne:

 14544 - 14800 // a safe infrastructure setup on aMiniRESPONDER side ~ 256 SLOCs 15294 - 15405 // a safe infrastructure graceful termination ~ 110 SLOCs 

par rapport à la logique de base du segment de traitement d’ aMiniRESPONDER exemple aMiniRESPONDER

 14802 - 15293 // aMiniRESPONDER logic, incl. EXC-HANDLERs ~ 491 SLOCs 

Une note finale sur les systèmes dissortingbués basés sur ZeroMQ

Exigeant? Oui, mais très puissant, évolutif, rapide et même gratifiant pour une utilisation correcte. N’hésitez pas à investir votre temps et vos efforts pour acquérir et gérer vos connaissances dans ce domaine. Tous vos projets logiciels pourraient bénéficier de cet investissement professionnel.

Je ne peux que partiellement répondre à cette question. Je ne sais pas pourquoi le processus serait suspendu après 2-3 jours.

Dans l’ensemble, un script PHP est chargé une fois au moment de l’exécution du script, il ne semble y avoir aucun moyen de contourner cette limitation. Cependant, votre code actuel peut être réécrit comme suit:

someFile.php

 $context = new ZMQContext(1); // Socket to talk to clients $responder = new ZMQSocket($context, ZMQ::SOCKET_REP); $responder->bind("tcp://*:5555"); while (true) { $request = $responder->recv(); printf ("Received request: [%s]\n", $request); $subscriptParams = [ "Request" => $request //Add more parameters here as needed ]; $result = shell_exec("php work.php ".base64_encode(serialize($subscriptParams))); // Send reply back to client $responder->send("Basic Reply"); } 

work.php

 if (!isset($argv[0])) { die("Need an argument"); } $params = unserialize(base64_decode($argv[0])); //Validate parameters $request = $params["Request"]; // Do some 'work' //Process push notifications here! sleep (1); 

Voici mes hypothèses:

  1. La partie configuration du script, par exemple en définissant $context et $responder , restra constante pour toujours (ou vous pourriez vivre avec le temps d’arrêt requirejs pour redémarrer le script en raison des modifications apscopes).

  2. Le début et la fin de la boucle restnt constants, mon idée est que shell_exec renverra une réponse pouvant être utilisée par le répondeur comme réponse réelle.

Quelques clarifications supplémentaires:

J’utilise serialize pour passer un tableau d’arguments que work.php devra utiliser. Je fais un décodage d’encodage en base64 parce que je veux m’assurer que l’argument entier tiendra bien dans $argv[0] et ne sera pas divisé sur les espaces potentiels trouvés dans les arguments.

La même combinaison serialize -> base64_encode et base64_decode -> deserialize peut être utilisée pour le résultat de work.php .

Notez que je n’ai pas personnellement essayé ce code, je ne peux donc pas garantir que cela fonctionne. Je ne vois pas pourquoi il ne devrait pas fonctionner (assurez-vous que php est sur votre chemin ou appelez /usr/bin/php dans votre shell_exec si ce n’est pas le cas).

Il est à noter que cette solution sera beaucoup plus lente que d’avoir tout le code dans un fichier, mais c’est le coût de rafraîchir le script à chaque itération.

Q2: Et comment faire cela?

Selon moi, la bonne façon de faire est de choisir la meilleure option disponible au début afin de ne pas investir de temps dans une méthode qui vous donnerait des résultats de deuxième année. Je n’ai rien contre ZeroMQ même si je suis la logique que les programmeurs doivent toujours s’efforcer de faire le code le plus propre et d’utiliser les meilleurs outils possibles. Dans le cas de la création d’une queue de messages avec PHP, vous auriez beaucoup plus de succès avec Pheanstalk : https://github.com/pda/pheanstalk

C’est une option open source hautement recommandée en ligne et fonctionne parfaitement sur Linux. L’installation de la queue est très simple et j’ai écrit une réponse complète sur la façon d’installer pheanstalk dans le sujet suivant: Impossible de faire fonctionner Beanstalkd Queue pour PHP

Pheanstalk utilise la bibliothèque beanstalkd, qui est très légère et efficace. Pour préparer une queue de messages comme le suggère votre question, vous pouvez le faire avec deux scripts php simples:

Producteur de message:

 useTube("my_queue") ->put("Hello World"); ?> 

Script de travail:

 watch('testtube') ->ignore('default') ->reserve())//retreives the job if there is one in the queue { echo $job->getData();//echos the message $pheanstalk->delete($job);//deletes the job from the queue } } ?> 

Le générateur de messages serait inclus dans une page où un utilisateur créerait un message et qui serait envoyé à une queue générée par beanstalkd. Le script de travail peut être conçu de différentes manières. Vous pouvez le placer dans une boucle while pour rechercher une nouvelle queue chaque seconde, et vous pouvez même demander à plusieurs employés de rechercher la queue. Pheanstalk est très efficace et fortement recommandé.