RabbitMQ e relazione tra canale e connessione


176

Il client RabbitMQ Java ha i seguenti concetti:

  • Connection - una connessione a un'istanza del server RabbitMQ
  • Channel - ???
  • Pool di thread consumer: un pool di thread che consumano messaggi dalle code del server RabbitMQ
  • Coda - una struttura che contiene i messaggi in ordine FIFO

Sto cercando di capire la relazione e , soprattutto , le associazioni tra loro.

  1. Non sono ancora del tutto sicuro di cosa Channelsia, a parte il fatto che questa è la struttura da cui pubblichi e consumi, e che è stata creata da una connessione aperta. Se qualcuno potesse spiegarmi cosa rappresenta il "Canale", potrebbe aiutare a chiarire alcune cose.
  2. Qual è la relazione tra canale e coda? Lo stesso canale può essere utilizzato per comunicare con code multiple o deve essere 1: 1?
  3. Qual è la relazione tra Queue e Consumer Pool? È possibile abbonarsi più consumatori alla stessa coda? È possibile consumare più code dallo stesso consumatore? O è la relazione 1: 1?

Grazie in anticipo per qualsiasi aiuto qui!


Le risposte a questa domanda mi hanno portato a segnalare questo problema con il client Golang piuttosto che porre la domanda qui.
Bruce Adams,

Il canale è un concetto logico utilizzato per multiplexare una singola connessione TCP fisica tra un client e un nodo. Il numero del canale è incluso nell'intestazione del messaggio del frame AMQP.
Natale,

Risposte:


196
  1. A Connectionrappresenta una vera connessione TCP al broker dei messaggi, mentre a Channelè una connessione virtuale (connessione AMQP) al suo interno. In questo modo è possibile utilizzare tutte le connessioni (virtuali) desiderate all'interno dell'applicazione senza sovraccaricare il broker con connessioni TCP.

  2. Puoi usarne uno Channelper tutto. Tuttavia, se si dispone di più thread, si consiglia di utilizzare un Channelthread diverso per ogni thread.

    Sicurezza del thread del canale nella Guida dell'API del client Java :

    Le istanze di canale sono sicure per l'uso da parte di più thread. Le richieste in un canale sono serializzate, con un solo thread in grado di eseguire un comando sul canale alla volta. Anche così, le applicazioni dovrebbero preferire l'uso di un canale per thread anziché condividere lo stesso canale su più thread.

    Non esiste una relazione diretta tra Channele Queue. A Channelviene utilizzato per inviare comandi AMQP al broker. Questa può essere la creazione di una coda o simile, ma questi concetti non sono collegati tra loro.

  3. Ciascuno Consumerviene eseguito nel proprio thread allocato dal pool di thread del consumatore. Se più consumatori sono abbonati alla stessa coda, il broker utilizza round-robin per distribuire equamente i messaggi tra loro. Vedi Tutorial due: "Code di lavoro" .

    È anche possibile collegare lo stesso Consumera più code. Puoi comprendere i consumatori come richiamate. Questi vengono chiamati ogni volta che arriva un messaggio su una coda a cui è legato il consumatore. Nel caso del client Java, ciascun consumatore ha un metodo handleDelivery(...), che rappresenta il metodo di callback. Quello che fai di solito è la sottoclasse DefaultConsumere l'override handleDelivery(...). Nota: se si collega la stessa istanza Consumer a più code, questo metodo verrà chiamato da thread diversi. Quindi prenditi cura della sincronizzazione, se necessario.


4
Solo per aggiungere dalla documentazione: I callback ai consumatori vengono inviati su un thread separato dal thread gestito dalla connessione. Ciò significa che i consumatori possono chiamare in modo sicuro metodi di blocco sulla connessione o sul canale, come queueDeclare, txCommit, basicCancel o basicPublish. Ogni canale ha il proprio thread di invio. Per il caso d'uso più comune di un consumatore per canale, ciò significa che i consumatori non trattengono altri consumatori. Se hai più consumatori per canale, tieni presente che un consumatore di lunga data può bloccare l'invio di callback ad altri consumatori su quel canale.
filip,

1
Se si collega la stessa istanza Consumer a più code dallo stesso canale, ciò significherebbe che i callback vengono inviati sullo stesso thread. In tal caso non avresti bisogno di sincronizzazione, vero?
filip

Posso utilizzare solo una connessione e utilizzare un pool di canali anziché un pool di connessioni? Ciò influirà sulla velocità di pubblicazione dei messaggi?
Qeek,

4
Penso che questo riferimento all'API client Java sia ormai obsoleto e in realtà il riferimento di oggi contraddice direttamente la citazione in questa risposta. Il riferimento di oggi dice "Le istanze del canale non devono essere condivise tra thread".
Edwin Dalorzo,

1
@EdwinDalorzo - sembra che chiunque abbia originariamente scritto la documentazione non abbia compreso appieno la dicotomia canale-connessione. L'architettura fondamentale di AMQP 0.9.1 tratta davvero un canale come una sessione, quindi thread diversi che condividono una sessione sono davvero senza senso. La mia ipotesi è che questo sia il motivo del cambiamento.
theMayer,

53

Una buona comprensione concettuale di ciò che il protocollo AMQP fa "sotto il cofano" è utile qui. Vorrei offrire che la documentazione e l'API che AMQP 0.9.1 ha scelto di distribuire rendono questo aspetto particolarmente confuso, quindi la domanda stessa è quella con cui molte persone devono confrontarsi.

TL; DR

Una connessione è il socket TCP negoziato fisico con il server AMQP. I client correttamente implementati ne avranno uno per applicazione, thread-safe, condivisibile tra i thread.

Un canale è una singola sessione dell'applicazione sulla connessione. Una discussione avrà una o più di queste sessioni. L'architettura AMQP 0.9.1 è che questi non devono essere condivisi tra i thread e devono essere chiusi / distrutti al termine del thread che l'ha creato. Inoltre, vengono chiusi dal server quando si verificano varie violazioni del protocollo.

Un consumatore è un costrutto virtuale che rappresenta la presenza di una "cassetta postale" su un determinato canale. L'uso di un consumatore indica al broker di inviare i messaggi da una determinata coda all'endpoint del canale.

Fatti di connessione

Innanzitutto, come altri hanno correttamente sottolineato, una connessione è l'oggetto che rappresenta la connessione TCP effettiva al server. Le connessioni sono specificate a livello di protocollo in AMQP e tutte le comunicazioni con il broker avvengono su una o più connessioni.

  • Poiché è una connessione TCP effettiva, ha un indirizzo IP e un numero di porta.
  • I parametri del protocollo vengono negoziati su una base per client come parte della configurazione della connessione (un processo noto come stretta di mano .
  • È progettato per essere longevo ; ci sono alcuni casi in cui la chiusura della connessione fa parte del progetto del protocollo.
  • Dal punto di vista OSI, risiede probabilmente da qualche parte attorno al Livello 6
  • Gli heartbeat possono essere impostati per monitorare lo stato della connessione, poiché TCP non contiene nulla in sé e per sé.
  • È preferibile che un thread dedicato gestisca le letture e le scritture nel socket TCP sottostante. La maggior parte, se non tutti, i clienti RabbitMQ lo fanno. A tale proposito, sono generalmente sicuri per i thread.
  • Relativamente parlando, le connessioni sono "costose" da creare (a causa della stretta di mano), ma praticamente parlando, questo non importa. La maggior parte dei processi avrà davvero bisogno di un solo oggetto di connessione. Tuttavia, è possibile mantenere le connessioni in un pool, se si ritiene che sia necessario un throughput maggiore di quello che può fornire un singolo thread / socket (improbabile con l'attuale tecnologia di elaborazione).

Fatti del canale

Un canale è la sessione dell'applicazione che viene aperta per ogni parte dell'app per comunicare con il broker RabbitMQ. Funziona su una singola connessione e rappresenta una sessione con il broker.

  • Poiché rappresenta una parte logica della logica dell'applicazione, ogni canale di solito esiste sul proprio thread.
  • In genere, tutti i canali aperti dalla tua app condivideranno una singola connessione (sono sessioni leggere che operano in cima alla connessione). Le connessioni sono thread-safe, quindi va bene.
  • La maggior parte delle operazioni AMQP avviene tramite canali.
  • Dal punto di vista del livello OSI, i canali sono probabilmente attorno al livello 7 .
  • I canali sono progettati per essere transitori ; parte della progettazione di AMQP è che il canale è in genere chiuso in risposta a un errore (ad es. dichiarare nuovamente una coda con parametri diversi prima di eliminare la coda esistente).
  • Poiché sono transitori, i canali non devono essere raggruppati dalla tua app.
  • Il server utilizza un numero intero per identificare un canale. Quando il thread che gestisce la connessione riceve un pacchetto per un determinato canale, utilizza questo numero per indicare al broker a quale canale / sessione appartiene il pacchetto.
  • I canali non sono generalmente sicuri per i thread in quanto non avrebbe senso condividerli tra i thread. Se si dispone di un altro thread che deve utilizzare il broker, è necessario un nuovo canale.

Fatti di consumo

Un consumatore è un oggetto definito dal protocollo AMQP. Non è né un canale né una connessione, ma è qualcosa che la tua particolare applicazione utilizza come una "cassetta postale" per eliminare i messaggi.

  • "Creazione di un consumatore" significa che dici al broker (usando un canale tramite una connessione ) che desideri che i messaggi ti vengano inviati su quel canale. In risposta, il broker registrerà che hai un consumatore sul canale e inizierà a inviarti messaggi.
  • Ogni messaggio inviato sulla connessione farà riferimento sia a un numero di canale che a un numero utente . In questo modo, il thread di gestione della connessione (in questo caso, all'interno dell'API Java) sa cosa fare del messaggio; quindi, il thread di gestione dei canali sa anche cosa fare con il messaggio.
  • L'implementazione del consumatore ha la più ampia gamma di variazioni, perché è letteralmente specifica per l'applicazione. Nella mia implementazione, ho scelto di escludere un'attività ogni volta che un messaggio arrivava tramite il consumatore; quindi, avevo un thread che gestiva la connessione, un thread che gestiva il canale (e per estensione, il consumatore) e uno o più thread di attività per ciascun messaggio recapitato tramite il consumatore.
  • La chiusura di una connessione chiude tutti i canali sulla connessione. La chiusura di un canale chiude tutti i consumatori sul canale. È anche possibile cancellare un consumatore (senza chiudere il canale). Ci sono vari casi in cui ha senso fare una delle tre cose.
  • In genere, l'implementazione di un consumatore in un client AMQP alloca un canale dedicato al consumatore per evitare conflitti con le attività di altri thread o codice (inclusa la pubblicazione).

In termini di cosa intendi per pool di thread dei consumatori, sospetto che il client Java stia facendo qualcosa di simile a quello che ho programmato per il mio client (il mio era basato sul client .Net, ma fortemente modificato).


1
"I canali non dovrebbero essere raggruppati", questo è quello che sto cercando
ospider

"Poiché sono transitori, i canali non devono essere raggruppati dalla tua app." - puoi chiarire come sei arrivato a questa conclusione, per favore. I documenti raccomandano il pooling di canali se l'implementazione di "un canale per thread" utilizza troppe risorse, vedere qui: rabbitmq.com/channels.html#resource-usage
Natale

@ymas - La documentazione a cui ti riferisci è speculativa e, a mio avviso, scarsa guida. Sto leggendo il codice sorgente e le specifiche del protocollo. I canali non devono essere raggruppati, punto. Inoltre, un canale per thread è una guida basata su questo stesso principio. Se scopri di avere così tanti canali aperti che il server è limitato dalle risorse, devi rivalutare la tua architettura (ovvero passare a uno schema ad alta disponibilità e / o ridurre la concorrenza).
theMayer

21

Ho trovato questo articolo che spiega tutti gli aspetti del modello AMQP, di cui il canale è uno. L'ho trovato molto utile per completare la mia comprensione

https://www.rabbitmq.com/tutorials/amqp-concepts.html

Alcune applicazioni richiedono più connessioni a un broker AMQP. Tuttavia, è indesiderabile mantenere aperte contemporaneamente molte connessioni TCP poiché ciò consuma risorse di sistema e rende più difficile la configurazione dei firewall. Le connessioni AMQP 0-9-1 sono multiplexate con canali che possono essere considerati "connessioni leggere che condividono una singola connessione TCP".

Per le applicazioni che utilizzano più thread / processi per l'elaborazione, è molto comune aprire un nuovo canale per thread / processo e non condividerne i canali.

La comunicazione su un determinato canale è completamente separata dalla comunicazione su un altro canale, quindi ogni metodo AMQP porta anche un numero di canale che i clienti usano per capire a quale canale è destinato il metodo (e quindi, quale gestore di eventi deve essere invocato, per esempio) .


4

Esiste una relazione tra come Una connessione TCP può avere più canali .

Canale : è una connessione virtuale all'interno di una connessione. Quando si pubblicano o consumano messaggi da una coda, tutto avviene su un canale Considerando Connessione : è una connessione TCP tra l'applicazione e il broker RabbitMQ.

Nell'architettura multi-threading, potrebbe essere necessaria una connessione separata per thread. Ciò può comportare una sottoutilizzazione della connessione TCP, inoltre aggiunge un sovraccarico al sistema operativo per stabilire tutte le connessioni TCP necessarie durante l'ora di punta della rete. Le prestazioni del sistema potrebbero essere drasticamente ridotte. Qui è dove il canale è utile, crea connessioni virtuali all'interno di una connessione TCP. Riduce immediatamente il sovraccarico del sistema operativo, inoltre ci consente di eseguire operazioni asincrone in un modo più veloce, affidabile e simultaneo. inserisci qui la descrizione dell'immagine

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.