Modello di coda di priorità

Classificare in ordine di priorità le richieste inviate ai servizi in modo che un carico di lavoro elabori le richieste con priorità alta più rapidamente rispetto a quelle con priorità inferiore. Questo approccio usa i messaggi inviati a una o più code ed è utile per le applicazioni che forniscono diversi livelli di servizio o contratti di servizio a diversi tipi di richiesta o clienti.

Contesto e problema

I carichi di lavoro potrebbero dover 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 di violazione.

Per gestire le attività in modo efficiente in base alla priorità, i carichi di lavoro necessitano di un meccanismo per elaborare ed eseguire le attività di conseguenza. Per impostazione predefinita, la maggior parte dei carichi di lavoro elabora le attività nell'ordine in cui arrivano, usando una struttura della coda FIFO (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é esclusivamente in base all'ordine di arrivo. L'applicazione o il producer che invia una richiesta assegna un valore di priorità al messaggio e i consumer elaborano i messaggi in base alla priorità. Il modello Priority Queue soddisfa i requisiti seguenti:

  • Gestisce 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.

  • Gestisce contratti di servizio diversi: Si offrono contratti di servizio diversi a clienti diversi ed è necessario garantire che i clienti con priorità elevata ricevano prestazioni e disponibilità migliori.

  • Supporta diverse esigenze di gestione dei carichi di lavoro: È disponibile un carico di lavoro che deve gestire immediatamente determinate attività, mentre le attività meno urgenti possono attendere.

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

  • Coda singola: A ogni messaggio viene assegnato un valore di priorità e tutti i messaggi usano la stessa coda.

  • Più code: A ogni messaggio viene assegnato un valore di priorità e i messaggi con priorità diversa usano code separate.

Coda singola

In un approccio a una singola coda, l'applicazione assegna una priorità a ogni messaggio e invia tutti i messaggi a una singola 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.

Più code

Più code separano i messaggi in base alla priorità. L'applicazione assegna una priorità a ogni messaggio e indirizza il messaggio alla coda che corrisponde alla priorità, in cui i consumer elaborano i messaggi. Una soluzione a più code può usare un singolo pool di consumer o più pool di consumer.

Pool di un singolo consumatore

In un'unica configurazione del pool, tutte le code condividono lo stesso pool di consumer. I consumer elaborano prima i messaggi dalla coda con priorità più alta ed elaborano i messaggi dalle code con priorità inferiore solo quando non sono presenti messaggi con priorità più alta. Di conseguenza, i singoli pool di consumer elaborano sempre messaggi con priorità più alta prima di quelli con priorità più bassa. Questa configurazione può causare un ritardo continuo dei messaggi con priorità inferiore e potenzialmente non elaborati.

Diagramma che illustra l'uso di un singolo pool di consumer per tutte le priorità.

Usare un singolo pool di consumer per i motivi seguenti:

  • Gestione semplice. Usare un singolo pool di consumer quando la configurazione e la manutenzione sono facili da configurare e gestire è una priorità. Un singolo pool riduce la complessità di configurazione e monitoraggio.

  • Esigenze di elaborazione unificata. Usare un singolo pool di consumer quando le attività in ingresso sono simili nel tipo.

Più pool di consumatori

In un pool di consumer multipli ogni coda ha un pool di consumer dedicato. Le code con priorità più alta usano più consumer o livelli di prestazioni superiori per elaborare i messaggi più rapidamente rispetto alle code con priorità inferiore.

Diagramma che illustra l'uso di pool di consumer separati per ogni priorità.

Usare più pool di consumer per i motivi seguenti:

  • Requisiti di prestazioni rigorosi. Usare 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. Usare più pool di consumer per le applicazioni quando l'affidabilità e l'isolamento degli errori sono critici e i problemi in una coda non devono influire sulle altre code.

  • Applicazioni complesse. Usare più pool di consumer per applicazioni complesse in cui diverse attività richiedono caratteristiche di elaborazione e garanzie di prestazioni diverse.

Problemi e considerazioni

Quando si decide come implementare questo modello, tenere presente quanto segue:

Raccomandazioni generali

  • Definire chiaramente le priorità. Stabilire livelli di priorità distinti e chiari rilevanti per la soluzione. Ad esempio, è possibile definire messaggi ad alta priorità come quelli che richiedono l'elaborazione entro 10 secondi. Identificare i requisiti dei consumer per la gestione degli elementi con priorità elevata e allocare le risorse necessarie di conseguenza.

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

  • Monitorare l'integrità della coda. Tenere traccia della profondità della coda, latenza di elaborazione, numero di recapito e velocità effettiva, in modo da poter rilevare backlog e rallentamenti prima che influiscano sul lavoro.

  • Usare code di messaggi non recapitabili. Spostare i messaggi non elaborabili in una coda di messaggi non recapitabili dopo un numero configurabile di tentativi di recapito, in modo che un messaggio non valido non blocchi il percorso di priorità.

  • Classificare in ordine di priorità i livelli di servizio. Implementare code con priorità per soddisfare le esigenze aziendali che richiedono disponibilità o prestazioni prioritarie. Ad esempio, i clienti con priorità elevata possono ricevere un livello di servizio superiore in modo da ottenere prestazioni e disponibilità migliori.

  • Prendere in considerazione l'elaborazione con priorità bassa. Decidere se tutti gli elementi con priorità alta devono essere elaborati prima di qualsiasi elemento con priorità inferiore. Se possibile, aumentare dinamicamente la priorità dei messaggi precedenti per garantire che i messaggi con priorità bassa vengano elaborati.

  • Ottimizzare e ridurre al minimo i costi. Elaborare immediatamente le attività critiche con i consumatori disponibili. Pianificare attività in background meno critiche durante gli orari meno occupati.

    Se si usa una singola coda, ottimizzare i costi ridimensionando il numero di consumer. I messaggi con priorità alta elaborano prima ma probabilmente più lentamente, mentre i messaggi con priorità più bassa potrebbero riscontrare ritardi più lunghi.

  • Proteggere i processori dai picchi di domanda. Se la frequenza di arrivo del produttore può superare la capacità di elaborazione dei consumatori, combinare questo schema con il modello di livellamento del carico basato su coda. Questo approccio memorizza nel buffer i picchi di traffico e impedisce l'overload delle risorse di elaborazione downstream.

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.

  • Implementare la precedenza e la sospensione. Se si usano più code con un singolo pool di consumer, implementare un algoritmo che garantisce che le code con priorità alta vengano sempre gestite prima delle code con priorità più bassa.

  • Prendere in considerazione i costi della coda. Tenere presente i costi finanziari associati al controllo e all'elaborazione delle code. Alcuni servizi di accodamento addebitano tariffe per la registrazione, il recupero e l'esecuzione di query sui messaggi. Queste tariffe possono aumentare con il numero di code.

Quando usare questo modello

Usare questo modello quando:

  • È necessario soddisfare diversi obiettivi di latenza o di servizio per diverse classi di lavoro, ad esempio premium e richieste standard dei clienti.

  • Il lavoro arriva in burst ed è necessario proteggere le operazioni critiche elaborando prima i messaggi con priorità alta mentre si rinvia il lavoro con priorità più bassa.

Questo modello potrebbe non essere adatto quando:

  • Tutti gli elementi di lavoro hanno un'importanza aziendale simile e l'elaborazione FIFO rigorosa è più importante rispetto alla pianificazione basata sulla priorità.

  • Le attività hanno dipendenze di ordinamento forte tra i livelli di priorità e il riordinamento del lavoro per priorità può causare risultati incoerenti o richiedere una logica di coordinamento complessa.

Progettazione del carico di lavoro

Valutare come usare il modello di coda priorità nella progettazione di un carico di lavoro per soddisfare gli obiettivi e i principi trattati nei pilastri di Azure Well-Architected Framework. La tabella seguente fornisce indicazioni su come questo modello supporta gli obiettivi di ogni pilastro.

Pilastro 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
l'efficienza delle prestazioni consente al carico di lavoro soddisfare in modo efficiente le richieste tramite ottimizzazioni di ridimensionamento, dati e 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

Se questo modello introduce compromessi all'interno di un pilastro, considerarli contro gli obiettivi degli altri pilastri.

Example

L'esempio di modello Di coda priorità in GitHub illustra un'implementazione del modello di coda priorità che usa bus di servizio di Azure argomenti e sottoscrizioni. L'esempio distribuisce un account di archiviazione sicuro, una risorsa di Application Insights per il monitoraggio e uno spazio dei nomi bus di servizio per abilitare la comunicazione tra le funzioni mittente e consumer.

La distribuzione include tre app per le funzioni: un mittente e due consumer. Le app consumer usano numero massimo di istanze diverse per simulare la definizione delle priorità dei messaggi. La funcPriorityQueueConsumerHigh funzione può aumentare fino a 200 istanze, mentre la funcPriorityQueueConsumerLow funzione è limitata a 40 istanze. Tutte le app per le funzioni usano il piano a consumo Flex e sono connesse ad Application Insights per la diagnostica e il monitoraggio.

Le assegnazioni di ruolo concedono l'accesso sicuro alle bus di servizio e all'archiviazione usando le identità gestite. Tutte le app per le funzioni condividono lo stesso account di archiviazione e la stessa risorsa di Application Insights. Questa configurazione centralizza l'osservabilità e la registrazione.

Il diagramma seguente illustra l'architettura della coda con priorità:

Diagram che illustra come implementare una coda di priorità usando bus di servizio.

Nel diagramma precedente:

  1. Applicazione (producer). L'applicazione PriorityQueueSender crea messaggi, assegna una proprietà dell'applicazione personalizzata denominata Priority a ogni messaggio e imposta il Priority valore su High o Low.

  2. Broker di messaggi e argomento. Il broker di messaggi bus di servizio invia messaggi a un singolo argomento bus di servizio denominato messages. bus di servizio usa filtri SQL per instradare ogni messaggio alla sottoscrizione con priorità alta o con priorità bassa, in base al relativo Priority valore.

  3. Più pool di consumer. I PriorityQueueConsumerHigh pool di consumer e PriorityQueueConsumerLow rispondono ai messaggi provenienti dalle sottoscrizioni con priorità alta o bassa usando trigger di Funzioni di Azure bus di servizio.

Ruolo nell'esempio Servizio Azure nell'esempio Nome nell'esempio
Applicazione (producer) App Funzioni di Azure PriorityQueueSender
Broker di messaggi Bus di servizio di Azure <spazio dei nomi del bus di servizio>
Argomento del messaggio Argomento del bus di servizio di Azure messages
Sottoscrizioni di messaggi sottoscrizioni bus di servizio di Azure highPriority
lowPriority
Consumatori App Funzioni di Azure PriorityQueueConsumerHigh
PriorityQueueConsumerLow

Passaggi successivi

  • bus di servizio code, argomenti e sottoscrizioni: esaminare le entità bus di servizio e le differenze tra code e argomenti.
  • Rilevamento duplicati: informazioni su come bus di servizio può rifiutare i messaggi duplicati quando un mittente ritenta dopo un invio incerto.
  • Code di messaggi non recapitabili: informazioni su come bus di servizio sposta i messaggi che non possono essere elaborati in una coda di messaggi non recapitabili per l'analisi o la rielaborazione.
  • Che cos'è archiviazione code di Azure?: esaminare i concetti di base di archiviazione code di Azure per confrontarlo con le code bus di servizio.

I modelli seguenti possono essere utili quando si implementa questo modello:

  • Queue-Based modello di livellamento del carico: usare una coda come buffer tra l'inserimento della richiesta e l'elaborazione. Usarlo con il modello Priority Queue quando è necessaria sia la protezione burst che la gestione differenziata.

  • Modello consumer concorrenti: implementare 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.

  • Modello di limitazione: implementare la limitazione usando le code per gestire le tariffe delle richieste. Usare la messaggistica con priorità per classificare in ordine di priorità le richieste da applicazioni critiche o clienti di alto valore rispetto a quelle meno importanti.