Une fois n’est pas coutume, voici un article particulièrement technique.
Le développement d’applications connectées est quelque chose d’à la fois important et délaissé. Important car cela constitue la base de l’informatique moderne, et que c’est une chose qui est enseignée dans tous les cursus informatiques. Délaissé car l’écrasante majorité des applications connectées actuelles sont basées sur le protocole HTTP.
L’omniprésence du HTTP est globalement une très bonne chose : Pas besoin de redévelopper la roue (les serveurs Apache et IIS sont là depuis longtemps, Nginx et Lighttpd cherchent à prendre la relève), les développements sont facilités (le protocole est simple, son utilisation est rapide), et un très grand choix d’applications est accessible de manière unifiée (il suffit de voir toutes les API REST disponibles). Cela a créé un écosystème applicatif dynamique.
Mais il y a aussi un inconvénient : Il devient difficile de sortir de ce modèle.
- Soit les développeurs ne savent pas faire de développement réseau. Ils ont bien appris la théorie du client-serveur à l’école, mais ne l’ont jamais appliquée autrement qu’en faisant du code PHP, Java ou .NET qui tourne sur un serveur HTTP.
- Soit les développeurs n’ont pas fait de développement réseau depuis tellement longtemps qu’ils ne savent même plus par où commencer. Ils ont perdu les compétences nécessaires, et doivent presque repartir de zéro.
- Soit les développeurs deviennent fainéants et ne veulent plus s’embêter à réfléchir autrement qu’en faisant du client-serveur basique en utilisant le protocole HTTP.
Et pourtant, être capable de développer des applications qui utilisent le réseau de manière différente est vital. Cela ouvre l’esprit à de nouveaux types de programmes, ce qui est parfois nécessaire pour mettre en place une fonctionnalité qui ne peut pas se satisfaire d’un fonctionnement simpliste.
ZeroMQ
ZeroMQ est une bibliothèque permettant de créer des applications client-serveur. Elle a un triple intérêt :
- Elle offre des possibilités nouvelles. Plutôt que de se casser la tête dès qu’on veut sortir un peu du client-serveur habituel, ZeroMQ met à notre disposition tout un arsenal de nouveaux types de connexions. La liste est longue : du client-serveur classique ; de l’envoi de données asynchrones avec load-balacing ; du “publish-subscribe” ; de la connexion multiple simultanée et transparente ; de la communication inter-threads (au sein d’un même processus), inter-processus (au sein de la même machine) et/ou inter-machines (au sein du même réseau).
- Elle est très simple à utiliser. Là où il faudrait normalement des dizaines de lignes de code, les choses se développent en quelques lignes, tout en restant très faciles à comprendre et à relire.
- Elle est très performante. ZeroMQ génère ses propres threads pour gérer ses connexions, et intègre des optimisations qui la rende généralement plus rapide que si vous ouvrez vos propres sockets brutes (oui, j’ai eu du mal à le croire moi aussi, mais c’est véridique).
En plus de cela, ZeroMQ est disponible sur un grand nombre de langages de programmation (34 à ce jour), ce qui permet de faire communiquer facilement des programmes écrits en PHP, en C, en C++, en Java, en C#, en Lua, …
Il y a toutefois une spécificité, qui peut être un inconvénient dans certains cas : ZeroMQ ne peut communiquer qu’avec ZeroMQ. Cela veut dire qu’il n’est pas possible d’utiliser cette bibliothèque pour se connecter à un serveur HTTP, FTP ou n’importe quel autre type de serveur qui utilise des sockets TCP/IP. Cela est dû au fait que ZeroMQ utilise son propre protocole d’échange de données, qui lui donne justement ses «super-pouvoirs», mais qui empêche de l’utiliser comme une bibliothèque de connexion universelle.
Principes de base
Avec ZeroMQ, on manipule des “sockets”. C’est un peu comme les sockets BSD habituelles, sauf qu’elles offrent une abstraction permettant de manipuler aussi bien des sockets réseau que des communications inter-threads ou inter-processus.
Par la force des choses, ZeroMQ reste basé sur les fondements de la communication client-serveur. Donc, quand on crée une socket ZMQ, il faut déterminer si elle va “écouter” (ce sera donc un serveur) ou si elle va se “connecter” (ce sera donc un client). Mais ZeroMQ fait une telle abstraction des choses qu’au final cela n’est pas si important. Vous pouvez avoir un “point stable” de votre application (que l’on pourrait donc considérer comme un serveur) qui va se connecter à plusieurs programmes éphémères (assimilables à des clients).
Si vous avez le temps, je vous conseille fortement de regarder la vidéo ci-dessous. Ian Barber y explique les concepts-clés de ZeroMQ. Ça dure une heure, mais ça vaut la peine. Pour vous faciliter le suivi de la conférence, vous trouverez ses slides en-dessous.
Exemple simple
Voici un petit exemple simple de client-serveur en PHP, inspiré de la conférence ci-dessus.
Le code du serveur :
$ctx = new ZMQContext(); $server = new ZMQSocket($ctx, ZMQ::SOCKET_REP); $server->bind("tcp://*:11111"); while (true) { $message = $server->recv(); $reply = strrev($message); $server->send($reply); }
On commence par créer un “contexte ZeroMQ”, qui sert à la bibliothèque pour faire ses initialisations. On crée ensuite une socket, en indiquant le type REP (“reply”, cette socket répond aux requêtes qui lui sont envoyées), puis on l’attache au port n°11111. Nous avons donc créé un serveur qui va accepter les connexions provenant du port 11111, depuis n’importe quelle interface réseau (d’où l’étoile devant le numéro de port). On voit bien qu’ils s’agit d’une socket TCP-IP grâce au préfixe «tcp://».
Le serveur tournera ensuite indéfiniment. Quand une connexion s’établit, il récupère le message qui lui a été envoyé, inverse le sens d’écriture de la chaîne reçue, puis la renvoie au client.
Le code du client :
$ctx = new ZMQContext(); $req = new ZMQSocket($ctx, ZMQ::SOCKET_REQ); $req->connect("tcp://localhost:11111"); $req->send("bonjour"); $response = $req->recv(); print("Réponse : '$response'\n");
On crée là encore un contexte, puis une socket de type REQ (“request”, cette socket va effectuer une requête). La socket est ensuite connectée au port 11111 sur la machine locale.
Le message “bonjour” est envoyé au serveur. La réponse est récupérée et affichée. Normalement, cela devrait donner comme résultat le texte suivant :
Réponse : 'ruojnob'
Cet exemple très simple montre à quel point ZeroMQ est facile d’utilisation.
Vous aurez remarqué que le serveur n’est capable que de traiter une seule requête à la fois. Dans le cas où le traitement est simple et rapide, cela ne pose pas de problème ; ZeroMQ place les requêtes entrantes dans une file, et le serveur va les traiter les unes après les autres.
Par contre, dans le cas où les traitements prennent du temps à être effectués, il est possible de mettre en place des stratégies variées :
- Faire du multi-processus, en “forkant” le serveur à chaque connexion entrante.
- Préparer à l’avance un certain nombre de processus “travailleurs” (je n’ai pas trouvé de meilleur terme pour traduire “worker”). Le serveur se contente alors de faire le passe-plat entre les clients et les travailleurs.
Communications request-reply
Le premier type de socket géré par ZeroMQ vous est maintenant familier grâce à l’exemple précédent. Les socket de type REQ (request) sont destinées à se connecter à des sockets de type REP (reply). Quand une socket REQ envoie un message à une socket REP, elle attend que cette dernière lui réponde. Tant que la réponse n’aura pas été reçue, il ne sera pas possible d’envoyer de message supplémentaire ; c’est du client-serveur basique.
Je vais toutefois en profiter pour vous montrer deux spécificités de ZeroMQ.
Dans l’exemple, nous avons une architecture qui ressemble à ceci :
Le serveur écoute sur un point d’entrée, et le client s’y connecte. Mais il aurait été possible de connecter la socket ZMQ du serveur à plusieurs points d’entrée :
Il est très simple de modifier notre serveur, pour lui demander d’écouter sur plusieurs ports TCP et sur un fichier IPC :
$ctx = new ZMQContext(); $server = new ZMQSocket($ctx, ZMQ::SOCKET_REP); $server->bind("tcp://*:11111"); $server->bind("tcp://*:22222"); $server->bind("ipc://file"); while (true) { $message = $server->recv(); $reply = strrev($message); $server->send($reply); }
Comme vous pouvez le voir, la seule modification tient dans l’ajout de deux attachements supplémentaire de la socket ZMQ. Ainsi, sans autre modification de code, le serveur écoutera désormais sur trois points d’entrée au lieu d’un seul.
Autre chose : comme je l’expliquais quand je vous parlais des principes de base de ZeroMQ, le sens de connexion des sockets ZMQ n’a pas vraiment de rapport avec le sens de communication de vos applications.
On pourrait très bien réécrire le client et le serveur de manière à obtenir l’architecture suivante :
Le serveur :
$ctx = new ZMQContext(); $server = new ZMQSocket($ctx, ZMQ::SOCKET_REP); $server->connect("tcp://localhost:11111"); while (true) { $message = $server->recv(); $reply = strrev($message); $server->send($reply); }
Le client :
$ctx = new ZMQContext(); $req = new ZMQSocket($ctx, ZMQ::SOCKET_REQ); $req->bind("tcp://*:11111"); $req->send("bonjour"); $response = $req->recv(); print("Réponse : '$response'\n");
Comme vous pouvez le voir, j’ai juste interverti les instructions d’écoute et de connexion. Mais comment cela peut-il fonctionner ? C’est la magie de ZeroMQ. Quand le serveur se lance, il tente de se connecter sur le port demandé ; tant que personne ne répondra à sa tentative de connexion, il attendra sagement. Dès que le client se met à écouter sur le port en question, le serveur s’y connecte. Une fois la connexion effectuée et gérée par ZeroMQ, l’application peut communiquer ; le client envoie sa requête, le serveur y répond.
Alors évidemment, cette «bizarrerie» peut sembler inutile. Un serveur qui se connecte, à quoi cela peut-il bien servir ? Il faut juste comprendre que grâce à ZeroMQ, la notion de client-serveur devient obsolète. D’un côté, il y a la notion de connexion (quel programme attend les connexions, quel programme se connecte) ; de l’autre côté, il y a la notion de communication (quel programme envoie des données, quel programme les reçoit).
Celui qui attend les connexions ne doit pas nécessairement être celui qui reçoit les données ; celui qui se connecte n’est pas obligatoirement celui qui envoie les données.
Communications push-pull
Le second type de communication géré par ZeroMQ est de type «pipeline». Un programme envoie des données, un autre les reçoit. C’est une communication unidirectionnelle asynchrone : l’émetteur n’a pas besoin d’attendre que le message ait été réceptionné avant de continuer son travail ; c’est du «fire and forget».
Nous allons donc avoir d’un côté une socket “PUSH”, correspondant à l’envoi de données, et de l’autre une socket “PULL”, qui reçoit des données. La plupart du temps, une socket “PULL” sera mise en place au niveau d’un serveur qui accepte des connexions venant de plusieurs clients qui feront du “PUSH”.
Voici le code d’un serveur qui se contente d’écrire sur sa sortie standard les chaînes qui lui sont envoyées :
$ctx = new ZMQContext(); $receiver = new ZMQSocket($ctx, ZMQ::SOCKET_PULL); $receiver->bind("tcp://*:1234"); while (true) { $message = $receiver->recv(); print("$message\n"); }
Voici le code d’un client, qui envoie au serveur l’heure courante dix fois de suite, en faisant une pause de 3 secondes entre chaque envoi :
$ctx = new ZMQContext(); $sender = new ZMQSocket($ctx, ZMQ::SOCKET_PUSH); $send->connect("tcp://localhost:1234"); for ($i = 0; $i < 10; $i++) { $sender->send(date('c')); sleep(3); }
Vous pouvez exécuter autant de client que vous le souhaitez, le serveur affichera les messages au fur et à mesure qu’il les recevra.
Communication publish-subscribe
Le troisième type de communication géré par ZeroMQ est un modèle d’abonnement. Un programme émet des messages, qui sont envoyés à tous ceux qui s’y sont abonnés préalablement.
Pour reprendre un modèle client-serveur traditionnel, on aura souvent un serveur qui émet des messages, et plusieurs clients qui s’y connectent pour recevoir les messages.
Voici un exemple de programme qui publie des données. Il envoie la date et heure courante toutes les 10 secondes :
$ctx = new ZMQContext(); $publisher = new ZMQSocket($ctx, ZMQ::SOCKET_PUB); $publisher->bind("tcp://*:1234"); while (true) { $message = date("c"); $publisher->send($message); }
Et voici le code d’un programme qui s’abonne au premier, et qui va écrire sur sa sortie standard toutes les données qu’il recevra :
$ctx = new ZMQContext(); $subscriber = new ZMQSocket($ctx, ZMQ::SOCKET_SUB); $subscriber->connect("tcp://localhost:1234"); $subscriber->setSockOpt(ZMQ::SOCKOPT_SUBSCRIBE, ""); while (true) { $message = $subscriber->recv(); print("Date : '$message'\n"); }
Comme vous pouvez le voir, cela reste toujours aussi simple. Ne vous stressez pas à cause de l’instruction setSockOpt() ; elle est nécessaire et peut se révéler très utile, mais je vous laisse découvrir ça par vous-même.
Load-balancing
Nous venons de voir que le cas du publish-subscribe est très spécifique. Le programme qui émet des données n’a ouvert qu’une seule socket, et plusieurs programmes vont recevoir les messages envoyés.
Dans certains cas, on voudrait au contraire pouvoir communiquer avec plusieurs programmes, en leur envoyant des données successivement et non pas simultanément. Cela peut être très pratique dans le cas d’un programme qui doit donner des ordres à des “travailleurs” (voir plus haut).
La marche à suivre est très simple : Après avoir créé une socket PUSH, il suffit de la connecter à plusieurs autres sockets PULL. Par la suite, à chaque fois qu’un message sera envoyé sur cette socket, il le sera sur un destinataire différent (en tournant en boucle sur l’ensemble des destinataires disponibles).
L’avantage de ce fonctionnement, c’est que ZeroMQ gère complètement le mécanisme. Qu’il y ait une connexion ou plusieurs dizaines/centaines, une fois que la connexion est faite le programme se contente d’envoyer des messages comme d’habitude. C’est très pratique et très puissant.
Pour aller plus loin
ZeroMQ est tellement simple à mettre en œuvre et rapide dans son exécution qu’il est conseillé de ne pas hésiter à l’utiliser en mélangeant plusieurs types de communications, pour former des applications complexes.
Par exemple, si vous avez besoin de créer une file de message, il suffit d’avoir un programme qui réceptionne des messages d’un côté, et qui les redistribue séquentiellement de l’autre.
ZeroMQ offre aussi un mécanisme de «polling», qui permet à un programme d’ouvrir plusieurs socket ZeroMQ en même temps, mais aussi des sockets classiques ou des descripteurs de fichiers (n’oubliez pas que l’entrée standard est un descripteur de fichier), puis d’attendre qu’une donnée arrive sur l’une de ces entrées, pour ensuite les traiter.
Que vous ayez besoin de créer une architecture distribuée ou simplement pour votre veille technologique, je ne peux que vous inciter à lire la documentation de ZeroMQ. Elle est assez longue à lire, mais ça en vaut la peine.
PHP, 0MQ… il fallait que je place ce lien: http://www.photon-project.com/
Oui, tout à fait. Pour tout dire, Photon est basé sur Mongrel2, qui facilite la création d’applications réparties, justement grâce à ZeroMQ.
Mais même en dehors de l’utilisation de tels frameworks, il me semble intéressant d’être capable de créer des applications distribuées et réparties. Et ZeroMQ est parfait pour y arriver.
J’ai entendu dire que PHP avait du mal à tourner comme daemon (à cause de fuite mémoire dans des bibliotheques externes).
Est ce que 0MQ fait parties des ces bibliotheques ?
@Paul : J’ai plusieurs réponses à apporter à ta question.
1. PHP tourne très bien en daemon (je prépare d’ailleurs une conférence sur ce sujet). Je fais tourner des daemons FineFS sans problème avec des uptimes de plusieurs mois, de très bonnes performances et aucune fuite mémoire.
2. Oui, certaines bibliothèques externes peuvent comporter des fuites de mémoire. C’est à contrôler durant les développements, quitte à mettre en place des solutions de contournement (se passer des bibliothèques en question, ou faire un fork et utiliser ces bibliothèques dans un sous-processus éphémère).
3. A priori, ZeroMQ est efficace dans sa gestion de la mémoire et ne contient pas de fuite. En tout cas, je n’en ai pas remarqué durant mes développements.
Merci pour cette initiation, je ne connaissais pas ce système, et si j’avais du faire du client-serveur sans HTTP, je serai passé par les Socket directement ce qui m’aurai valu une bonne perte de temps par rapport à ZeroMQ.
Armetiz.
zeroMq c’est génial, on peut faire plein de trucs…
J’ai commencé à développer un micro-framework autour de zeroMQ. Pour l’instant c’est plus à l’état de prototype mais ça marche pas trop mal.
– Pour la partie HTTP, c’est basé sur Mongrel2, les requètes sont réparties automatiquement en round-robin via zeroMq sur différents workers.
– On peut lancer un ensemble de task workers qui attendent pour éxecuter des tâches en arrière-plan. Exemple: envoyer des mails d’alertes, bref tout ce qui prends du temps à s’éxecuter…
– J’ai me suis même amuser à développer un daemon qui fait office de cache en mémoire, j’ai pas fait de comparatif en terme de perfs par rapport à Memcached mais c’est assez rapide.
– Un service RPC, là encore basé avec zeroMQ, le format d’échange est du Json. N’importe quel programme externe peut exécuté une action de ton controller.
Une fois que chaque worker a chargé toutes les classes nécessaire, c’est vraiment rapide, contrairement à un LAMP classique les fichiers sont chargé qu’une fois au démarrage du daemon. Par exemple sur mon netbook, un requête HTTP avec une vue simple mets environ 12-14ms à répondre au navigateur web.
Le code est ici : https://github.com/fguillot/kiwiFramework
Ce n’est qu’un prototype pour l’instant mais c’est prometteur vu comment zeroMQ est simple à utiliser.
J’ai développé cela en PHP 5.3, c’est peut-être plus rapide en Python ou en Ruby…
Question aux utilisateurs de 0MQ.
Des Workers s’abonne à un Router en disant:
je peux traiter les messages « W1 », « W »
je peux traiter « W »
je peux traiter « W3 »
Le router publie ces messages, donc PUB/SUB a priori.
Sauf que si worker2 s’arrete, j’aimerais que le router soit au courant et qu’ils puissent réémettre tous les messages que Worker2 n’a pas pu traiter le temps du down.
Y a t’il une facon « native » de faire ca avec 0MQ ?
Dans ton exemple, le premier worker pourra de toute manière traiter les messages «W», non ?
De manière générale, la réponse à ce genre de problématique est d’ajouter des canaux de communication (il ne faut pas hésiter, puisque c’est simple et peu “couteux” avec ZMQ).
Par exemple, tu prévois que tes workers fassent du PUSH en direction du broker, à chaque fois qu’ils reçoivent un PUB/SUB. Le broker compte le nombre de PUSH/PULL qu’il a reçu correspondant à chaque PUB. Si le PUB/SUB n’a “reçu” aucun PUSH/PULL, il sera renvoyé au bout d’un certain temps.
Hello,
Article interressant, meme si j’ai arreter le dev il y a quelques années. Je suis dans l’administration reseau et systeme.
Et en tant que prestataire, j’ai tres souvent des relations avec des sociétés de progiciel qui fournissent des applications en reseau… et j’avoue qu’aujourd’hui j’ai tendance a etre soulagé quand on me demande de placer du web sur un reseau, surtout si jamais il y a VPN. Il semble que la notion de performance est aujourd’hui perdu avec ce genre d’application, rien que ces 6 derniers mois j’ai eu 4 fois des problemes avec des appli differentes(de société differentes), il semble qu’une connexion SDSL 1 mega dédié ne suffit plus pour faire fonctionner 1 client… A croire que la programmation reseau est dediée a une elite :p
HTTP a un avantage énorme c’est les proxy !!!
Monter un proxy en frontal est primordiale pour une API, le proxy étant un filtre d’entrée (contrôle des URL au moins) et un parefeu (les hackeurs doivent se farcir le proxy avant d’attaquer le reste).
ZeroMQ a l’air super mais si c’est pour perdre les proxy … je n’y vois aucun gain (juste une grosse perte en sécurité).
Ps: voir Misc hors-série n°4 – A l’assaut du web.
Il ne faut pas voir ZeroMQ comme un concurrent de HTTP. ZMQ propose des fonctionnalités très intéressantes, qui dépassent les possibilités du protocole HTTP (et inversement).
Tu ne vois aucun gain à pouvoir écrire un publisher/subscriber en seulement 5 lignes de code ? À pouvoir séparer le sens de connexion de la logique applicative ?
ZMQ est un fantastique outil pour créer des architectures distribuées. Il permet d’écrire des programmes composés de modules découplés les uns des autres, répartis sur des threads, des processus et/ou des machines distinctes.
On aura tendance à l’utiliser pour construire des applications spécifiques, privées, pas pour faire du client/serveur au sens classique du terme.
Dire que ZMQ est moins bien que HTTP à cause des proxy, ça revient à dire que les files de messages n’apportent à rien par rapport aux filesystems, ou que les caches HTTP (Varnish, Squid) ne servent à rien puisque les bases de données ont du cache interne. Ou que le caramel est mieux que le chocolat. C’est complètement différent dans son utilité et son usage.
Il faut connaître chaque outil pour les utiliser à bon escient.
Déjà je reprend un point pour être sûr:
j’utilise ZMQ pour créer mon propre protocole de communication, pas vraiment pour refaire du HTTP.
http://zguide.zeromq.org/page:all#-MQ-is-Not-a-Neutral-Carrier
Donc je perd tout l’architecture qui va avec HTTP, dont les proxy qu’on peut transformer en parefeu applicatif:
http://en.wikipedia.org/wiki/Proxy_server#Filtering
Par exemple je peux utiliser un proxy pour filtrer les injections SQL ou toute autre chose. Par exemple, je me rend compte qu’il y a une faille sur un page (ex: info.php ne doit pas recevoir de champs mais en ajoutant ?show=users elle affiche les utilisateurs), le temps de développer un fix-it, on peut la bloquer depuis le proxy pour éviter un exploit.
Mais pour faire ça, j’ai besoin du HTTP car le proxy ne lit que ça.
Je vois très bien le gain pour le développement, mais je vois aussi la perte en sécurité. Surtout que ZMQ est fait pour le backen, c’est la partie la plus critique de l’architecture et c’est elle qui faut sur-protéger.
HTTP ça vend pas du rêve c’est vrai, mais en réseau on sait comment le sécuriser. Si vous faites quelque chose de nouveau, à votre charge de tout sécuriser.
Oui, je comprends bien ton point de vue.
Tu peux vouloir faire un match HTTP versus ZMQ, c’est ton droit. Tu trouveras toujours des arguments.
Mais le vrai match, c’est plutôt ZMQ versus socket BSD (et là, c’est ZMQ qui gagne).
Excellent article, d’autant plus que pour un sujet complexe comme ça en français ça aide !
keep up !
@Paul
Oui, … et non. En fait ZMQ ne propose pas de dispositif « natif » prenant en charge le failover, mais sa doc contient des HowTo avec du code pré-maché pour les langages les plus populaires pour des patterns de haut niveau.
http://zguide.zeromq.org/page:all#Chapter-Reliable-Request-Reply-Patterns
J’ai réalisé en Python un système client/serveur synchrone avec failover basé sur le pattern BinaryStar. Ce devrait être adaptable en PHP à peu de frais.
Très bonne présentation synthétique de ZMQ, toutefois pour moi néophyte en programmation réseau je ne perçois pas bien la différence entre bind() et connect(), dans la mesure où ils paraissent interchangeables :
Je suppose que l’implémentation de chacune des méthodes change selon que l’on a créé un socket de type request-reply, push-pull ou publish-subscribe (vrai ?), mais au moins en request-reply l’inversion des deux commandes entre client et serveur ne se traduit-elle aucunement en terme de performances ou de fonctionnalités ?
@Laïos : Non, ça ne dépend pas du type de socket, mais de qui attend qu’on se connecte à lui, et qui fait l’effort de se connecter à celui qui attend.
bind => le programme va écouter, en attendant que quelqu’un se connecte.
connect => le programme va se connecter
Mais ces concepts, qui jusqu’ici étaient très impactant dans la vision client-serveur, prennent une dimension différente avec ZeroMQ. Aucun changement en performance, mais ça te permet de « penser » ton architecture de manière très souple.
Au début, ça fait un peu bizarre de penser à un client qui écoute et un serveur qui se connecte. Mais au bout d’un moment, tu finis par penser ton architecture comme étant des entités qui communiquent entre elles, et non plus des clients et des serveurs.
plateforme de files de messages VS protocole de transport ????
ZeroMQ VS Socket BSD n’est pas plus pertinent.
Il existe des files de messages utilisant l’HTTP ( ex rabbitMQ).
Coté sécurité pas de souci : c’est à utiliser en back-office et si besoin un front classique (WS, HTTP) pour alimenter les files de messages.