Progettazione resiliente di Hub eventi e funzioni
La gestione degli errori, la progettazione per l'idempotenza e la gestione del comportamento di ripetizione dei tentativi sono alcune delle misure critiche che è possibile adottare per garantire che le funzioni attivate da Hub eventi siano resilienti e in grado di gestire grandi volumi di dati. Questo articolo illustra questi concetti cruciali e fornisce raccomandazioni per soluzioni di streaming di eventi serverless.
Azure offre tre principali servizi di messaggistica che possono essere usati con Funzioni di Azure per supportare un'ampia gamma di scenari univoci basati su eventi. A causa del modello consumer partizionato e della possibilità di inserire dati a una velocità elevata, Hub eventi di Azure viene comunemente usato per gli scenari di streaming di eventi e Big Data. Per un confronto dettagliato dei servizi di messaggistica di Azure, vedere Scegliere tra i servizi di messaggistica di Azure - Griglia di eventi, Hub eventi e bus di servizio.
Vantaggi e sfide per lo streaming
Comprendere i vantaggi e gli svantaggi dei flussi consente di apprezzare il funzionamento di un servizio come Hub eventi. Questo contesto è necessario anche quando si apportano decisioni di architettura, risoluzione dei problemi e ottimizzazione per le prestazioni. Considerare i concetti chiave seguenti sulle soluzioni con Hub eventi e Funzioni:
I flussi non sono code: Hub eventi, Kafka e altre offerte simili basate sul modello consumer partizionato non supportano intrinsecamente alcune delle funzionalità principali in un broker di messaggi come bus di servizio. Forse l'indicatore più grande di queste differenze è il fatto che le letture sono non distruttive. In questo modo si garantisce che i dati letti dall'host di Funzioni rimangano disponibili in un secondo momento. I messaggi non sono invece modificabili e rimangono per consentire ad altri consumer di leggere, incluso potenzialmente lo stesso consumer che lo legge nuovamente. Per questo motivo, le soluzioni che implementano modelli come i consumer concorrenti potrebbero essere meglio serviti con un broker di messaggi, ad esempio bus di servizio.
Supporto di messaggi non recapitabili intrinseci: un canale di messaggi non recapitabili non è una funzionalità nativa in Hub eventi o Kafka. Spesso, il concetto di messaggi non recapitabili è integrato in una soluzione di streaming per tenere conto dei dati che non possono essere elaborati. Questa funzionalità non è intenzionalmente un elemento innato in Hub eventi e viene aggiunta solo sul lato consumer per produrre un comportamento o un effetto simile. Se è necessario il supporto di messaggi non recapitabili, è consigliabile esaminare la scelta di un servizio di messaggi di streaming.
Un'unità di lavoro è una partizione: in un broker di messaggi tradizionale, un'unità di lavoro è un singolo messaggio. In una soluzione di streaming, una partizione viene spesso considerata l'unità di lavoro. Se ogni evento in un hub eventi viene considerato come un messaggio distinto che richiede l'elaborazione degli ordini o la gestione delle transazioni finanziarie, suggerisce un'opportunità per esplorare un servizio di messaggistica più adatto per prestazioni o elaborazione ottimali.
Nessun filtro sul lato server: uno dei motivi per cui Hub eventi è in grado di aumentare la scalabilità e la velocità effettiva è dovuta al basso sovraccarico del servizio stesso. Le funzionalità come il filtro lato server, gli indici e il coordinamento tra broker non fanno parte dell'architettura di Hub eventi. Le funzioni vengono usate occasionalmente per filtrare gli eventi instradandoli ad altri hub eventi in base al contenuto nel corpo o nell'intestazione. Questo approccio è comune nel flusso di eventi, ma viene fornito con l'avvertenza che la funzione iniziale legge e valuta ogni evento.
Ogni lettore deve leggere tutti i dati: poiché il filtro lato server non è disponibile, un consumer legge in sequenza tutti i dati in una partizione. Sono inclusi i dati che potrebbero non essere rilevanti o che potrebbero anche essere in formato non valido. È possibile usare diverse opzioni e strategie per compensare queste sfide, descritte più avanti in questa sezione.
Queste decisioni di progettazione significative consentono agli hub eventi di eseguire le operazioni migliori: supportano un flusso significativo di eventi e forniscono un servizio affidabile e resiliente da cui i consumer possono leggere. A ogni applicazione consumer viene assegnata la responsabilità di mantenere i propri offset lato client o cursori a tali eventi. Il basso sovraccarico rende Hub eventi un'opzione conveniente e potente per lo streaming di eventi.
Idempotenza
Uno dei set principali di Hub eventi di Azure è il concetto di recapito almeno una volta. Questo approccio garantisce che gli eventi vengano sempre recapitati. Significa anche che gli eventi possono essere ricevuti più volte, anche ripetutamente, dai consumer, ad esempio una funzione. Per questo motivo, è importante che una funzione attivata da hub eventi supporti il modello consumer idempotente.
Lavorare in base all'ipotesi di recapito almeno una volta, soprattutto nel contesto di un'architettura basata su eventi, è un approccio responsabile per l'elaborazione affidabile degli eventi. La funzione deve essere idempotente in modo che il risultato dell'elaborazione dello stesso evento più volte sia uguale all'elaborazione una sola volta.
Eventi duplicati
Esistono diversi scenari che potrebbero comportare la consegna di eventi duplicati a una funzione:
Checkpointing: se l'host Funzioni di Azure si arresta in modo anomalo o la soglia impostata per la frequenza del checkpoint batch non viene soddisfatta, non viene creato un checkpoint. Di conseguenza, l'offset per il consumer non è avanzato e la volta successiva che viene richiamata la funzione, riprenderà dall'ultimo checkpoint. È importante notare che il checkpoint si verifica a livello di partizione per ogni consumer.
Eventi duplicati pubblicati: molte tecniche possono ridurre le probabilità che lo stesso evento venga pubblicato in un flusso, ma il consumer è comunque responsabile della gestione dei duplicati in modo idempotente.
Riconoscimenti mancanti: in alcune situazioni, una richiesta in uscita a un servizio potrebbe avere esito positivo, ma un riconoscimento (ACK) dal servizio non viene mai ricevuto. Questa percezione potrebbe causare la convinzione che la chiamata in uscita non è riuscita e avviare una serie di tentativi o altri risultati dalla funzione. Alla fine, è possibile pubblicare eventi duplicati o non viene creato un checkpoint.
Tecniche di deduplicazione
La progettazione delle funzioni per l'input identico deve essere l'approccio predefinito adottato quando è associato all'associazione di trigger di Hub eventi. È consigliabile considerare le tecniche seguenti:
Ricerca di duplicati: prima dell'elaborazione, eseguire i passaggi necessari per verificare che l'evento debba essere elaborato. In alcuni casi, è necessaria un'indagine per verificare che sia ancora valida. Potrebbe anche essere possibile che la gestione dell'evento non sia più necessaria a causa dell'aggiornamento dei dati o della logica che invalida l'evento.
Progettare eventi per idempotenza: fornendo informazioni aggiuntive all'interno del payload dell'evento, è possibile garantire che l'elaborazione più volte non abbia effetti negativi. Si prenda l'esempio di un evento che include un importo da ritirare da un conto bancario. Se non gestito responsabilmente, è possibile che possa decrementare il saldo di un conto più volte. Tuttavia, se lo stesso evento include il saldo aggiornato al conto, potrebbe essere utilizzato per eseguire un'operazione di upsert al saldo del conto bancario. Questo approccio di trasferimento dello stato trasportato da eventi richiede occasionalmente il coordinamento tra produttori e consumatori e deve essere utilizzato quando ha senso partecipare ai servizi.
Gestione degli errori e tentativi
La gestione degli errori e i tentativi sono alcune delle qualità più importanti delle applicazioni distribuite, guidate dagli eventi e funzioni non fanno eccezione. Per le soluzioni di streaming di eventi, la necessità di un supporto appropriato per la gestione degli errori è fondamentale, poiché migliaia di eventi possono trasformarsi rapidamente in un numero uguale di errori se non vengono gestiti correttamente.
Istruzioni per la gestione degli errori
Senza la gestione degli errori, può essere difficile implementare nuovi tentativi, rilevare le eccezioni di runtime e analizzare i problemi. Ogni funzione deve avere almeno un livello o una gestione degli errori. Ecco alcune linee guida consigliate:
Usare Application Insights: abilitare e usare Application Insights per registrare gli errori e monitorare l'integrità delle funzioni. Tenere presente le opzioni di campionamento configurabili per gli scenari che elaborano un volume elevato di eventi.
Aggiungere la gestione degli errori strutturata: applicare i costrutti di gestione degli errori appropriati per ogni linguaggio di programmazione per rilevare, registrare e rilevare le eccezioni previste e non gestite nel codice della funzione. Ad esempio, usare un blocco try/catch in C#, Java e JavaScript e sfruttare i vantaggi dei blocchi try e except in Python per gestire le eccezioni.
Registrazione: intercettare un'eccezione durante l'esecuzione offre la possibilità di registrare informazioni critiche che possono essere usate per rilevare, riprodurre e risolvere in modo affidabile i problemi. Registrare l'eccezione, non solo il messaggio, ma il corpo, l'eccezione interna e altri artefatti utili in un secondo momento.
Non intercettare e ignorare le eccezioni: una delle cose peggiori che è possibile fare è intercettare un'eccezione e non eseguire alcuna operazione con essa. Se si rileva un'eccezione generica, registrarla da qualche parte. Se non si registrano errori, è difficile analizzare i bug e segnalare i problemi.
Nuovi tentativi
L'implementazione della logica di ripetizione dei tentativi in un'architettura di streaming di eventi può essere complessa. Supportare i token di annullamento, i conteggi dei tentativi e le strategie di back off esponenziale sono solo alcune delle considerazioni che rendono difficile. Fortunatamente, Funzioni fornisce criteri di ripetizione dei tentativi che possono comportare molte di queste attività che in genere si codificano manualmente.
Diversi fattori importanti da considerare quando si usano i criteri di ripetizione dei tentativi con l'associazione di Hub eventi, tra cui:
Evitare tentativi illimitati: quando l'impostazione numero massimo di tentativi è impostata su -1, la funzione ritenta per un periodo illimitato. In generale, è consigliabile usare tentativi illimitati con Funzioni e quasi mai con l'associazione di trigger dell'hub eventi.
Scegliere la strategia di ripetizione dei tentativi appropriata: una strategia di ritardo fisso può essere ottimale per gli scenari che ricevono la pressione da altri servizi di Azure. In questi casi, il ritardo può aiutare a evitare limitazioni e altre limitazioni rilevate da tali servizi. La strategia di back off esponenziale offre maggiore flessibilità per gli intervalli di ritardo dei tentativi e viene comunemente usata durante l'integrazione con servizi di terze parti, endpoint REST e altri servizi di Azure.
Mantenere bassi gli intervalli e i tentativi: quando possibile, provare a mantenere un intervallo di ripetizione più breve di un minuto. Inoltre, mantenere il numero massimo di tentativi a un numero ragionevolmente basso. Queste impostazioni sono particolarmente pertinenti durante l'esecuzione nel piano a consumo di funzioni.
Modello di interruttore: si prevede un errore di errore temporaneo e un caso d'uso naturale per i tentativi. Tuttavia, se si verificano un numero significativo di errori o problemi durante l'elaborazione della funzione, può essere opportuno arrestare la funzione, risolvere i problemi e riavviarsi in un secondo momento.
Un aspetto importante per i criteri di ripetizione dei tentativi in Funzioni è che si tratta di una funzionalità ottimale per la rielaborazione degli eventi. Non sostituisce la necessità di gestire gli errori, registrare e altri modelli importanti che forniscono resilienza al codice.
Strategie per errori e dati danneggiati
Esistono diversi approcci importanti che è possibile usare per compensare i problemi che si verificano a causa di errori o dati errati in un flusso di eventi. Alcune strategie fondamentali sono:
Interrompere l'invio e la lettura: per risolvere il problema sottostante, sospendere la lettura e la scrittura degli eventi. Il vantaggio di questo approccio è che i dati non andranno persi e le operazioni possono riprendere dopo l'implementazione di una correzione. Questo approccio può richiedere un componente interruttore nell'architettura ed eventualmente una notifica ai servizi interessati per ottenere una pausa. In alcuni casi, l'arresto di una funzione può essere necessario fino a quando i problemi non vengono risolti.
Eliminare i messaggi: se i messaggi non sono importanti o sono considerati non cruciali, è consigliabile procedere e non elaborarli. Questo approccio non funziona per gli scenari che richiedono coerenza assoluta, ad esempio la registrazione degli spostamenti in una partita di scacchi o transazioni basate su finanza. La gestione degli errori all'interno di una funzione è consigliata per intercettare ed eliminare messaggi che non possono essere elaborati.
Riprova: esistono molte situazioni che possono giustificare la rielaborazione di un evento. Lo scenario più comune è un errore temporaneo durante la chiamata a un altro servizio o dipendenza. Gli errori di rete, i limiti del servizio e la disponibilità e la coerenza assoluta sono probabilmente i casi d'uso più frequenti che giustificano i tentativi di rielaborazione.
Messaggi non recapitabili: l'idea è pubblicare l'evento in un hub eventi diverso in modo che il flusso esistente non venga interrotto. La percezione è che viene spostato fuori dal percorso caldo e può essere affrontato in seguito o da un processo diverso. Questa soluzione viene usata di frequente per la gestione di messaggi o eventi non elaborabili. Ogni funzione configurata con un gruppo di consumer diverso rileva comunque dati danneggiati o danneggiati nel flusso e deve gestirla in modo responsabile.
Ripetizione dei tentativi e messaggi non recapitabili: la combinazione di numerosi tentativi prima di pubblicare in un flusso di messaggi non recapitabili una volta raggiunta una soglia, è un altro metodo familiare.
Usare un registro schemi: un registro schemi può essere usato come strumento proattivo per migliorare la coerenza e la qualità dei dati. Registro schemi di Azure può supportare la transizione degli schemi insieme al controllo delle versioni e alle diverse modalità di compatibilità man mano che gli schemi si evolvono. Al suo interno, lo schema funge da contratto tra producer e consumer, che potrebbe ridurre la possibilità di pubblicare dati non validi o danneggiati nel flusso.
Alla fine, non c'è una soluzione perfetta e le conseguenze e i compromessi di ognuna delle strategie devono essere esaminati accuratamente. In base ai requisiti, l'uso di diverse di queste tecniche può essere l'approccio migliore.
Collaboratori
Questo articolo viene gestito da Microsoft. Originariamente è stato scritto dai seguenti contributori.
Autore principale:
- David Barkol | GbB principale specialista della soluzione
Per visualizzare i profili LinkedIn non pubblici, accedere a LinkedIn.
Passaggi successivi
Prima di continuare, prendere in considerazione la revisione di questi articoli correlati:
- Elaborazione di eventi affidabili di Funzioni di Azure
- Progettazione di Funzioni di Azure per un input identico
- Funzioni di Azure indicazioni sulla gestione degli errori e sulla ripetizione dei tentativi
Risorsa correlata
L'elaborazione di eventi serverless è un'architettura di riferimento che descrive in dettaglio un'architettura tipica di questo tipo, con esempi di codice e discussioni su considerazioni importanti.