Indicazioni sulle prestazioni e sulla scalabilità per Hub eventi e Funzioni di Azure

Hub eventi di Azure
Funzioni di Azure

Questo articolo fornisce indicazioni per ottimizzare la scalabilità e le prestazioni quando si usano Hub eventi di Azure e Funzioni di Azure insieme nelle applicazioni.

Raggruppamento di funzioni

In genere, una funzione incapsula un'unità di lavoro in un flusso di elaborazione eventi. Ad esempio, una funzione può trasformare un evento in una nuova struttura di dati o arricchire i dati per le applicazioni downstream.

In Funzioni un'app per le funzioni fornisce il contesto di esecuzione per le funzioni. I comportamenti delle app per le funzioni si applicano a tutte le funzioni ospitate dall'app per le funzioni. Le funzioni in un'app per le funzioni vengono distribuite insieme e ridimensionate insieme. Tutte le funzioni in un'app per le funzioni devono essere dello stesso linguaggio.

Il raggruppamento delle funzioni nelle app per le funzioni può influire sulle funzionalità di prestazioni e ridimensionamento delle app per le funzioni. È possibile raggruppare in base ai diritti di accesso, alla distribuzione e ai modelli di utilizzo che richiamano il codice.

Per indicazioni sulle procedure consigliate per le funzioni per il raggruppamento e altri aspetti, vedere Procedure consigliate per Funzioni di Azure affidabili e Migliorare le prestazioni e l'affidabilità di Funzioni di Azure.

L'elenco seguente include indicazioni per il raggruppamento delle funzioni. Le linee guida considerano gli aspetti relativi all'archiviazione e al gruppo di consumer:

  • Ospitare una singola funzione in un'app per le funzioni: Se Hub eventi attiva una funzione, è possibile ridurre la contesa tra tale funzione e altre funzioni, isolare la funzione nella propria app per le funzioni. L'isolamento è particolarmente importante se le altre funzioni sono a elevato utilizzo di CPU o memoria. Questa tecnica è utile perché ogni funzione ha un proprio footprint di memoria e modelli di utilizzo che possono influire direttamente sul ridimensionamento dell'app per le funzioni che lo ospita.

  • Assegnare a ogni app per le funzioni il proprio account di archiviazione: Evitare di condividere gli account di archiviazione tra le app per le funzioni. Inoltre, se un'app per le funzioni usa un account di archiviazione, non usare tale account per altre operazioni di archiviazione o esigenze. Può essere particolarmente importante evitare di condividere gli account di archiviazione per le funzioni attivate da Hub eventi, perché tali funzioni possono avere un volume elevato di transazioni di archiviazione a causa del checkpoint.

  • Creare un gruppo di consumer dedicato per ogni app per le funzioni: Un gruppo di consumer è una visualizzazione di un hub eventi. I diversi gruppi di consumer hanno visualizzazioni diverse, il che significa che gli stati, le posizioni e gli offset possono differire. I gruppi di consumer consentono a più applicazioni che utilizzano di avere visualizzazioni personalizzate del flusso di eventi e di leggere il flusso in modo indipendente al proprio ritmo e con i propri offset. Per altre informazioni sui gruppi di consumer, vedere Funzionalità e terminologia in Hub eventi di Azure.

    A un gruppo di consumer è associata una o più applicazioni consumer e un'applicazione consumer può usare uno o più gruppi di consumer. In una soluzione di elaborazione del flusso ogni applicazione consumer equivale a un gruppo di consumer. Un'app per le funzioni è un esempio principale di un'applicazione consumer. Il diagramma seguente fornisce un esempio di due app per le funzioni che leggono da un hub eventi, in cui ogni app ha un proprio gruppo di consumer dedicato:

    Gruppi di consumer dedicati per ogni app per le funzioni

    Non condividere gruppi di consumer tra le app per le funzioni e altre applicazioni consumer. Ogni app per le funzioni deve essere un'applicazione distinta con un proprio gruppo di consumer assegnato per garantire l'integrità di offset per ogni consumer e semplificare le dipendenze in un'architettura di streaming di eventi. Una configurazione di questo tipo, oltre a fornire a ogni funzione attivata dall'hub eventi la propria app per le funzioni e l'account di archiviazione, consente di impostare le basi per ottenere prestazioni e scalabilità ottimali.

Piani di hosting delle funzioni

Ogni app per le funzioni è ospitata in base a uno dei tre piani di hosting. Per informazioni su questi piani, vedere Funzioni di Azure opzioni di hosting. Prendere nota del ridimensionare le tre opzioni.

Il piano a consumo è il valore predefinito. Le app per le funzioni nel piano a consumo vengono ridimensionate in modo indipendente e sono più efficaci quando evitano attività a esecuzione prolungata.

I piani Premium e Dedicati vengono spesso usati per ospitare più app per le funzioni e funzioni che richiedono un utilizzo maggiore di CPU e memoria. Con il piano dedicato, le funzioni vengono eseguite in un piano di Servizio app di Azure a tariffe regolari del piano di servizio app. È importante notare che tutte le app per le funzioni in questi piani condividono le risorse allocate al piano. Se le funzioni hanno profili di carico o requisiti univoci diversi, è consigliabile ospitarli in piani diversi, in particolare nelle applicazioni di elaborazione dei flussi.

Ridimensionamento di Hub eventi

Quando si distribuisce uno spazio dei nomi di Hub eventi, è necessario impostare correttamente diverse impostazioni importanti per garantire prestazioni e scalabilità ottimali. Questa sezione è incentrata sul livello Standard di Hub eventi e sulle funzionalità univoche di tale livello che influiscono sul ridimensionamento quando si usano anche Funzioni. Per altre informazioni sui livelli di Hub eventi, vedere Livelli Basic e Standard rispetto a Premium e Dedicati.

Uno spazio dei nomi di Hub eventi corrisponde a un cluster Kafka. Per informazioni sulla correlazione tra Hub eventi e Kafka, vedere Che cos'è Hub eventi di Azure per Apache Kafka.

Informazioni sulle unità elaborate (UNITÀ elaborate)

Nel livello Standard di Hub eventi la velocità effettiva viene classificata come quantità di dati immessi e letti dallo spazio dei nomi per unità di tempo. Le unità elaborate sono unità pre-acquistate della capacità di velocità effettiva.

Le unità elaborate vengono fatturate su base oraria.

Tutti gli hub eventi in uno spazio dei nomi condividono le unità elaborate. Per calcolare correttamente le esigenze di capacità, è necessario prendere in considerazione tutte le applicazioni e i servizi, sia gli editori che i consumer. Le funzioni influiscono sul numero di byte ed eventi pubblicati in e letti da un hub eventi.

L'enfasi per determinare il numero di unità elaborate è sul punto di ingresso. Tuttavia, l'aggregazione per le applicazioni consumer, inclusa la frequenza con cui vengono elaborati tali eventi, deve essere inclusa anche nel calcolo.

Per altre informazioni sulle unità elaborate di Hub eventi, vedere Unità elaborate.

Aumentare le prestazioni con aumento automatico

L'aumento automatico può essere abilitato in uno spazio dei nomi di Hub eventi per gestire situazioni in cui il carico supera il numero configurato di unità elaborate. L'uso dell'aumento automatico impedisce la limitazione dell'applicazione e garantisce che l'elaborazione, inclusa l'inserimento di eventi, continui senza interruzioni. Poiché l'impostazione TU influisce sui costi, l'uso dell'aumento automatico consente di risolvere i problemi relativi all'overprovisioning.

L'aumento automatico è una funzionalità di Hub eventi spesso confusa con la scalabilità automatica, soprattutto nel contesto di soluzioni serverless. Tuttavia, l'aumento automatico, a differenza della scalabilità automatica, non aumenta quando la capacità aggiunta non è più necessaria.

Se l'applicazione necessita di capacità superiore al numero massimo consentito di unità elaborate, è consigliabile usare il livello Premium di Hub eventi o il livello Dedicato.

Partizioni e funzioni simultanee

Quando viene creato un hub eventi, è necessario specificare il numero di partizioni . Il numero di partizioni rimane fisso e non può essere modificato a eccezione dei livelli Premium e Dedicato. Quando Hub eventi attiva le app per le funzioni, è possibile che il numero di istanze simultanee sia uguale al numero di partizioni.

Nei piani di hosting Consumo e Premium, le istanze dell'app per le funzioni aumentano in modo dinamico in base al numero di partizioni, se necessario. Il piano di hosting dedicato esegue funzioni in un piano di servizio app e richiede di configurare manualmente le istanze o di configurare uno schema di scalabilità automatica. Per altre informazioni, vedere Piani di hosting dedicati per Funzioni di Azure.

In definitiva, una relazione uno-a-uno tra il numero di partizioni e le istanze dell'app per le funzioni è la destinazione ideale per la velocità effettiva massima in una soluzione di elaborazione del flusso. Per ottenere un parallelismo ottimale, avere più consumer in un gruppo di consumer. Per Funzioni, questo obiettivo si traduce in molte istanze di un'app per le funzioni nel piano. Il risultato viene definito parallelismo a livello di partizione o il grado massimo di parallelismo, come illustrato nel diagramma seguente:

Massimo grado di parallelismo

Potrebbe sembrare opportuno configurare il maggior numero possibile di partizioni per ottenere la velocità effettiva massima e tenere conto della possibilità di un volume di eventi superiore. Esistono tuttavia diversi fattori importanti da considerare quando si configurano molte partizioni:

  • Un numero maggiore di partizioni può comportare una maggiore velocità effettiva: Poiché il grado di parallelismo è il numero di consumer (istanze dell'app per le funzioni), maggiore è il numero di partizioni presenti, maggiore sarà la velocità effettiva simultanea. Questo fatto è importante quando si condivide un numero designato di unità elaborate per un hub eventi con altre applicazioni consumer.
  • Altre funzioni possono richiedere più memoria: Man mano che aumenta il numero di istanze dell'app per le funzioni, il footprint di memoria delle risorse nel piano. A un certo punto, troppe partizioni possono peggiorare le prestazioni per i consumer.
  • C'è un rischio di back pressure dai servizi downstream: Man mano che viene generata una maggiore velocità effettiva, si corre il rischio di sovraccaricare i servizi downstream o di ricevere una pressione indietro da tali servizi. I fan-out dei consumatori devono essere considerati quando si considerano le conseguenze delle risorse circostanti. Le possibili conseguenze includono la limitazione da altri servizi, saturazione della rete e altre forme di contesa di risorse.
  • Le partizioni possono essere popolate in modo sparse: La combinazione di molte partizioni e un volume ridotto di eventi può causare dati distribuiti in modo sparse tra le partizioni. Al contrario, un numero minore di partizioni può offrire prestazioni migliori e utilizzo delle risorse

Disponibilità e coerenza

Quando non viene specificata una chiave di partizione o un ID, Hub eventi instrada un evento in ingresso alla successiva partizione disponibile. Questa procedura offre disponibilità elevata e consente di aumentare la velocità effettiva per i consumer.

Quando è necessario ordinare un set di eventi, il producer di eventi può specificare che una determinata partizione deve essere usata per tutti gli eventi del set. L'applicazione consumer che legge dalla partizione riceve gli eventi nell'ordine corretto. Questo compromesso garantisce coerenza, ma compromette la disponibilità. Non usare questo approccio a meno che non sia necessario conservare l'ordine degli eventi.

Per Funzioni, l'ordinamento viene ottenuto quando gli eventi vengono pubblicati in una determinata partizione e una funzione attivata da Hub eventi ottiene un lease alla stessa partizione. Attualmente, la possibilità di configurare una partizione con l'associazione di output di Hub eventi non è supportata. L'approccio migliore consiste invece nell'usare uno degli SDK di Hub eventi per pubblicare in una partizione specifica.

Per altre informazioni su come Hub eventi supporta la disponibilità e la coerenza, vedere Disponibilità e coerenza in Hub eventi.

Trigger per Hub eventi

Questa sezione è incentrata sulle impostazioni e sulle considerazioni per l'ottimizzazione delle funzioni attivate da Hub eventi. I fattori includono l'elaborazione batch, il campionamento e le funzionalità correlate che influiscono sul comportamento di un'associazione di trigger dell'hub eventi.

Invio in batch per le funzioni attivate

È possibile configurare funzioni attivate da un hub eventi per elaborare un batch di eventi o un evento alla volta. L'elaborazione di un batch di eventi è più efficiente perché elimina il sovraccarico delle chiamate di funzione. A meno che non sia necessario elaborare solo un singolo evento, la funzione deve essere configurata per elaborare più eventi quando viene richiamato.

L'abilitazione dell'invio in batch per l'associazione di trigger di Hub eventi varia tra le lingue:

  • JavaScript, Python e altri linguaggi consentono l'invio in batch quando la proprietà di cardinalità è impostata su molti nel file function.json per la funzione.
  • In C# la cardinalità viene configurata automaticamente quando viene designata una matrice per il tipo nell'attributo EventHubTrigger .

Per altre informazioni sull'abilitazione dell'invio in batch, vedere trigger Hub eventi di Azure per Funzioni di Azure.

Impostazioni di trigger

Diverse impostazioni di configurazione nel file host.json svolgono un ruolo chiave nelle caratteristiche delle prestazioni dell'associazione di trigger di Hub eventi per Funzioni:

  • maxEventBatchSize: Questa impostazione rappresenta il numero massimo di eventi che la funzione può ricevere quando viene richiamata. Se il numero di eventi ricevuti è minore di questo importo, la funzione viene comunque richiamata con il numero di eventi disponibili. Non è possibile impostare una dimensione minima del batch.
  • prefetchCount: Il conteggio dei prelettura è una delle impostazioni più importanti quando si ottimizzano le prestazioni. Il canale AMQP sottostante fa riferimento a questo valore per determinare il numero di messaggi da recuperare e memorizzare nella cache per il client. Il numero di prelettura deve essere maggiore o uguale al valore maxEventBatchSize ed è in genere impostato su un multiplo di tale importo. L'impostazione di questo valore su un numero minore dell'impostazione maxEventBatchSize può compromettere le prestazioni.
  • batchCheckpointFrequency: Quando la funzione elabora i batch, questo valore determina la frequenza con cui vengono creati i checkpoint. Il valore predefinito è 1, il che significa che è presente un checkpoint ogni volta che una funzione elabora correttamente un batch. Viene creato un checkpoint a livello di partizione per ogni lettore nel gruppo di consumer. Per informazioni su come questa impostazione influisce sulle riproduzioni e i tentativi di eventi, vedere Funzione di Azure attivata dall'hub eventi: Riesecuzioni e tentativi (post di blog).

Eseguire diversi test delle prestazioni per determinare i valori da impostare per l'associazione di trigger. È consigliabile modificare le impostazioni in modo incrementale e misurare in modo coerente per ottimizzare queste opzioni. I valori predefiniti sono un punto di partenza ragionevole per la maggior parte delle soluzioni di elaborazione degli eventi.

Checkpoint

I checkpoint contrassegnano o eseguono il commit delle posizioni del lettore in una sequenza di eventi di partizione. È responsabilità dell'host di Funzioni di eseguire il checkpoint quando vengono elaborati gli eventi e viene soddisfatta l'impostazione per la frequenza del checkpoint batch. Per altre informazioni sul checkpoint, vedere Funzionalità e terminologia in Hub eventi di Azure.

I concetti seguenti consentono di comprendere la relazione tra il checkpoint e il modo in cui la funzione elabora gli eventi:

  • Le eccezioni vengono comunque conteggiate in caso di esito positivo: Se il processo della funzione non si arresta in modo anomalo durante l'elaborazione degli eventi, il completamento della funzione viene considerato riuscito, anche se si sono verificate eccezioni. Al termine della funzione, l'host di Funzioni valuta batchCheckpointFrequency. Se è il momento di un checkpoint, ne crea uno, indipendentemente dal fatto che si siano verificati eccezioni. Il fatto che le eccezioni non influiscano sul checkpoint non influiscano sull'uso appropriato del controllo e della gestione delle eccezioni.
  • La frequenza batch è importante: Nelle soluzioni di streaming di eventi con volume elevato, può essere utile modificare l'impostazione batchCheckpointFrequency su un valore maggiore di 1. L'aumento di questo valore può ridurre la frequenza di creazione del checkpoint e, di conseguenza, il numero di operazioni di I/O di archiviazione.
  • Le riproduzioni possono verificarsi: Ogni volta che una funzione viene richiamata con l'associazione di trigger di Hub eventi, usa il checkpoint più recente per determinare dove riprendere l'elaborazione. L'offset per ogni consumer viene salvato a livello di partizione per ogni gruppo di consumer. Le riproduzioni si verificano quando non si verifica un checkpoint durante l'ultima chiamata della funzione e la funzione viene richiamata di nuovo. Per altre informazioni sui duplicati e sulle tecniche di deduplicazione, vedere Idempotenza.

La comprensione del checkpoint diventa fondamentale quando si considerano le procedure consigliate per la gestione degli errori e i tentativi, un argomento descritto più avanti in questo articolo.

Campionamento dei dati di telemetria

Funzioni offre il supporto predefinito per Application Insights, un'estensione di Monitoraggio di Azure che offre funzionalità di monitoraggio delle prestazioni delle applicazioni. Con questa funzionalità è possibile registrare informazioni sulle attività delle funzioni, sulle prestazioni, sulle eccezioni di runtime e altro ancora. Per altre informazioni, vedere Panoramica di Application Insights.

Questa potente funzionalità offre alcune scelte di configurazione chiave che influiscono sulle prestazioni. Alcune delle impostazioni e considerazioni rilevanti per il monitoraggio e le prestazioni sono:

  • Abilitare il campionamento dei dati di telemetria: Per gli scenari con velocità effettiva elevata, è consigliabile valutare la quantità di dati di telemetria e le informazioni necessarie. È consigliabile usare la funzionalità di campionamento dei dati di telemetria in Application Insights per evitare di ridurre le prestazioni della funzione con dati di telemetria e metriche non necessari.
  • Configurare le impostazioni di aggregazione: Esaminare e configurare la frequenza di aggregazione e invio di dati ad Application Insights. Questa impostazione di configurazione si trova nel file host.json insieme a molte altre opzioni correlate al campionamento e alla registrazione. Per altre informazioni, vedere Configurare l'aggregatore.
  • Disabilitare AzureWebJobDashboard: Per le app destinate alla versione 1.x del runtime di Funzioni, questa impostazione archivia la stringa di connessione a un account di archiviazione usato da Azure SDK per conservare i log per il dashboard dei processi Web. Se Application Insights viene usato invece del dashboard processi Web, questa impostazione deve essere rimossa. Per altre informazioni, vedere AzureWebJobsDashboard.

Quando Application Insights è abilitato senza campionamento, vengono inviati tutti i dati di telemetria. L'invio di dati su tutti gli eventi può avere un effetto negativo sulle prestazioni della funzione, in particolare negli scenari di streaming di eventi con velocità effettiva elevata.

Sfruttare il campionamento e valutare continuamente la quantità appropriata di dati di telemetria necessari per il monitoraggio è fondamentale per ottenere prestazioni ottimali. I dati di telemetria devono essere usati per la valutazione generale dell'integrità della piattaforma e per la risoluzione dei problemi occasionali, non per acquisire le metriche aziendali principali. Per altre informazioni, vedere Configurare il campionamento.

Associazione di output

Usare l'associazione di output di Hub eventi per Funzioni di Azure per semplificare la pubblicazione in un flusso di eventi da una funzione. I vantaggi dell'uso di questa associazione includono:

  • Gestione risorse: L'associazione gestisce sia il ciclo di vita del client che il ciclo di vita della connessione e riduce il potenziale di problemi che possono verificarsi con l'esaurimento delle porte e la gestione del pool di connessioni.
  • Meno codice: L'associazione astrae l'SDK sottostante e riduce la quantità di codice necessario per pubblicare gli eventi. Consente di scrivere codice più semplice da scrivere e gestire.
  • Batch: Per diversi linguaggi, l'invio in batch è supportato per pubblicare in modo efficiente in un flusso di eventi. L'invio in batch può migliorare le prestazioni e semplificare il codice che invia gli eventi.

È consigliabile esaminare l'elenco dei linguaggi supportati da Funzioni e le guide per gli sviluppatori per tali linguaggi. La sezione Bindings per ogni linguaggio fornisce esempi dettagliati e documentazione.

Invio in batch durante la pubblicazione di eventi

Se la funzione pubblica solo un singolo evento, la configurazione dell'associazione per restituire un valore è un approccio comune utile se l'esecuzione della funzione termina sempre con un'istruzione che invia l'evento. Questa tecnica deve essere usata solo per le funzioni sincrone che restituiscono un solo evento.

L'invio in batch è consigliato per migliorare le prestazioni quando si inviano più eventi a un flusso. L'invio in batch consente all'associazione di pubblicare eventi nel modo più efficiente possibile.

Il supporto per l'uso dell'associazione di output per inviare più eventi a Hub eventi è disponibile in C#, Java, Python e JavaScript.

Output di più eventi (C#)

Usare i tipi ICollector e IAsyncCollector quando si inviano più eventi da una funzione in C#.

  • ICollector<T>. Il metodo Add() può essere usato sia nelle funzioni sincrone che asincrone. Esegue l'operazione di aggiunta non appena viene chiamata.
  • IAsyncCollector<T>. Il metodo AddAsync() prepara gli eventi da pubblicare nel flusso di eventi. Se si scrive una funzione asincrona, è consigliabile usare IAsyncCollector per gestire meglio gli eventi pubblicati.

Per esempi di uso di C# per pubblicare eventi singoli e multipli, vedere Hub eventi di Azure binding di output per Funzioni di Azure.

Limitazione e pressione posteriore

Le considerazioni sulla limitazione si applicano all'associazione di output, non solo per Hub eventi, ma anche per i servizi di Azure, ad esempio Azure Cosmos DB. È importante acquisire familiarità con i limiti e le quote applicabili a tali servizi e pianificare di conseguenza.

Per gestire gli errori downstream, è possibile eseguire il wrapping di AddAsync e FlushAsync in un gestore di eccezioni per funzioni .NET per rilevare le eccezioni da IAsyncCollector. Un'altra opzione consiste nell'usare direttamente gli SDK di Hub eventi anziché usare associazioni di output.

Codice di funzione

Questa sezione illustra le aree chiave che devono essere considerate durante la scrittura di codice per elaborare gli eventi in una funzione attivata da Hub eventi.

Programmazione asincrona

È consigliabile scrivere la funzione per usare il codice asincrono ed evitare di bloccare le chiamate, soprattutto quando sono coinvolte chiamate di I/O.

Di seguito sono riportate le linee guida da seguire quando si scrive una funzione per elaborare in modo asincrono:

  • Tutti asincroni o tutti sincroni: Se una funzione è configurata per l'esecuzione asincrona, tutte le chiamate di I/O devono essere asincrone. Nella maggior parte dei casi, il codice parzialmente asincrono è peggiore del codice completamente sincrono. Scegliere asincrona o sincrona e attenersi alla scelta fino all'altro.
  • Evitare di bloccare le chiamate: Il blocco delle chiamate torna al chiamante solo dopo il completamento della chiamata, a differenza delle chiamate asincrone che restituiscono immediatamente. Un esempio in C# chiama Task.Result o Task.Wait su un'operazione asincrona.

Altre informazioni sul blocco delle chiamate

L'uso delle chiamate di blocco per le operazioni asincrone può causare l'arresto anomalo del processo di funzione. L'arresto anomalo si verifica perché una chiamata di blocco richiede la creazione di un altro thread per compensare la chiamata originale in attesa. Di conseguenza, richiede il doppio del numero di thread per completare l'operazione.

Evitare questo approccio asincrono è particolarmente importante quando gli hub eventi sono coinvolti, perché un arresto anomalo della funzione non aggiorna il checkpoint. La prossima volta che la funzione viene richiamata, potrebbe terminare in questo ciclo e sembra essere bloccata o spostarsi lentamente come le esecuzioni di funzioni alla fine timeout.

La risoluzione dei problemi di questo fenomeno inizia in genere con la revisione delle impostazioni del trigger e l'esecuzione di esperimenti che possono comportare l'aumento del conteggio delle partizioni. Le indagini possono anche causare la modifica di diverse opzioni di batch, ad esempio il numero massimo di batch o il numero di prefetch. L'impressione è che sia un problema di velocità effettiva o un'impostazione di configurazione che deve essere ottimizzata di conseguenza. Tuttavia, il problema principale è nel codice stesso e deve essere risolto lì.

Autori di contributi

Questo articolo viene gestito da Microsoft. È stato originariamente scritto dal collaboratore seguente.

Autore principale:

Per visualizzare profili LinkedIn non pubblici, accedere a LinkedIn.

Passaggi successivi

Prima di continuare, prendere in considerazione la revisione di questi articoli correlati: