Concorrenza in Funzioni di Azure

Questo articolo descrive i comportamenti di concorrenza dei trigger basati su eventi in Funzioni di Azure. Descrive anche un nuovo modello dinamico per l'ottimizzazione dei comportamenti di concorrenza.

Il modello di hosting per Funzioni consente l'esecuzione simultanea di più chiamate di funzione in una singola istanza di calcolo. Si consideri, ad esempio, un caso in cui nell'app per le funzioni siano presenti tre funzioni diverse, con scalabilità orizzontale e in esecuzione su più istanze. In questo scenario ogni funzione elabora le chiamate in ogni istanza di macchina virtuale in cui è in esecuzione l'app per le funzioni. Le chiamate di funzione in una singola istanza condividono le stesse risorse di calcolo della macchina virtuale, ad esempio memoria, CPU e connessioni. Quando l'app è ospitata in un piano dinamico (Consumo o Premium), la piattaforma aumenta o riduce il numero di istanze dell'app per le funzioni in base al numero di eventi in ingresso. Per altre informazioni, vedere Ridimensionamento basato su eventi. Quando si ospitano le funzioni in un piano dedicato (servizio app), configurare manualmente le istanze o configurare uno schema di scalabilità automatica.

Poiché più chiamate di funzione possono essere eseguite in ogni istanza contemporaneamente, ogni funzione deve avere un modo per limitare il numero di chiamate simultanee che elabora in qualsiasi momento.

Concorrenza statica

Molti dei trigger supportano un modello di configurazione statica a livello di host, usato per specificare la concorrenza per istanza per tale tipo di trigger. Ad esempio, il trigger di bus di servizio fornisce sia un MaxConcurrentCalls oggetto che un'impostazione MaxConcurrentSessionsnel file host.json. Queste impostazioni controllano insieme il numero massimo di messaggi che ogni funzione elabora contemporaneamente in ogni istanza. Altri tipi di trigger includono meccanismi predefiniti per il bilanciamento del carico delle chiamate tra istanze. Ad esempio, Hub eventi e Azure Cosmos DB usano entrambi uno schema basato su partizione.

Per i tipi di trigger che supportano la configurazione della concorrenza, esiste un comportamento predefinito, che è possibile scegliere di eseguire l'override nel file host.json per l'app per le funzioni. Queste impostazioni, che si applicano a tutte le istanze in esecuzione, consentono di controllare la concorrenza massima per le funzioni in ogni istanza. Ad esempio, quando la funzione è a elevato utilizzo di CPU o risorse, è possibile scegliere di limitare la concorrenza per mantenere integre le istanze. Analogamente, quando la funzione effettua richieste a un servizio downstream che viene limitato, è consigliabile considerare anche la limitazione della concorrenza.

Anche se tali configurazioni di concorrenza offrono il controllo di determinati comportamenti di trigger, ad esempio la limitazione delle funzioni, può essere difficile determinare i valori ottimali per queste impostazioni. In genere, è necessario arrivare a valori accettabili tramite un processo di valutazione e errore di test di carico. Anche quando si determina un set di valori che funzionano per un profilo di carico specifico, il numero di eventi provenienti dai servizi connessi può cambiare da giorno a giorno. Questa variabilità significa che l'app spesso può essere eseguita con valori non ottimali. Ad esempio, l'app per le funzioni può elaborare payload di messaggi particolarmente impegnativi nell'ultimo giorno della settimana, che richiede la limitazione della concorrenza. Tuttavia, durante il resto della settimana i payload del messaggio sono più semplici, il che significa che è possibile usare un livello di concorrenza superiore il resto della settimana.

Idealmente, si vuole che il sistema consenta alle istanze di elaborare il maggior numero possibile di operazioni, mantenendo ogni istanza integra e bassa delle latenze, che è ciò che la concorrenza dinamica è progettata per eseguire.

Concorrenza dinamica

Funzioni offre ora un modello di concorrenza dinamico che semplifica la configurazione della concorrenza per tutte le app per le funzioni in esecuzione nello stesso piano.

Nota

La concorrenza dinamica è attualmente supportata solo per i trigger BLOB di Azure, Coda di Azure e bus di servizio e richiede l'uso delle versioni elencate nella sezione relativa al supporto delle estensioni seguente.

Vantaggi

L'uso della concorrenza dinamica offre i vantaggi seguenti:

  • Configurazione semplificata: non è più necessario determinare manualmente le impostazioni di concorrenza per trigger. Il sistema apprende i valori ottimali per il carico di lavoro nel tempo.
  • Regolazioni dinamiche: la concorrenza viene modificata in modo dinamico in tempo reale, consentendo al sistema di adattarsi ai modelli di carico modificati nel tempo.
  • Protezione dell'integrità dell'istanza: il runtime limita la concorrenza ai livelli che un'istanza dell'app per le funzioni può gestire comodamente. In questo modo l'app viene protetto dall'overload di se stesso eseguendo un lavoro maggiore di quello che dovrebbe.
  • Miglioramento della velocità effettiva: la velocità effettiva complessiva è migliorata perché le singole istanze non estraggono più lavoro di quanto possano elaborare rapidamente. Ciò consente di bilanciare il carico in modo più efficace tra istanze. Per le funzioni in grado di gestire carichi più elevati, la concorrenza può essere aumentata a valori superiori ai valori di configurazione predefiniti, che produce una velocità effettiva più elevata.

Configurazione dinamica della concorrenza

La concorrenza dinamica può essere abilitata a livello di host nel file host.json. Quando è abilitata qualsiasi estensione di associazione usata dall'app per le funzioni che supporta la concorrenza dinamica regola la concorrenza in modo dinamico in base alle esigenze. Le impostazioni di concorrenza dinamica sostituiscono tutte le impostazioni di concorrenza configurate manualmente per i trigger che supportano la concorrenza dinamica.

Per impostazione predefinita, la concorrenza dinamica è disabilitata. Con la concorrenza dinamica abilitata, la concorrenza inizia da 1 per ogni funzione e viene adattata a un valore ottimale, determinato dall'host.

È possibile abilitare la concorrenza dinamica nell'app per le funzioni aggiungendo le impostazioni seguenti nel file host.json:

    { 
        "version": "2.0", 
        "concurrency": { 
            "dynamicConcurrencyEnabled": true, 
            "snapshotPersistenceEnabled": true 
        } 
    } 

Quando SnapshotPersistenceEnabled è true, che è l'impostazione predefinita, i valori di concorrenza appresi vengono mantenuti periodicamente nell'archiviazione, in modo che le nuove istanze inizino da tali valori invece di partire da 1 e dover ripetere l'apprendimento.

Gestione concorrenza

Dietro le quinte, quando la concorrenza dinamica è abilitata, è in esecuzione un processo di gestione della concorrenza in background. Questo gestore monitora costantemente le metriche di integrità delle istanze, ad esempio l'utilizzo della CPU e del thread, e le modifiche vengono limitate in base alle esigenze. Quando una o più limitazioni sono abilitate, la concorrenza delle funzioni viene modificata fino a quando l'host non è di nuovo integro. Quando le limitazioni sono disabilitate, la concorrenza può aumentare. Diverse euristiche vengono usate per regolare in modo intelligente la concorrenza verso l'alto o verso il basso in base alle esigenze in base a queste limitazioni. Nel corso del tempo, la concorrenza per ogni funzione si stabilizza a un determinato livello.

I livelli di concorrenza vengono gestiti per ogni singola funzione. Di conseguenza, il sistema si bilancia tra le funzioni a elevato utilizzo di risorse che richiedono un basso livello di concorrenza e funzioni più leggere che possono gestire una concorrenza più elevata. Il bilanciamento della concorrenza per ogni funzione consente di mantenere l'integrità complessiva dell'istanza dell'app per le funzioni.

Quando la concorrenza dinamica è abilitata, nei log verranno visualizzate decisioni sulla concorrenza dinamica. Ad esempio, verranno visualizzati i log quando sono abilitate varie limitazioni e ogni volta che la concorrenza viene modificata verso l'alto o verso il basso per ogni funzione. Questi log vengono scritti nella categoria del log Host.Concurrency nella tabella delle tracce.

Supporto per estensioni

La concorrenza dinamica è abilitata per un'app per le funzioni a livello di host e per tutte le estensioni che supportano l'esecuzione dinamica della concorrenza in tale modalità. La concorrenza dinamica richiede la collaborazione tra l'host e le singole estensioni del trigger. Solo le versioni elencate delle estensioni seguenti supportano la concorrenza dinamica.

Code di Azure

Il trigger di archiviazione code di Azure ha un proprio ciclo di polling dei messaggi. Quando si usa la configurazione statica, la concorrenza è governata dalle BatchSize/NewBatchThreshold opzioni di configurazione. Quando si usa la concorrenza dinamica, tali valori di configurazione vengono ignorati. La concorrenza dinamica è integrata nel ciclo di messaggi, pertanto il numero di messaggi recuperati per iterazione viene regolato in modo dinamico. Quando le limitazioni sono abilitate (l'host è in overload), l'elaborazione dei messaggi verrà sospesa fino a quando le limitazioni non vengono disabilitate. Quando le limitazioni sono disabilitate, la concorrenza aumenterà.

Per usare la concorrenza dinamica per le code, è necessario usare la versione 5.x dell'estensione di archiviazione.

BLOB di Azure

Internamente, il trigger di archiviazione BLOB di Azure usa la stessa infrastruttura usata dal trigger di coda di Azure. Quando i BLOB nuovi/aggiornati devono essere elaborati, i messaggi vengono scritti in una coda di controllo gestita dalla piattaforma e tale coda viene elaborata usando la stessa logica usata per QueueTrigger. Quando la concorrenza dinamica è abilitata, la concorrenza per l'elaborazione di tale coda di controllo verrà gestita in modo dinamico.

Per usare la concorrenza dinamica per i BLOB, è necessario usare la versione 5.x dell'estensione di archiviazione.

Bus di servizio

Il trigger bus di servizio supporta attualmente tre modelli di esecuzione. La concorrenza dinamica influisce su questi modelli di esecuzione come indicato di seguito:

  • Elaborazione di un singolo argomento di invio/coda: ogni chiamata della funzione elabora un singolo messaggio. Quando si usa la configurazione statica, la concorrenza è governata dall'opzione MaxConcurrentCalls config. Quando si usa la concorrenza dinamica, tale valore di configurazione viene ignorato e la concorrenza viene modificata in modo dinamico.
  • Elaborazione di un singolo argomento/coda di invio basato su sessione: ogni chiamata della funzione elabora un singolo messaggio. A seconda del numero di sessioni attive per l'argomento o la coda, ogni istanza esegue il lease di una o più sessioni. I messaggi in ogni sessione vengono elaborati in modo seriale, per garantire l'ordinamento in una sessione. Quando non si usa la concorrenza dinamica, la concorrenza è governata dall'impostazione MaxConcurrentSessions . Con la concorrenza dinamica abilitata, MaxConcurrentSessions viene ignorata e il numero di sessioni elaborate da ogni istanza viene regolato in modo dinamico.
  • Elaborazione batch: ogni chiamata della funzione elabora un batch di messaggi, regolati dall'impostazione MaxMessageCount . Poiché le chiamate batch sono seriali, la concorrenza per la funzione attivata da batch è sempre una e la concorrenza dinamica non si applica.

Per abilitare il trigger di bus di servizio per usare la concorrenza dinamica, è necessario usare la versione 5.x dell'estensione bus di servizio.

Passaggi successivi

Per ulteriori informazioni, vedi le seguenti risorse: