Condividi tramite


Elaborazione di eventi affidabile con Funzioni di Azure e Hub eventi

Scopri come creare soluzioni serverless robuste e affidabili usando Funzioni di Azure con i trigger di Event Hubs di Azure. Questo articolo illustra le procedure consigliate per i checkpoint, la gestione degli errori e l'implementazione di modelli di interruttore per assicurarsi che non vengano persi eventi e che le applicazioni guidate dagli eventi rimangano stabili e resilienti.

Sfide dei flussi di eventi nei sistemi distribuiti

Si consideri un sistema che invia eventi a una frequenza costante di 100 eventi al secondo. A questa velocità, in pochi minuti più istanze parallele possono elaborare 100 eventi in arrivo ogni secondo.

Tuttavia, considerate queste sfide nella fruizione di un flusso di eventi.

  • Un autore di eventi invia un evento danneggiato.
  • Il codice della funzione rileva un'eccezione non gestita.
  • Un sistema downstream passa offline e blocca l'elaborazione degli eventi.

A differenza di un trigger di archiviazione code di Azure, che blocca i messaggi durante l'elaborazione, Hub eventi di Azure legge, per partizione, da un singolo punto nel flusso. Questo comportamento di lettura, più simile a un lettore video, offre i vantaggi desiderati di velocità effettiva elevata, più gruppi di consumer e capacità di riproduzione. Gli eventi vengono letti, in avanti o indietro, da un checkpoint, ma è necessario spostare il puntatore per elaborare nuovi eventi. Per altre informazioni, vedere Checkpoint nella documentazione di Hub eventi.

Quando si verificano errori in un flusso e si sceglie di non avanzare il puntatore, viene bloccata un'ulteriore elaborazione degli eventi. In altre parole, se si arresta il puntatore per gestire un problema durante l'elaborazione di un singolo evento, gli eventi non elaborati iniziano a accumularsi.

La funzione evita i deadlock avanzando sempre il puntatore del flusso, indipendentemente dall'esito positivo o negativo. Poiché il puntatore continua ad avanzare, le funzioni devono gestire correttamente gli errori.

Come il trigger di Event Hubs consuma gli eventi

Azure Functions consuma eventi da un hub eventi eseguendo i passaggi seguenti:

  1. Un puntatore viene creato e salvato in modo permanente in Archiviazione di Azure per ogni partizione dell'hub eventi.
  2. I nuovi eventi vengono ricevuti in un batch (per impostazione predefinita) e l'host tenta di attivare la funzione fornendo un batch di eventi per l'elaborazione.
  3. Quando la funzione completa l'esecuzione, con o senza eccezioni, il puntatore è avanzato e un checkpoint viene salvato nell'account di archiviazione host predefinito.
  4. Se le condizioni impediscono il completamento dell'esecuzione della funzione, l'host non può avanzare il puntatore. Quando il puntatore non può avanzare, le esecuzioni successive elaborano nuovamente gli stessi eventi.

Questo comportamento rivela alcuni punti importanti:

  • Le eccezioni non gestite possono causare la perdita di eventi:

    Le esecuzioni di funzioni che generano un'eccezione continuano a far progredire il puntatore. L'impostazione di un criterio di ripetizione dei tentativi o di un'altra logica di ripetizione dei tentativi ritarda l'avanzamento del puntatore fino al completamento dell'intero tentativo.

  • Funzioni garantisce il recapito at-least-once :

    Il codice e i sistemi dipendenti potrebbero dover tenere conto del fatto che lo stesso evento potrebbe essere elaborato due volte. Per altre informazioni, vedere Progettazione di Funzioni di Azure per un input identico.

Gestione delle eccezioni

Anche se tutto il codice della funzione deve includere un blocco try/catch al massimo livello di codice, la presenza di un catch blocco è ancora più importante per le funzioni che elaborano gli eventi di Event Hubs. In questo modo, quando viene generata un'eccezione, il blocco catch gestisce l'errore prima che il puntatore progredisca.

Meccanismi e criteri di ripetizione dei tentativi

Poiché molte eccezioni nel cloud sono temporanee, il primo passaggio nella gestione degli errori consiste sempre nel ripetere l'operazione. È possibile applicare criteri di ripetizione dei tentativi predefiniti o definire la logica di ripetizione dei tentativi.

Criteri di ripetizione dei tentativi

Funzioni fornisce criteri di retry predefiniti per Hub eventi. Quando si usano criteri di ripetizione dei tentativi, è sufficiente generare una nuova eccezione e l'host prova a elaborare nuovamente l'evento in base ai criteri definiti. Questo comportamento di ripetizione dei tentativi richiede la versione 5.x o successiva dell'estensione di Hub eventi. Per altre informazioni, vedere il Criteri di ripetizione dei tentativi.

Logica di ripetizione dei tentativi personalizzata

È anche possibile definire la logica di ripetizione dei tentativi nella funzione stessa. Ad esempio, è possibile implementare un criterio che segue un flusso di lavoro illustrato dalle regole seguenti:

  • Tentare di elaborare un evento tre volte (potenzialmente con un ritardo tra i tentativi).
  • Se il risultato finale di tutti i tentativi è un errore, aggiungere un evento a una coda in modo che l'elaborazione possa continuare nel flusso.
  • Gli eventi danneggiati o non elaborati vengono quindi gestiti in un secondo momento.

Annotazioni

Polly è un esempio di una libreria di resilienza e di gestione degli errori temporanei per le applicazioni C#.

Errori non di eccezione

Alcuni problemi possono verificarsi senza che venga generata un'eccezione. Si consideri, ad esempio, un caso in cui si verifica il timeout di una richiesta o l'istanza che esegue la funzione si arresta in modo anomalo. Quando una funzione non viene completata senza un'eccezione, il puntatore di offset non viene mai avanzato. Se il puntatore non avanza, qualsiasi istanza eseguita dopo un'esecuzione non riuscita continua a leggere gli stessi eventi. Questa situazione fornisce una garanzia at-least-once.

La garanzia che ogni evento venga elaborato almeno una volta implica che alcuni eventi potrebbero essere elaborati più volte. Le app per le funzioni devono essere consapevoli di questa possibilità e devono essere compilate in base ai principi di idempotenza.

Gestione degli stati di errore

L'app potrebbe essere in grado di gestire in modo accettabile alcuni errori nell'elaborazione degli eventi. Tuttavia, è necessario essere pronti anche a gestire lo stato di errore persistente, che potrebbe verificarsi a causa di errori nell'elaborazione downstream. In uno stato di errore di questo tipo, ad esempio un archivio dati downstream offline, la funzione deve interrompere l'attivazione degli eventi fino a quando il sistema non raggiunge uno stato integro.

Modello di interruttore

Quando implementi il modello di interruttore , l'app può sospendere efficacemente l'elaborazione degli eventi e quindi riprenderla in un secondo momento dopo la risoluzione dei problemi.

Esistono due componenti necessari per implementare un interruttore in un processo del flusso di eventi:

  • Stato condiviso tra tutte le istanze per tenere traccia e monitorare l'integrità del circuito.
  • Processo primario in grado di gestire lo stato del circuito, come open o closed.

I dettagli di implementazione possono variare, ma per condividere lo stato tra le istanze è necessario un meccanismo di archiviazione. È possibile archiviare lo stato in Archiviazione di Azure, in una cache Redis o in qualsiasi altro servizio permanente accessibile dalle istanze dell'app per le funzioni.

Durable Functions e App per la logica di Azure forniscono un'infrastruttura per gestire flussi di lavoro e stati del circuito. Questo articolo descrive l'uso di App per la logica per sospendere e riavviare le esecuzioni delle funzioni, fornendo il controllo necessario per implementare il modello di interruttore.

Definire una soglia di errore tra istanze

Lo stato esterno condiviso persistente è necessario per monitorare l'integrità del circuito quando più istanze elaborano eventi contemporaneamente. È quindi possibile monitorare questo stato persistente in base alle regole che indicano uno stato di errore, ad esempio:

Quando sono presenti più di 100 errori di eventi entro un periodo di 30 secondi in tutte le istanze, interrompere il circuito per interrompere l'attivazione di nuovi eventi.

I dettagli di implementazione per questa logica di monitoraggio variano a seconda delle esigenze specifiche dell'app, ma in generale è necessario creare un sistema che:

  1. Registra i fallimenti su memoria persistente.
  2. Esaminare il conteggio progressivo quando vengono registrati nuovi errori per determinare se è stata raggiunta la soglia di errore dell'evento.
  3. Quando questa soglia viene raggiunta, generare un evento che informa il sistema di interrompere il circuito.

Gestione dello stato del circuito con App per la logica di Azure

App per la logica di Azure include connettori predefiniti per servizi, funzionalità e orchestrazioni con stato diversi ed è una scelta naturale per gestire lo stato del circuito. Dopo aver rilevato quando un circuito deve interrompersi, è possibile compilare un'app per la logica per implementare questo flusso di lavoro:

  1. Attivare un flusso di lavoro di Griglia di eventi che arresta l'elaborazione della funzione.
  2. Inviare un messaggio di posta elettronica di notifica che include un'opzione per riavviare il flusso di lavoro.

Per informazioni su come disabilitare e riabilitare funzioni specifiche usando le impostazioni dell'app, vedere Come disabilitare le funzioni in Funzioni di Azure.

Il destinatario del messaggio di posta elettronica può analizzare l'integrità del circuito e, quando appropriato, riavviare il circuito tramite un collegamento nel messaggio di posta elettronica di notifica. Quando il flusso di lavoro riavvia la funzione, gli eventi vengono elaborati dall'ultimo checkpoint dell'hub eventi.

Quando si usa questo approccio, non vengono persi eventi, gli eventi vengono elaborati in ordine ed è possibile interrompere il circuito purché necessario.

Strategie di migrazione per i trigger di Griglia di eventi

Quando si esegue la migrazione di un'app per le funzioni esistente tra aree o tra alcuni piani, è necessario ricreare l'app durante il processo di migrazione. In questo caso, durante il processo di migrazione, potrebbero esserci due app in grado di consumare dallo stesso flusso di eventi e scrivere nella stessa destinazione di output.

È consigliabile usare i gruppi di consumer per evitare la perdita o la duplicazione dei dati degli eventi durante il processo di migrazione:

  1. Creare un nuovo gruppo di consumer per la nuova app di destinazione.

  2. Configurare il trigger nella nuova app per usare questo nuovo gruppo di consumatori.

    In questo modo entrambe le app possono elaborare gli eventi in modo indipendente durante la convalida.

  3. Verificare che la nuova app stia elaborando correttamente gli eventi.

  4. Interrompere l'app originale o rimuovere il relativo gruppo di sottoscrizioni/consumatori.