Schema di coda di priorità

Bus di servizio di Azure

Il modello di coda con priorità consente a un carico di lavoro di elaborare le attività con priorità alta più rapidamente rispetto alle attività con priorità inferiore. Questo modello usa i messaggi inviati a una o più code ed è utile nelle applicazioni che offrono garanzie di servizio diverse ai singoli client.

Contesto e problema

I carichi di lavoro spesso devono gestire ed elaborare le attività con diversi livelli di importanza e urgenza. Alcune attività richiedono un'attenzione immediata, mentre altre possono attendere. La mancata gestione delle attività ad alta priorità può influire sull'esperienza utente e sui contratti di servizio (SLA).

Per gestire le attività in modo efficiente in base alla priorità, i carichi di lavoro devono disporre di un meccanismo per classificare in ordine di priorità ed eseguire le attività di conseguenza. In genere, i carichi di lavoro elaborano le attività nell'ordine in cui arrivano, usando una struttura di coda FIFO (First-In, First-In First Out). Questo approccio non tiene conto dell'importanza variabile delle attività.

Soluzione

Le code con priorità consentono ai carichi di lavoro di elaborare le attività in base alla priorità anziché all'ordine di arrivo. L'applicazione che invia un messaggio alla coda assegna una priorità al messaggio e i consumer elaborano i messaggi in base alla priorità. Usare il modello di coda di priorità quando si hanno i requisiti seguenti:

  • Gestire le attività di varia urgenza e importanza. Si dispone di attività con diversi livelli di urgenza e importanza ed è necessario assicurarsi di elaborare attività più critiche prima di quelle meno critiche.

  • Gestire contratti di servizio diversi. È possibile offrire garanzie a livello di servizio diverse per i client e assicurarsi che i client con priorità elevata ricevano prestazioni e disponibilità migliori.

  • Soddisfare diverse esigenze di gestione del carico di lavoro. Si dispone di un carico di lavoro che deve affrontare determinate attività immediatamente e meno urgenti attività possono attendere.

Esistono due approcci principali per implementare il modello di coda prioritaria:

  • Coda singola: tutti i messaggi vengono inviati a una coda e a ogni messaggio è assegnata una priorità.

  • Più code: per ogni priorità del messaggio vengono usate code separate.

Coda singola

Con una singola coda, l'applicazione (producer) assegna una priorità a ogni messaggio e invia il messaggio alla coda. La coda ordina i messaggi in base alla priorità, assicurandosi che i consumer eselaborino i messaggi con priorità più alta prima di quelli con priorità più bassa.

Diagramma che illustra un meccanismo di accodamento che supporta la definizione delle priorità dei messaggi.
Figura 1. Architettura di una singola coda e di un singolo pool di consumer

Più code

Più code consentono di separare il messaggio in base alla priorità. L'applicazione assegna una priorità a ogni messaggio e indirizza il messaggio alla coda corrispondente alla relativa priorità. I consumer elaborano i messaggi. Una soluzione a più code usa un singolo pool di consumer o più pool di consumer.

Più pool di consumer

Con più pool di consumer, ogni coda include risorse consumer dedicate. Le code con priorità più alta devono usare più consumer o livelli di prestazioni superiori per elaborare i messaggi più rapidamente rispetto alle code con priorità più bassa.

Usare più pool di consumer quando si dispone di:

  • Requisiti di prestazioni rigorosi: sono necessari più pool di consumer quando le diverse priorità delle attività hanno requisiti di prestazioni rigorosi che devono essere soddisfatti in modo indipendente.
  • Esigenze di affidabilità elevata: sono necessari più pool di consumer per le applicazioni in cui l'affidabilità e l'isolamento degli errori sono critici. I problemi in una coda non devono influire sulle altre code.
  • Applicazioni complesse: utile per applicazioni complesse con attività che richiedono caratteristiche di elaborazione e garanzie di prestazioni diverse per attività diverse.

Diagramma che illustra l'uso di code di messaggi separate per ogni priorità.
Figura 2. Architettura di più code e più pool di consumer.

Pool di consumer singolo

Con un singolo pool di consumer, tutte le code condividono un singolo pool di consumer. I consumer elaborano prima i messaggi dalla coda con priorità più alta ed elaborano solo i messaggi dalle code con priorità inferiore quando non sono presenti messaggi con priorità alta. Di conseguenza, il singolo pool di consumer elabora sempre messaggi con priorità più alta prima di quelli con priorità più bassa. Questa configurazione potrebbe causare un ritardo continuo dei messaggi con priorità inferiore e potenzialmente non elaborati.

Usare un singolo pool di consumer per:

  • Gestione semplice: un singolo pool di consumer è adatto per l'applicazione in cui la facilità di installazione e manutenzione è una priorità. Riduce la complessità della configurazione e del monitoraggio.
  • Esigenze di elaborazione unificata: un singolo pool di consumer è utile quando la natura esatta delle attività in ingresso è simile.

Diagramma che illustra l'uso di code di messaggi separate per ogni priorità.
Figura 3. Architettura di più code e di un singolo pool di consumer.

Raccomandazioni per il modello di coda priorità

Quando si decide come implementare il modello di coda di priorità, prendere in considerazione i consigli seguenti:

Raccomandazioni generali

  • Definire chiaramente le priorità. Stabilire livelli di priorità distinti e chiari rilevanti per la soluzione. Ad esempio, un messaggio ad alta priorità potrebbe richiedere l'elaborazione entro 10 secondi. Identificare i requisiti per la gestione degli elementi con priorità elevata e allocare di conseguenza le risorse necessarie.

  • Regolare dinamicamente i pool di consumer. Ridimensionare le dimensioni dei pool di consumer in base alla lunghezza della coda di manutenzione.

  • Classificare in ordine di priorità i livelli di servizio. Implementare code con priorità per soddisfare le esigenze aziendali che richiedono disponibilità o prestazioni con priorità. Ad esempio, i diversi gruppi di clienti possono ricevere diversi livelli di servizio in modo che i clienti con priorità elevata abbiano prestazioni e disponibilità migliori.

  • Verificare l'elaborazione con priorità bassa. Nelle code che supportano la definizione delle priorità dei messaggi, aumentare dinamicamente la priorità dei messaggi obsoleti se il sistema consente di garantire che i messaggi con priorità bassa vengano elaborati.

  • Prendere in considerazione i costi della coda. Tenere presente i costi finanziari ed elaborati associati alla verifica delle code. Alcuni servizi di accodamento applicano tariffe per la registrazione, il recupero e l'esecuzione di query sui messaggi, che possono aumentare con il numero di code.

Raccomandazioni su più code

  • Monitorare le velocità di elaborazione. Per garantire che i messaggi vengano elaborati a velocità previste, monitorare continuamente la velocità di elaborazione delle code con priorità alta e bassa.

  • Ridurre al minimo i costi. Elaborare immediatamente le attività critiche con i consumer disponibili. Pianificare attività in background meno critiche durante gli orari meno occupati.

Raccomandazioni per un singolo pool di consumer

  • Implementare la precedenza e la sospensione. Decidere se tutti gli elementi con priorità alta devono essere elaborati prima di qualsiasi elemento con priorità inferiore. Usare un algoritmo che garantisce che le code con priorità alta vengano sempre gestite prima delle code con priorità più bassa quando si usa un singolo pool di consumer per più code.

  • Ottimizzare i costi. Ottimizzare i costi operativi ridimensionando il numero di consumer quando si usa l'approccio a coda singola. I messaggi con priorità alta elaborano prima di tutto, anche se probabilmente più lentamente, mentre i messaggi con priorità più bassa potrebbero riscontrare ritardi più lunghi.

Progettazione del carico di lavoro

Un architetto deve valutare il modo in cui il modello di coda prioritaria può soddisfare gli obiettivi e i principi trattati nei pilastri di Azure Well-Architected Framework. Ad esempio:

Concetto fondamentale Come questo modello supporta gli obiettivi di pilastro
Le decisioni di progettazione dell'affidabilità consentono al carico di lavoro di diventare resilienti a malfunzionamenti e di assicurarsi che venga ripristinato in uno stato completamente funzionante dopo che si verifica un errore. La separazione degli elementi in base alla priorità aziendale consente di concentrare le attività di affidabilità sul lavoro più critico.

- Flussi critici RE:02
- RE:07 Processi in background
L'efficienza delle prestazioni consente al carico di lavoro di soddisfare in modo efficiente le richieste tramite ottimizzazioni in termini di scalabilità, dati, codice. La separazione degli elementi in base alla priorità aziendale consente di concentrare le attività di prestazioni sul lavoro più sensibile al tempo.

- Flussi critici PE:09

Come per qualsiasi decisione di progettazione, prendere in considerazione eventuali compromessi rispetto agli obiettivi degli altri pilastri che potrebbero essere introdotti con questo modello.

Esempio del modello di coda priorità

L'esempio seguente in GitHub illustra un'implementazione del modello Code con priorità usando bus di servizio di Azure.

Diagramma che mostra come implementare una coda di priorità usando bus di servizio.
Figura 4. Architettura dell'esempio PriorityQueue in GitHub

Ecco una panoramica dell'architettura:

  • Applicazione (producer):l'esempio include un'applicazione (PriorityQueueSender) che crea messaggi e assegna una proprietà personalizzata denominata Priority in ogni messaggio. Priority ha un valore pari High a o Low.

  • Broker di messaggi e code: l'esempio usa bus di servizio di Azure come broker di messaggi. Usa due code bus di servizio di Azure, una per ogni priorità del messaggio (High e Low). L'applicazione (producer) invia messaggi alla coda corretta in base al messaggio Priority.

  • Più pool di consumer: nell'esempio vengono usati più pool di consumer (PriorityQueueConsumerHigh e PriorityQueueConsumerLow) dedicati per leggere i messaggi da ognuna delle code.

Ruolo nell'architettura di esempio Servizio di Azure nell'esempio Nome nell'esempio
Applicazione App Funzioni di Azure PriorityQueueSender
Broker di accodamento messaggi Bus di servizio di Azure <spazio dei nomi del bus di servizio>
Code di messaggi Code del bus di servizio di Azure <nomi delle code>
Consumer App Funzioni di Azure PriorityQueueConsumerHigh
PriorityQueueConsumerLow

Quando si implementa questo modello, possono essere utili i modelli seguenti:

  • Modello consumer concorrenti: questo modello prevede l'implementazione di più consumer in ascolto della stessa coda e delle stesse attività di elaborazione in parallelo per aumentare la velocità effettiva. Ogni messaggio viene elaborato da un solo consumer. L'articolo fornisce informazioni dettagliate sui vantaggi e sugli svantaggi di questo approccio.

  • Modello di limitazione: questo modello può essere implementato usando le code per gestire le frequenze delle richieste. Usando la messaggistica con priorità, le richieste provenienti da applicazioni critiche o clienti ad alto valore possono essere classificate in ordine di priorità rispetto a quelle meno importanti.