RabbitMQ et relation entre le canal et la connexion
Le client Java RabbitMQ {[5] } a les concepts suivants:
-
Connection
- une connexion à une instance de serveur RabbitMQ -
Channel
- ??? - pool de threads consommateurs-un pool de threads qui consomment des messages depuis les files D'attente du serveur RabbitMQ
- file d'attente-une structure qui contient des messages dans L'ordre FIFO
J'essaie de comprendre la relation, et plus important encore , les associations entre elles.
- je suis toujours pas tout à fait sûr de ce qu'est un
Channel
, à part le fait que c'est la structure à partir de laquelle vous publiez et consommez, et qu'elle est créée à partir d'une connexion ouverte. Si quelqu'un pouvait m'expliquer ce que le "canal" représente, cela pourrait aider à éclaircir quelques choses. - Quelle est la relation entre le canal et la file d'attente? Le même canal peut-il être utilisé pour communiquer aux Files d'attente multiples, ou doit-il être 1:1?
- Quelle est la relation entre la file D'attente et le Pool de consommateurs? Peut plusieurs consommateurs sont abonnés à la même file d'attente? Plusieurs Files d'attente peuvent-elles être consommées par le même consommateur? Ou est la relation 1: 1?
Merci d'avance pour toute aide ici!
3 réponses
Un
Connection
représente une véritable connexion TCP au courtier de messages, alors qu'unChannel
est une connexion virtuelle (connexion AMPQ) à l'intérieur. De cette façon, vous pouvez utiliser autant de connexions (virtuelles) que vous le souhaitez dans votre application sans surcharger le courtier avec des connexions TCP.-
, Vous pouvez utiliser un
Channel
pour tout. Cependant, si vous avez plusieurs threads, il est suggéré d'utiliser unChannel
différent pour chaque thread.Filetage de canal-sécurité dans Guide de l'API du client Java :
Les instances de canal sont sûres pour une utilisation par plusieurs threads. Les demandes en un canal sont sérialisés, avec un seul thread pouvant exécuter un commande sur le Canal à la fois. Même ainsi, les applications devraient préférer utiliser un canal par thread au lieu de partager le même canal plusieurs threads.
Il n'y a pas de relation directe entre
Channel
etQueue
. Un {[1] } est utilisé pour envoyer des commandes AMQP au courtier. Cela peut être le création d'une file d'attente ou similaire, mais ces concepts ne sont pas liés ensemble. -
Chaque
Consumer
s'exécute dans son propre thread alloué à partir du pool de threads consommateurs. Si plusieurs consommateurs sont abonnés à la même file d'attente, le courtier utilise round-robin pour distribuer les messages entre eux également. Voir deuxième tutoriel: "Files D'attente de travail" .Il est également possible d'attacher le même
Consumer
à plusieurs Files d'attente. Vous pouvez comprendre les consommateurs comme des rappels. Ceux-ci sont appelés chaque fois qu'un message arrive dans une file d'attente, le consommateur est tenu de le faire. Pour le cas du client Java, chaque consommateur a une méthodehandleDelivery(...)
, qui représente la méthode de rappel. Ce que vous faites généralement est, sous-classeDefaultConsumer
et overridehandleDelivery(...)
. Remarque: Si vous attachez la même instance Consumer à plusieurs files d'attente, cette méthode sera appelée par différents threads. Alors prenez soin de la synchronisation si nécessaire.
J'ai trouvé cet article qui explique tous les aspects du modèle AMQP, dont channel en est un. Je l'ai trouvé très utile pour compléter ma compréhension
Https://www.rabbitmq.com/tutorials/amqp-concepts.html
Certaines applications ont besoin de plusieurs connexions à un courtier AMQP. Cependant, il n'est pas souhaitable de garder de nombreuses connexions TCP ouvertes en même temps, car cela consomme des ressources système et rend plus difficile la configuration des pare-feu. AMQP 0-9-1 les connexions sont multiplexées avec des canaux qui peuvent être considérés comme des "connexions légères qui partagent une seule connexion TCP".
Pour les applications qui utilisent plusieurs threads / processus pour le traitement, il est très courant d'ouvrir un nouveau canal par thread/processus et de ne pas partager de canaux entre eux.
La Communication sur un canal particulier est complètement séparée de la communication sur un autre canal, par conséquent chaque méthode AMQP porte également un numéro de canal que les clients utilisez-le pour déterminer le canal pour lequel la méthode est utilisée (et donc, quel gestionnaire d'événements doit être appelé, par exemple).
Une bonne compréhension conceptuelle de ce que le protocole AMQP fait "sous le capot" est utile ici. Je proposerais que la documentation et L'API qu'AMQP 0.9.1 a choisi de déployer rendent cela particulièrement confus, donc la question elle-même est celle avec laquelle beaucoup de gens doivent lutter.
TL;DR
Une connexion {[8] } est le socket TCP négocié physique avec le serveur AMQP. Les clients correctement implémentés en auront un par application, thread-safe, sharable entre les threads.
Un canal {[8] } est une session d'application unique sur la connexion. Un thread aura une ou plusieurs de ces sessions. AMQP architecture 0.9.1 est que ceux-ci ne doivent pas être partagés entre les threads, et doivent être fermés/détruits lorsque le thread qui l'a créé est terminé avec lui. Ils sont également fermés par le serveur lorsque diverses violations de protocole se produisent.
Un consommateur est un virtuel construire que représente la présence d'une "boîte aux lettres" sur un particulier canal. L'utilisation d'un consommateur indique au courtier d'envoyer des messages d'une file d'attente particulière à ce point de terminaison de canal.
Faits De Connexion
Tout d'abord, comme d'autres l'ont correctement souligné, une connexion est l'objet qui représente la connexion TCP réelle au serveur. Les connexions sont spécifiées au niveau du protocole dans AMQP, et toute communication avec le courtier se fait sur une ou plusieurs connexions.
- Comme il s'agit d'une connexion TCP réelle, a une Adresse IP et des numéros de Port.
- les paramètres de protocole sont négociés sur une base par client dans le cadre de la configuration de la connexion (un processus connu sous le nom de handshake.
- Il est conçu pour être à longue durée de vie ; Il y a peu de cas où la fermeture de connexion fait partie de la conception du protocole.
- d'un point de vue OSI, il réside probablement quelque part autour de couche 6
- Heartbeats peut être configuré pour surveiller L'état de la connexion, comme TCP ne le fait pas contenir quoi que ce soit en soi pour le faire.
- Il est préférable qu'un thread dédié gère les lectures et les Écritures sur le socket TCP sous-jacent. La plupart, sinon tous, les clients RabbitMQ le font. À cet égard, ils sont généralement thread-safe.
- relativement parlant, les connexions sont "coûteuses" à créer (en raison de la poignée de main), mais pratiquement parlant, cela n'a vraiment pas d'importance. La plupart des processus n'auront vraiment besoin que d'un seul objet de connexion. Mais, vous pouvez maintenir des connexions dans un pool, si vous trouvez que vous avez besoin de plus de débit qu'un seul thread/socket peut fournir (peu probable avec la technologie informatique actuelle).
Informations Sur La Chaîne
Un Canal {[4] } est la session d'application qui est ouverte pour chaque élément de votre application pour communiquer avec le courtier RabbitMQ. Il fonctionne sur une seule connexion, un session avec le courtier.
- Comme il représente une partie logique de la logique d'application, chaque canal il existe sur son propre thread.
- généralement, tous les canaux ouverts par votre application partagent une seule connexion (ce sont des sessions légères qui fonctionnent au-dessus de la connexion). Les connexions sont thread-safe, donc C'est OK.
- La plupart des opérations AMQP ont lieu sur des canaux.
- du point de vue de la couche OSI, les canaux sont probablement autour de couche 7.
- les canaux sont conçus pour être transitoires ; une partie de la conception D'AMQP est que le canal est généralement fermé en réponse à une erreur (par exemple, re-déclarer une file d'attente avec des paramètres différents avant de supprimer la file d'attente existante).
- Comme ils sont transitoires, les canaux ne doivent pas être regroupés par votre application.
- Le serveur utilise un entier pour identifier un canal. Lorsque le thread gérant la connexion reçoit un paquet pour un canal particulier, il utilise ce numéro pour indiquer au courtier à quel canal/session le paquet appartient.
- canaux ne sont généralement pas thread-safe comme il aurait aucun sens de les partager entre les threads. Si vous avez un autre thread qui doit utiliser le courtier, un nouveau canal est nécessaire.
Faits Sur Les Consommateurs
Un consommateur est un objet défini par le protocole AMQP. Ce n'est ni un canal ni une connexion, au lieu d'être quelque chose que votre application particulière utilise comme une "boîte aux lettres" pour déposer des messages.
- "créer un consommateur" signifie que vous le dites au courtier (en utilisant un canal via une connexion ) que vous souhaitez que les messages vous soient envoyés sur ce canal. En réponse, le courtier enregistrera que vous avez un consommateur sur le canal et commencera à vous envoyer des messages.
- chaque message poussé sur la connexion référencera à la fois un numéro de Canal et un numéro de consommateur . De cette façon, le thread de gestion de connexion (dans ce cas, dans L'API Java) sait quoi faire avec le message; ensuite, le thread de gestion de canal sait quoi faire avec le message.
- L'implémentation du consommateur a la plus grande quantité de variation, car elle est littéralement spécifique à l'application. Dans mon implémentation, j'ai choisi de spin off une tâche chaque fois qu'un message arrivait via le consommateur; ainsi, j'avais un thread gérant la connexion, un thread gérant le canal (et par extension, le consommateur), et un ou plusieurs threads de tâche pour chaque message livré via le consommateur.
- fermeture d'une connexion ferme tous les canaux connexion. Fermeture d'un canal ferme tous les consommateurs sur le canal. Il est également possible de annuler un consommateur (sans fermer la chaîne). Il y a divers cas où il est logique de faire l'une des trois choses.
- typiquement, l'implémentation d'un consommateur dans un client AMQP allouera un canal dédié au consommateur pour éviter les conflits avec les activités d'autres threads ou code (y compris la publication).
En termes de ce que vous entendez par pool de threads consommateurs, je soupçonne que le client Java fait quelque chose de similaire à ce que j'ai programmé mon client (le mien était basé sur le client.Net, mais fortement modifié).