Condividi tramite


Modello di consumatori concorrenti

Consentire a più consumer concorrenti di elaborare i messaggi ricevuti sullo stesso canale di messaggistica. Con più consumer simultanei, un sistema può elaborare più messaggi contemporaneamente per ottimizzare la velocità effettiva, migliorare la scalabilità e la disponibilità e bilanciare il carico di lavoro.

Contesto e problema

Un'applicazione cloud spesso gestisce un numero elevato di richieste. Anziché elaborare ogni richiesta in modo sincrono, l'applicazione può passare le richieste tramite un sistema di messaggistica a un servizio consumer che le gestisce in modo asincrono. Questa strategia aiuta a impedire che l'elaborazione delle richieste blocchi la logica di business dell'applicazione.

Il numero di richieste può variare in modo significativo nel tempo. Un aumento improvviso delle attività degli utenti o delle richieste aggregate provenienti da più tenant può creare un carico di lavoro imprevedibile. Nelle ore di punta, un sistema potrebbe dover elaborare molte centinaia di richieste al secondo. In altri casi, il numero potrebbe essere ridotto. Inoltre, il lavoro necessario per gestire queste richieste potrebbe variare notevolmente. Se si usa una singola istanza del servizio consumer, le richieste possono sovraccaricare tale istanza. Oppure un flusso di messaggi dell'applicazione può sovraccaricare il sistema di messaggistica.

Per gestire questo carico di lavoro fluttuante, il sistema può eseguire più istanze del servizio consumer. Tuttavia, il sistema deve coordinare questi consumer per garantire che ogni messaggio venga recapitato a un solo consumer. Il sistema deve anche bilanciare il carico di lavoro tra i consumatori per impedire che un'istanza diventi un collo di bottiglia.

Soluzione

Usare una coda di messaggi per implementare il canale di comunicazione tra l'applicazione e le istanze del servizio consumer. L'applicazione invia richieste come messaggi alla coda e le istanze del servizio consumer ricevono ed elaborano i messaggi dalla coda. Questo approccio consente allo stesso pool di istanze del servizio consumer di gestire i messaggi da qualsiasi istanza dell'applicazione. Il diagramma seguente illustra come una coda di messaggi distribuisce il lavoro alle istanze del servizio.

Diagramma che mostra come una coda di messaggi distribuisce il lavoro alle istanze del servizio.

Annotazioni

Molteplici consumer ricevono questi messaggi, ma il modello Consumer concorrenti differisce dal modello Publisher-Subscriber. Nel modello dei Consumer concorrenti, un consumatore riceve ogni messaggio per il processamento. Nel modello di Publisher-Subscriber tutti i consumer ricevono ogni messaggio.

Questa soluzione offre i vantaggi seguenti:

  • Fornisce un sistema a livello di carico in grado di gestire variazioni ampie nel volume delle richieste dalle istanze dell'applicazione. La coda funge da buffer tra le istanze dell'applicazione e le istanze del servizio consumer. Questo buffer può ridurre al minimo l'effetto sulla disponibilità e sulla velocità di risposta per le istanze dell'applicazione e del servizio. Per ulteriori informazioni, consultare il modello di livellamento del carico basato su coda. Un messaggio che richiede un'elaborazione a esecuzione prolungata non impedisce ad altre istanze del servizio consumer di elaborare contemporaneamente altri messaggi.

  • Migliora l'affidabilità. Se un produttore comunica direttamente con un consumatore invece di utilizzare questo schema e non monitora il consumatore, rischia di perdere messaggi o di non elaborarli correttamente quando il consumatore fallisce. In questo modello, il sistema non invia messaggi a un'istanza del servizio specifica. Un'istanza del servizio non riuscita non blocca un producer e qualsiasi istanza del servizio funzionante può elaborare i messaggi.

  • Non richiede un coordinamento complesso tra consumatori o tra istanze di produttore e consumatore. La coda di messaggi assicura che ogni messaggio sia recapitato almeno una volta.

  • È scalabile. Quando si applica la scalabilità automatica, il sistema può aumentare o diminuire dinamicamente il numero di istanze del servizio consumer man mano che il volume dei messaggi varia.

  • Se la coda di messaggi fornisce operazioni di lettura transazionali, può migliorare la resilienza. Se un'istanza del servizio consumer legge ed elabora un messaggio come parte di un'operazione transazionale e ha esito negativo, questo modello può garantire che il messaggio venga restituito alla coda in modo che un'altra istanza del servizio consumer possa elaborarla. Per ridurre il rischio di errori continui nei messaggi, si consiglia di utilizzare code di messaggi inattivi.

Problemi e considerazioni

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

  • Ordinamento dei messaggi: L'ordine in cui le istanze del servizio consumer ricevono messaggi non è garantito e non mostra necessariamente l'ordine in cui sono stati creati i messaggi. Progettare il sistema in modo da elaborare i messaggi in modo idempotente. Questa progettazione consente di eliminare le dipendenze degli ordini di elaborazione.

    Il bus di servizio di Azure può implementare un ordinamento first-in-first-out garantito di messaggi e altri modelli usando sessioni di messaggi.

  • Requisiti di resilienza dei servizi: Se il sistema rileva e riavvia istanze del servizio non riuscite, potrebbe essere necessario implementare le operazioni eseguite da tali istanze del servizio come idempotenti per ridurre al minimo gli effetti quando recupera ed elabora un singolo messaggio più di una volta.

  • Rilevamento messaggi inaccettabili: Un messaggio in formato non valido o un'attività che richiede l'accesso a risorse non disponibili può causare un errore di istanza del servizio. Il sistema deve impedire che questi messaggi tornino alla coda per un periodo illimitato e invece acquisiscano e archiviano i relativi dettagli altrove per l'analisi, se necessario. Il Service Bus invia automaticamente i messaggi a una coda di messaggi non recapitabili dopo che il conteggio di consegna supera la soglia impostata MaxDeliveryCount.

  • Gestione dei risultati: L'istanza del servizio che gestisce un messaggio è completamente disaccoppiata dalla logica dell'applicazione che genera il messaggio, quindi potrebbe non essere in grado di comunicare direttamente. Se l'istanza del servizio genera risultati che devono tornare alla logica dell'applicazione, archiviare queste informazioni in un percorso a cui entrambi i componenti possono accedere. Per evitare che la logica dell'applicazione recuperi dati incompleti, il sistema deve indicare al termine dell'elaborazione. Un processo di lavoro può passare i risultati alla logica dell'applicazione tramite una coda di risposta dedicata ai messaggi. La logica dell'applicazione deve essere in grado di correlare questi risultati con il messaggio originale.

  • Ridimensionamento del sistema di messaggistica: In una soluzione su larga scala, un volume di messaggi elevato può sovraccaricare una singola coda di messaggi e trasformarlo in un collo di bottiglia del sistema. In questo caso, prendere in considerazione di partizionare il sistema di messaggistica per inviare messaggi da produttori specifici a una coda specifica o bilanciare il carico per distribuire i messaggi tra più code di messaggistica.

  • Affidabilità del sistema di messaggistica: Usare un sistema di messaggistica affidabile per garantire che i messaggi non vengano persi dopo che l'applicazione li accoda. Questa funzionalità è essenziale per garantire che tutti i messaggi vengano recapitati almeno una volta.

Quando usare questo modello

Usare questo modello quando:

  • Il carico di lavoro dell'applicazione è suddiviso in attività che possono essere eseguite in modo asincrono.

  • Le attività sono indipendenti e possono essere eseguite in parallelo.

  • Il volume di lavoro è altamente variabile e richiede una soluzione scalabile.

  • La soluzione deve fornire alta disponibilità e rimanere affidabile quando si verifica un errore nell'elaborazione delle attività.

Questo modello potrebbe non essere adatto quando:

  • Non è possibile separare facilmente il carico di lavoro dell'applicazione in attività discrete o esiste un livello elevato di dipendenza tra le attività.

  • Le attività devono essere eseguite in modo sincrono e la logica dell'applicazione deve attendere il completamento di ogni attività prima che continui.

  • Le attività devono essere eseguite in una sequenza specifica.

Annotazioni

Alcuni sistemi di messaggistica supportano sessioni che consentono a un gruppo di produttori di raggruppare i messaggi e assicurano che lo stesso consumatore gestisca tutti i messaggi nel gruppo. È possibile usare questo meccanismo con messaggi con priorità quando è supportato per applicare l'ordinamento dei messaggi e recapitare i messaggi in sequenza da un producer a un singolo consumer.

Progettazione del carico di lavoro

Valutare come usare il modello Consumatori concorrenti nella progettazione di un carico di lavoro per raggiungere 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
decisioni di progettazione dell'affidabilità consentono al carico di lavoro di diventare resiliente a un malfunzionamento e assicurano che ripristini a uno stato completamente funzionante dopo che si verifica un guasto. Questo modello crea ridondanza nell'elaborazione delle code considerando i consumer come repliche, pertanto un errore dell'istanza non impedisce ad altri consumer di elaborare i messaggi della coda.

- Ridondanza RE:05
- Processi in background
L'ottimizzazione dei costi è incentrata sul mantenimento e sul miglioramento del ritorno del carico di lavoro sugli investimenti. Questo modello consente di ottimizzare i costi perché viene ridimensionato in base alla profondità della coda e può essere ridotto a zero quando la coda è vuota. Può anche ottimizzare i costi perché è possibile limitare il numero massimo di istanze consumer simultanee.

- CO:05 Ottimizzazione del tasso
- Costi dei componenti CO:07
l'efficienza delle prestazioni consente al carico di lavoro soddisfare in modo efficiente le richieste tramite ottimizzazioni di ridimensionamento, dati e codice. Questo modello distribuisce il carico tra i nodi consumer per aumentare l'utilizzo e il ridimensionamento dinamico in base alla profondità della coda riduce al minimo l'overprovisioning.

- PE:05 Ridimensionamento e partizionamento
- PE:07 Codice e infrastruttura

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

Esempio

Azure fornisce code di Service Bus e trigger di coda delle Funzioni di Azure che insieme implementano direttamente questo modello di progettazione cloud. Le funzioni si integrano con il bus di servizio tramite trigger e associazioni. Questa integrazione consente di creare funzioni che utilizzano i messaggi della coda dai server di pubblicazione. Le applicazioni pubblicano messaggi in una coda e i consumer implementati come Funzioni possono recuperare e gestire tali messaggi.

Per la resilienza, una coda di Service Bus consente a un consumatore di usare la modalità PeekLock quando recupera un messaggio dalla coda. Questa modalità mantiene il messaggio ma lo nasconde ad altri consumer. Il runtime di Funzioni riceve un messaggio in modalità PeekLock. Se la funzione viene completata correttamente, il runtime chiama Complete sul messaggio. Se la funzione non riesce, il runtime potrebbe chiamare Abandon e rendere nuovamente visibile il messaggio in modo che un altro consumer possa recuperarlo. Se la funzione viene eseguita più a lungo del timeout PeekLock, il runtime rinnova automaticamente il blocco finché la funzione è in esecuzione.

Diagramma che usa il bus di servizio per distribuire il lavoro in Funzioni.

Funzioni ridimensiona automaticamente il numero di istanze consumer in base alla profondità della coda e al traffico. Questa scalabilità consente alla soluzione di gestire picchi di lavoro riducendo al minimo i costi durante periodi di basso volume. Se le funzioni creano più istanze, esse competono recuperando e elaborando messaggi in modo indipendente. Per altre informazioni, vedere Code delle code, degli argomenti e delle sottoscrizioni del Service Bus e trigger del Service Bus per funzioni.

Per altre informazioni su come usare la libreria client del bus di servizio per .NET per inviare messaggi a una coda del bus di servizio, vedere gli esempi pubblicati.

Passaggi successivi

  • Scegliere un servizio di messaggistica in Azure: informazioni su come diversi servizi di messaggistica di Azure, ad esempio bus di servizio, code di Archiviazione di Azure, Hub eventi di Azure e Griglia di eventi di Azure supportano modelli di comunicazione asincroni e come scegliere il servizio e il modello di messaggistica corretti per lo scenario.

  • Procedure consigliate per la scalabilità automatica: informazioni su come progettare soluzioni che aumentano il numero di istanze consumer in base al carico di lavoro, ad esempio la lunghezza della coda o la velocità effettiva dei messaggi, in modo che sia possibile gestire il carico di picco e controllare i costi durante i periodi di bassa attività.

  • Modello di consolidamento delle risorse di calcolo: è possibile consolidare più istanze di un servizio consumer in un unico processo per ridurre i costi e il sovraccarico di gestione. Il modello di consolidamento delle risorse di calcolo descrive i vantaggi e i compromessi di questo approccio.

  • Modello di livellamento del carico basato su coda: una coda di messaggi può aggiungere resilienza al sistema. La resilienza consente alle istanze del servizio di gestire volumi molto diversi di richieste provenienti dalle istanze dell'applicazione. La coda di messaggi funge da buffer che livelli il carico. Il modello di livellamento del carico basato sulle code descrive questo scenario in modo più dettagliato.