Creare e gestire app per le funzioni nel piano A consumo Flex

Questo articolo illustra come creare app per le funzioni ospitate nel piano A consumo Flex in Funzioni di Azure. Illustra anche come gestire determinate funzionalità di un'app ospitata con piano A consumo Flex.

Le risorse dell'app per le funzioni sono specifiche del linguaggio. Assicurarsi di scegliere il linguaggio di sviluppo di codice preferito all'inizio dell'articolo.

Prerequisiti

  • Un account Azure con una sottoscrizione attiva. Chi non ha ancora un account può crearlo gratuitamente.

  • Interfaccia della riga di comando di Azure: usata per creare e gestire le risorse in Azure. Quando si usa l'interfaccia della riga di comando di Azure nel computer locale, assicurarsi di usare la versione 2.60.0 o una versione successiva. È anche possibile usare Azure Cloud Shell, con la versione corretta dell'interfaccia della riga di comando di Azure.

  • Per le app Go, usare interfaccia della riga di comando di Azure versione 2.87.0 o versione successiva. Eseguire az version per verificare la versione installata.

Creare un'app A consumo Flex

Questa sezione illustra come creare un'app per le funzioni nel piano A consumo Flex usando l'interfaccia della riga di comando di Azure, il portale di Azure o Visual Studio Code. Per un esempio di creazione di un'app in un piano A consumo Flex con modelli Bicep/ARM, vedere il repository A consumo Flex.

È possibile ignorare questa sezione se si sceglie di creare e distribuire l'app usando Maven.

Per supportare il codice della funzione, è necessario creare tre risorse:

  • Un gruppo di risorse, ovvero un contenitore logico di risorse correlate.
  • Un account di archiviazione, usato per mantenere lo stato e altre informazioni sulle funzioni.
  • Un'app per le funzioni nel piano A consumo Flex, che fornisce l'ambiente per l'esecuzione del codice della funzione. Un'app per le funzioni si collega al progetto di funzione locale e consente di raggruppare le funzioni come un'unità logica per semplificare la gestione, la distribuzione e la condivisione di risorse nel piano A consumo Flex.
  1. Se non è già stato fatto, accedere ad Azure:

    az login
    

    Il comando az login consente di accedere all'account Azure.

  2. Usare il az functionapp list-flexconsumption-locations comando per esaminare l'elenco delle aree che attualmente supportano il consumo flessibile in ordine alfabetico.

    az functionapp list-flexconsumption-locations --query "sort_by(@, &name)[].{Region:name}" -o table
    
  1. Creare un gruppo di risorse in una delle aree attualmente supportate elencate dal comando nel passaggio precedente.

    az group create --name <RESOURCE_GROUP> --location <REGION>
    

    Nel comando precedente sostituire <RESOURCE_GROUP> con un valore univoco nella sottoscrizione e <REGION> con una delle aree attualmente supportate. Il comando az group create crea un gruppo di risorse.

  2. Creare un account di archiviazione per utilizzo generico nel gruppo di risorse e nell'area:

    az storage account create --name <STORAGE_NAME> --location <REGION> --resource-group <RESOURCE_GROUP> --sku Standard_LRS --allow-blob-public-access false
    

    Nell'esempio precedente sostituire <STORAGE_NAME> con un nome appropriato per l'utente e univoco in Archiviazione di Azure. I nomi devono contenere da tre a 24 caratteri costituiti solo da numeri e lettere minuscole. Standard_LRS specifica un account per utilizzo generico supportato da Funzioni di Azure in base ai requisiti dell'account di archiviazione. Il comando az storage account create crea l'account di archiviazione.

    Importante

    L'account di archiviazione viene usato per archiviare dati importanti dell'app, a volte incluso il codice dell'applicazione stesso. È consigliabile limitare l'accesso da altre app e utenti all'account di archiviazione.

  3. Creare l'app per le funzioni in Azure:

    az functionapp create --resource-group <RESOURCE_GROUP> --name <APP_NAME> --storage-account <STORAGE_NAME> --flexconsumption-location <REGION> --runtime dotnet-isolated --runtime-version 8.0
    

    Le app C# in esecuzione in-process non sono attualmente supportate durante l'esecuzione in un piano A consumo Flex.

    az functionapp create --resource-group <RESOURCE_GROUP> --name <APP_NAME> --storage-account <STORAGE_NAME> --flexconsumption-location <REGION> --runtime java --runtime-version 17
    
    az functionapp create --resource-group <RESOURCE_GROUP> --name <APP_NAME> --storage-account <STORAGE_NAME> --flexconsumption-location <REGION> --runtime node --runtime-version 20
    
    az functionapp create --resource-group <RESOURCE_GROUP> --name <APP_NAME> --storage-account <STORAGE_NAME> --flexconsumption-location <REGION> --runtime python --runtime-version 3.11
    

    Per le app Python, è attualmente supportato anche Python 3.10.

    az functionapp create --resource-group <RESOURCE_GROUP> --name <APP_NAME> --storage-account <STORAGE_NAME> --flexconsumption-location <REGION> --runtime powershell --runtime-version 7.4
    
    az functionapp create --resource-group <RESOURCE_GROUP> --name <APP_NAME> --storage-account <STORAGE_NAME> --flexconsumption-location <REGION> --runtime go --runtime-version 1.0 --functions-version 4
    az resource update --resource-group <RESOURCE_GROUP> --resource-type Microsoft.Web/sites --name <APP_NAME> --set properties.siteConfig.http20Enabled=false
    

    Il az resource update comando disabilita HTTP/2 nell'app per le funzioni, necessario durante l'anteprima pubblica di Go.

    In questo esempio sostituire sia <RESOURCE_GROUP> che <STORAGE_NAME> con il gruppo di risorse e con il nome dell'account usato rispettivamente nel passaggio precedente. Sostituire anche <APP_NAME> con un nome univoco globale appropriato. <APP_NAME> è anche il dominio DNS (Domain Name Server) predefinito per l'app per le funzioni. Il comando az functionapp create crea l'app per le funzioni in Azure.

    Il comando az functionapp create crea un'app per funzioni che viene eseguita nel piano Flex Consumption.

    Poiché l'app è stata creata senza specificare istanze sempre pronte, l'app comporta solo costi durante l'esecuzione attiva delle funzioni. Il comando crea anche un'istanza di applicazione Azure Insights associata nello stesso gruppo di risorse, con cui è possibile monitorare l'app per le funzioni e visualizzare i log. Per altre informazioni, vedere Monitorare Funzioni di Azure.

Distribuire il progetto di codice

Per la distribuzione, le app del piano Flex Consumption usano un contenitore di archiviazione BLOB per ospitare .zip file di pacchetto che contengono il codice del progetto e tutte le librerie necessarie per l'esecuzione dell'app. Per ulteriori informazioni, vedi Distribuzione.

È possibile ignorare questa sezione se si sceglie di creare e distribuire l'app usando Maven.

È possibile scegliere di distribuire il codice del progetto in un'app per le funzioni esistente usando vari strumenti:

La distribuzione go richiede Funzioni di Azure Core Tools versione 4.12 o versione successiva. Eseguire func --version per verificare la versione installata.

È possibile usare l'interfaccia della riga di comando di Azure per caricare un file di pacchetto di distribuzione nella condivisione di distribuzione per un'app per le funzioni in Azure. Per eseguire questa distribuzione, devi produrre un file di pacchetto .zip che può essere eseguito quando il pacchetto viene montato nell'app.

Questo file di pacchetto deve contenere tutti i file di output di compilazione e le librerie di riferimento necessarie per l'esecuzione del progetto.

Per i progetti con un numero elevato di librerie, creare un pacchetto della radice del file di progetto e richiedere una compilazione remota.

Per i progetti Python, creare un pacchetto della directory radice del progetto e richiedere sempre una build remota. L'uso di una compilazione remota impedisce potenziali problemi che possono verificarsi quando si compila un progetto in Windows da distribuire in Linux.

Per i progetti Go, usare Core Tools per creare un pacchetto .zip pronto per l'esecuzione in locale, quindi distribuire il pacchetto con il interfaccia della riga di comando di Azure. Non richiedere una compilazione remota per i pacchetti Go creati da func pack.

  1. Usando lo strumento di sviluppo preferito, compilare il progetto di codice.

  2. Creare un file .zip che contiene l'output della directory di compilazione. Per altre informazioni, vedere Struttura del progetto.

  3. Se necessario, accedere all'account Azure e selezionare la sottoscrizione attiva usando il comando az login.

    az login
    
  4. Eseguire il comando az functionapp deployment source config-zip per distribuire il pacchetto applicativo che si trova nel percorso relativo <FILE_PATH>.

    az functionapp deployment source config-zip --src <FILE_PATH> --name <APP_NAME> --resource-group <RESOURCE_GROUP>
    
  1. Usando lo strumento di sviluppo preferito, compilare il progetto di codice.

  2. Creare un file .zip che contiene l'output della directory di compilazione. Per altre informazioni, vedere Struttura di cartelle.

  3. Se necessario, accedere all'account Azure e selezionare la sottoscrizione attiva usando il comando az login.

    az login
    
  4. Eseguire il comando az functionapp deployment source config-zip per distribuire il pacchetto applicativo che si trova nel percorso relativo <FILE_PATH>.

    az functionapp deployment source config-zip --src <FILE_PATH> --name <APP_NAME> --resource-group <RESOURCE_GROUP>
    
  1. Creare un file .zip che contiene la directory radice del progetto di codice. Per altre informazioni, vedere Struttura di cartelle.

  2. Se necessario, accedere all'account Azure e selezionare la sottoscrizione attiva usando il comando az login.

    az login
    
  3. Eseguire il comando az functionapp deployment source config-zip per distribuire il pacchetto applicativo che si trova nel percorso relativo <FILE_PATH>.

    az functionapp deployment source config-zip --src <FILE_PATH> --name <APP_NAME> --resource-group <RESOURCE_GROUP>
    
  1. Creare un file .zip che contiene la directory radice del progetto di codice. Per altre informazioni, vedere Struttura di cartelle.

  2. Se necessario, accedere all'account Azure e selezionare la sottoscrizione attiva usando il comando az login.

    az login
    
  3. Eseguire il comando az functionapp deployment source config-zip per distribuire il pacchetto applicativo che si trova nel percorso relativo <FILE_PATH>.

    az functionapp deployment source config-zip --src <FILE_PATH> --name <APP_NAME> --resource-group <RESOURCE_GROUP> --build-remote true
    

    Assicurarsi di impostare --build-remote true per eseguire una compilazione remota.

  1. Creare un file .zip che contiene la directory radice del progetto di codice. Per altre informazioni, vedere Struttura di cartelle.

  2. Se necessario, accedere all'account Azure e selezionare la sottoscrizione attiva usando il comando az login.

    az login
    
  3. Eseguire il comando az functionapp deployment source config-zip per distribuire il pacchetto applicativo che si trova nel percorso relativo <FILE_PATH>.

    az functionapp deployment source config-zip --src <FILE_PATH> --name <APP_NAME> --resource-group <RESOURCE_GROUP> --build-remote true
    

    Assicurarsi di impostare --build-remote true per eseguire una compilazione remota.

  1. Nella cartella del progetto radice eseguire questo comando Core Tools per compilare e creare un pacchetto del progetto Go:

    func pack
    

    Per impostazione predefinita, il file di output .zip ha lo stesso nome della cartella del progetto.

  2. Quando necessario, accedere all'account Azure e selezionare la sottoscrizione attiva usando il az login comando .

    az login
    
  3. Eseguire il az functionapp deployment source config-zip comando per distribuire il pacchetto che si trova in <ZIP_FILE_PATH>.

    az functionapp deployment source config-zip --resource-group <RESOURCE_GROUP> --name <APP_NAME> --src <ZIP_FILE_PATH>
    

Creare e distribuire l'app usando Maven

È possibile usare Maven per creare un'app per funzioni ospitata nel piano Flex Consumption e le risorse necessarie durante la distribuzione, modificando il file pom.xml.

  1. Creare un progetto di codice Java completando la prima parte di uno di questi articoli di avvio rapido:

  2. Nel progetto Java, apri il file pom.xml e apporta queste modifiche per creare la tua app per le funzioni nel piano Flex Consumption:

    • Modificare il valore di <properties>.<azure.functions.maven.plugin.version> in 1.34.0.

    • Nella sezione <plugin>.<configuration> per azure-functions-maven-plugin, aggiungere o rimuovere il commento dall'elemento <pricingTier> come indicato di seguito:

      <pricingTier>Flex Consumption</pricingTier>
      
  3. (Facoltativo) Personalizzare il piano A consumo Flex nella distribuzione Maven includendo anche questi elementi nella sezione <plugin>.<configuration>: .

    • <instanceSize> : imposta le dimensioni della memoria dell'istanza per l'app per le funzioni. Il valore predefinito è 2048.
    • <maximumInstances> : imposta il valore più alto per il numero massimo di istanze dell'app per le funzioni.
    • <alwaysReadyInstances> : imposta i conteggi delle istanze sempre pronti con gli elementi figlio per i gruppi di trigger HTTP (<http>), i gruppi di Funzioni permanenti (<durable>) e altri trigger specifici (<my_function>). Quando si imposta un numero di istanze maggiore di zero, si paga per queste istanze indipendentemente dal fatto che le funzioni vengano eseguite o meno. Per altre informazioni, vedereFatturazione.
  4. Prima di poter eseguire la distribuzione, accedere alla sottoscrizione Azure usando il interfaccia della riga di comando di Azure.

    az login
    

    Il comando az login consente di accedere all'account Azure.

  5. Usare il comando seguente per distribuire il progetto di codice in una nuova app per le funzioni in A consumo Flex.

    mvn azure-functions:deploy
    

    Maven usa le impostazioni nel modello pom.xml per creare l'app per le funzioni in un piano Flex Consumption in Azure, insieme alle altre risorse necessarie. Se queste risorse esistono già, il codice viene distribuito nell'app per le funzioni, sovrascrivendo qualsiasi codice esistente.

Creare e distribuire l'app Go

Le app per le funzioni Go sono supportate solo nel piano Flex Consumption. Per creare, eseguire e distribuire un'app per le funzioni Go, vedere Creare una funzione Go dalla riga di comando. Per informazioni dettagliate sulla struttura del progetto e sulla distribuzione specifiche di Go, vedere le informazioni di riferimento per gli sviluppatori Go.

Configurare l'integrazione della rete virtuale

È possibile abilitare l'integrazione della rete virtuale per l'app in un piano a consumo Flex quando si crea l'app o in un secondo momento. Prima di abilitare l'integrazione con la rete virtuale, esamina il comportamento di rete e i requisiti della subnet specifici di Flex Consumption.

Funzionamento della rete Flex Consumption

Le istanze Flex Consumption non usano ciascuna un indirizzo IP univoco della subnet con cui viene integrata l'app. Un pool di gateway di rete gestiti dalla piattaforma (interno all'infrastruttura flex consumption) usa invece gli indirizzi IP della subnet per gestire tutte le app integrate con tale subnet. Questa architettura di multiplexing IP è fondamentalmente diversa dai piani Premium, in cui ogni istanza usa un indirizzo IP dalla subnet.

La linea guida dei 40 indirizzi IP per app garantisce che vi siano abbastanza indirizzi IP per il pool di gateway della piattaforma e altri componenti dell'infrastruttura, ma non è un limite vincolante. Prevedi almeno questo minimo quando dimensioni la subnet, ma tieni presente che il consumo effettivo di indirizzi IP è in genere inferiore. La piattaforma alloca dinamicamente gli indirizzi IP dal pool di gateway condiviso man mano che le app integrate con la subnet si espandono orizzontalmente.

Dimensioni e requisiti della subnet

Scegliere una subnet con dimensioni appropriate per le app Flex Consumption. La tabella seguente fornisce indicazioni in base allo scenario:

Scenario CIDR consigliato INDIRIZZI IP utilizzabili Note
App Flex singola /27 27 Dimensioni minime della subnet supportate per un'app
Più applicazioni Flex in una subnet /26 59 Consigliato quando si ospitano più app e per carichi di lavoro su larga scala (oltre 1.000 istanze); offre una capacità del gateway adeguata

Delegazione subnet

  • Delega la sottorete a Microsoft.App/environments. Questa delega differisce dai piani Premium e Dedicated, che utilizzano Microsoft.Web/serverFarms.
  • Registrare il provider di risorse Microsoft.App nella sottoscrizione di Azure.

Restrizioni relative all'utilizzo delle subnet

  • La subnet non può essere già usata per endpoint privati o endpoint di servizio e non può essere delegata ad altri piani o servizi di hosting.
  • Non è possibile condividere la stessa subnet tra un ambiente App contenitore di Azure e un'app Flex Consumption.
  • I nomi delle subnet non possono contenere caratteri di sottolineatura (_), ovvero una limitazione corrente del piano Flex Consumption.

Condivisione di subnet

  • È possibile condividere la stessa subnet con più app in esecuzione in un piano A consumo consumo Flex. Tuttavia, poiché le risorse di rete vengono condivise in tutte le app, un'app per le funzioni può influire sulle prestazioni di altri utenti nella stessa subnet. Prendere in considerazione la domanda aggregata durante la compressione di più app in una subnet di piccole dimensioni.
  • La subnet e l'app devono trovarsi nella stessa area.

Allocazione e pianificazione degli indirizzi IP

  • Le app Flex Consumption non assegnano un indirizzo IP univoco a ogni istanza. Un pool di gateway di rete usa invece gli indirizzi IP della subnet. Le linee guida per prenotare 40 INDIRIZZI IP per app consentono di garantire che siano presenti indirizzi IP sufficienti per il pool di gateway e altri componenti dell'infrastruttura, ma l'utilizzo effettivo è in genere inferiore.
  • Una /27 subnet (27 IP utilizzabili) è sufficiente per una singola app in grado di supportare fino a 1.000 istanze grazie al multiplexing IP. Per più applicazioni o carichi di lavoro su larga scala, utilizzare una subnet /26 per garantire una capacità del gateway adeguata.
  • Quando molte app condividono una subnet e molte vengono anche scalate orizzontalmente con un traffico in uscita significativo, la capacità effettiva della rete in uscita può diventare un collo di bottiglia, piuttosto che l’esaurimento degli indirizzi IP. Valutare le prestazioni a livello di produzione pianificato.

Abilitare l'integrazione della rete virtuale quando si crea l'app

Gli esempi in questa sezione presuppongono che l'account contenga già una rete virtuale e una subnet.

Abilitare l'integrazione della rete virtuale eseguendo il az functionapp create comando e includendo i --vnet parametri e --subnet . La sottorete deve essere delegata a Microsoft.App/environments e deve avere una dimensione minima di /27. Per altre informazioni, vedere Dimensionamento e requisiti delle subnet.

  1. Creare la rete virtuale e la subnet, se non ne è già disponibile una.

  2. Completare i passaggi da 1 a 4 in Creare un'app A consumo Flex per creare le risorse necessarie per l'app.

  3. Eseguire il comando az functionapp create, inclusi i parametri --vnet e --subnet, come nell'esempio seguente:

    az functionapp create --resource-group <RESOURCE_GROUP> --name <APP_NAME> --storage-account <STORAGE_NAME> --flexconsumption-location <REGION> --runtime go --runtime-version 1.0 --functions-version 4 --vnet <VNET_RESOURCE_ID> --subnet <SUBNET_NAME>
    az resource update --resource-group <RESOURCE_GROUP> --resource-type Microsoft.Web/sites --name <APP_NAME> --set properties.siteConfig.http20Enabled=false
    

    Il az resource update comando disabilita HTTP/2 nell'app per le funzioni, necessario durante l'anteprima pubblica di Go.

    az functionapp create --resource-group <RESOURCE_GROUP> --name <APP_NAME> --storage-account <STORAGE_NAME> --flexconsumption-location <REGION> --runtime <RUNTIME_NAME> --runtime-version <RUNTIME_VERSION> --vnet <VNET_RESOURCE_ID> --subnet <SUBNET_NAME>
    

    Il valore <VNET_RESOURCE_ID> è l'ID risorsa per la rete virtuale, che è nel formato: /subscriptions/<SUBSCRIPTION_ID>/resourceGroups/<RESOURCE_GROUP>/providers/Microsoft.Network/virtualNetworks/<VNET_NAME>. È possibile usare questo comando per ottenere un elenco di ID di rete virtuale, filtrati in base a <RESOURCE_GROUP>: az network vnet list --resource-group <RESOURCE_GROUP> --output tsv --query "[]".id.

Per esempi end-to-end su come creare app in Flex Consumption con l'integrazione della rete virtuale, vedere queste risorse:

Modificare o rimuovere l'integrazione della rete virtuale

È possibile aggiungere, modificare o rimuovere l'integrazione della rete virtuale per un'app esistente.

Usare il comando az functionapp vnet-integration add per abilitare l'integrazione della rete virtuale in un'app per le funzioni esistente:

az functionapp vnet-integration add --resource-group <RESOURCE_GROUP> --name <APP_NAME> --vnet <VNET_RESOURCE_ID> --subnet <SUBNET_NAME>

Usare il comando az functionapp vnet-integration remove per disabilitare l'integrazione della rete virtuale nell'app:

az functionapp vnet-integration remove --resource-group <RESOURCE_GROUP> --name <APP_NAME>

Usare il comando az functionapp vnet-integration list per elencare le integrazioni di rete virtuale correnti per l'app:

az functionapp vnet-integration list --resource-group <RESOURCE_GROUP> --name <APP_NAME>

Risolvere i problemi di rete con Application Insights

Application Insights è il primo punto in cui un'app Flex Consumption mostra errori DNS, timeout delle dipendenze o altri sintomi di connettività. Acquisisce ciò che il codice ha osservato durante l'esecuzione: eccezioni, chiamate in uscita alle dipendenze e comportamento di esecuzione end-to-end. Ciò consente di distinguere gli errori a livello di applicazione dai problemi di piattaforma o di rete sottostanti.

Le tabelle di Application Insights seguenti sono più utili per le indagini di rete:

Tabella Cosa mostra Usarlo per
traces Log del runtime, dell'host, ILogger e del controller di scalabilità. In Flex Consumption i dettagli di inizializzazione della distribuzione vengono visualizzati anche qui. Problemi di avvio dell'host, comportamento di avvio a freddo, errori di distribuzione ed errori DNS che emergono dai log dell'host o delle dipendenze.
requests Una voce per ogni invocazione HTTP, con durata, codice di risultato e lo stato di successo. Trigger HTTP a latenza elevata, errori 4xx e 5xx e conferma che l'app riceve e gestisce le richieste.
exceptions Eccezioni di runtime e generate dall'utente, incluse le tracce dello stack. Analisi della causa radice per dns, Archiviazione di Azure, Azure Key Vault, modulo non trovato, timeout e errori di runtime simili.
dependencies HTTP in uscita, SQL, bus di servizio e altre chiamate di dipendenza, con codici di intervallo ed errore. I sintomi di "Funziona localmente ma non in a consumo flessibile" e gli errori DNS, TLS o di autenticazione nelle chiamate in uscita causati dal comportamento della rete virtuale, del DNS o del NAT.
customMetrics Metriche aggregate, ad esempio durata e esito positivo o numero di errori. Analisi delle tendenze, calo improvviso della frequenza di successo e picchi di durata che indicano il ridimensionamento o le esecuzioni bloccate.
FunctionAppLogs (registro delle risorse) Log dell'app per le funzioni a livello di piattaforma inviati a Monitoraggio di Azure Logs. Quando i dati di Application Insights sono mancanti o incompleti o per problemi a livello di controllo e a livello di host, ad esempio errori di associazione.
AzureActivity Operazioni del piano di controllo, ad esempio: avvio, arresto, attivazione della sincronizzazione, eliminazione ed elencazione delle chiavi. Controllo delle modifiche alla configurazione e diagnosi dei problemi di registrazione dei trigger (gli errori dei trigger di sincronizzazione sono comuni).

Interrogazioni di esempio

Usa queste query iniziali nell'esperienza Logs della risorsa di Application Insights. Sostituire <APP_NAME> con il nome dell'app per le funzioni.

Errori di avvio o distribuzione dell'host (specifici di Flex Consumption):

traces
| where timestamp > ago(1d)
| where cloud_RoleName == "<APP_NAME>"
| where message contains "Starting" or message contains "host"
| project timestamp, message, customDimensions
| order by timestamp desc

Problemi relativi al trigger HTTP, latenza o errori 5xx:

requests
| where timestamp > ago(1h)
| where cloud_RoleName == "<APP_NAME>"
| project timestamp, name, resultCode, duration, success, url, operation_Name
| order by timestamp desc

Eccezioni comuni raggruppate per tipo, ad esempio DNS, Key Vault, archiviazione o moduli language-runtime:

exceptions
| where timestamp > ago(1d)
| where cloud_RoleName == "<APP_NAME>"
| summarize count() by type, innermostMessage
| order by count_ desc

Errori di dipendenza in uscita (DNS, TLS, autenticazione, routing di rete virtuale):

dependencies
| where timestamp > ago(2h)
| where cloud_RoleName == "<APP_NAME>"
| where success == false
| project timestamp, target, resultCode, duration, type, data

Trigger non-HTTP che non si attiva (trigger della coda, del BLOB o di Event Grid). Una causa comune è che la registrazione del trigger è riuscita ma il listener non è stato abilitato; le eccezioni correlate vengono visualizzate nelle tracce del controller di scalabilità:

traces
| where timestamp > ago(2h)
| where message contains "listener" or message contains "trigger"

Risolvere i problemi relativi alle prestazioni di rete

Quando un'app Flex Consumption si integra con una subnet inferiore alle dimensioni consigliate, è possibile che si verifichi una riduzione delle prestazioni man mano che l'app viene ridimensionata. Questo problema può verificarsi anche se si integra un gran numero di app con la stessa subnet quando si espandono e hanno un volume significativo di traffico in uscita.

Sintomi di subnet sottodimensionate

Monitorare questi sintomi, che indicano che la capacità in uscita anziché gli indirizzi IP è il fattore di limitazione:

  • Maggiore latenza nelle chiamate in uscita alle dipendenze
  • Timeout di connessione ai servizi esterni
  • Questi problemi aumentano man mano che l'app si espande, non come in caso di un'interruzione improvvisa

Importante

La scalabilità orizzontale non è bloccata dalle dimensioni della subnet. L'app continua ad aggiungere istanze anche se la subnet è sottodimensionata. Si verifica un degrado delle prestazioni anziché un limite rigido di scalabilità.

Monitoraggio e mitigazione

  • Configurare Application Insights con le metriche di latenza delle dipendenze in uscita: in cui questa metrica fornisce un segnale di allarme precoce per le subnet sottodimensionate.
  • Esegui test di carico su scala di produzione prima di definire la dimensione della subnet per verificare che il dimensionamento della subnet sia in grado di gestire il carico di lavoro previsto.
  • Monitor con Monitoraggio di Azure: passare a Rete virtuale>Subnet in Monitoraggio di Azure per visualizzare i dati di allocazione IP tramite query Azure Resource Graph e KQL.
  • Dimensiona correttamente la subnet in base alle indicazioni riportate nella sezione precedente. Si consiglia vivamente un minimo di /27; per più app, è consigliato /26.

Annotazioni

Usare almeno una /27 subnet per garantire un'adeguata stabilità della piattaforma. Le subnet significativamente più piccole di /27 potrebbero presentare problemi di creazione del gateway senza alcun messaggio di errore esplicito.

Configurare le impostazioni di distribuzione

Nel piano Flex Consumption un contenitore Archiviazione BLOB di Azure contiene il pacchetto di distribuzione con il codice dell'app. Per impostazione predefinita, le distribuzioni usano lo stesso account di archiviazione (AzureWebJobsStorage) e stringa di connessione usato dal runtime di Funzioni per gestire l'app. L'impostazione dell'applicazione DEPLOYMENT_STORAGE_CONNECTION_STRING archivia il stringa di connessione. Tuttavia, è possibile designare un contenitore BLOB in un account di archiviazione separato come origine di distribuzione per il codice. È anche possibile modificare il metodo di autenticazione usato per accedere al contenitore.

Un'origine di distribuzione personalizzata deve soddisfare questi criteri:

  • L'account di archiviazione deve esistere già.
  • Anche il contenitore da usare per le distribuzioni deve esistere.
  • Quando più app usano lo stesso account di archiviazione, ogni app deve avere un proprio contenitore di distribuzione. L'uso di un contenitore univoco per ogni app impedisce la sovrascrittura dei pacchetti di distribuzione, che si verifica se le app hanno condiviso lo stesso contenitore.

Quando si configura l'autenticazione dell'archiviazione di distribuzione, tenere presenti queste considerazioni:

  • Come procedura consigliata per la sicurezza, usare le identità gestite per la connessione a Archiviazione di Azure dalle app. Per altre informazioni, vedere Connections.
  • Quando si usa una stringa di connessione per connettersi all'account di archiviazione di distribuzione, l'impostazione dell'applicazione che contiene la stringa di connessione deve esistere già.
  • Quando si usa un'identità gestita assegnata dall'utente, si collega l'identità fornita all'app per le funzioni. È anche possibile assegnare il ruolo Storage Blob Data Contributor con ambito all'account di archiviazione di distribuzione all'identità.
  • Quando si usa un'identità gestita assegnata dal sistema, si crea un'identità quando un'identità assegnata dal sistema valida non esiste già nell'app. Quando esiste un'identità assegnata dal sistema, assegni all'identità il ruolo Storage Blob Data Contributor con ambito all'account di archiviazione della distribuzione.

Per configurare le impostazioni di distribuzione quando si crea l'app per le funzioni nel piano A consumo flessibile:

Usare il az functionapp create comando e specificare queste opzioni aggiuntive per personalizzare l'archiviazione della distribuzione:

Parametro Descrizione
--deployment-storage-name Nome dell'account di archiviazione di distribuzione.
--deployment-storage-container-name Nome del contenitore nell'account in cui contenere il pacchetto di distribuzione dell'app.
--deployment-storage-auth-type Tipo di autenticazione da usare per la connessione all'account di archiviazione di distribuzione. I valori accettati includono StorageAccountConnectionString, UserAssignedIdentitye SystemAssignedIdentity.
--deployment-storage-auth-value Quando si usa StorageAccountConnectionString, impostare questo parametro sul nome dell'impostazione dell'applicazione che contiene il stringa di connessione all'account di archiviazione di distribuzione. Quando si imposta UserAssignedIdentity, impostare questo parametro sul nome dell'ID della risorsa dell'identità che si desidera usare.

Questo esempio crea un'app per le funzioni nel piano A consumo flessibile con un account di archiviazione di distribuzione separato e l'identità assegnata dall'utente:

az functionapp create --resource-group <RESOURCE_GROUP> --name <APP_NAME> --storage-account <STORAGE_NAME> --runtime dotnet-isolated --runtime-version 8.0 --flexconsumption-location "<REGION>" --deployment-storage-name <DEPLOYMENT_ACCOUNT_NAME> --deployment-storage-container-name <DEPLOYMENT_CONTAINER_NAME> --deployment-storage-auth-type UserAssignedIdentity --deployment-storage-auth-value <MI_RESOURCE_ID>

È anche possibile modificare la configurazione dell'archiviazione di distribuzione per un'app esistente.

Usare il az functionapp deployment config set comando per modificare la configurazione dell'archiviazione di distribuzione.

az functionapp deployment config set --resource-group <RESOURCE_GROUP> --name <APP_NAME> --deployment-storage-name <DEPLOYMENT_ACCOUNT_NAME> --deployment-storage-container-name <DEPLOYMENT_CONTAINER_NAME>

Configurare la memoria dell'istanza

Imposta la dimensione della memoria dell'istanza per il tuo piano Flex Consumption al momento della creazione dell'app. Per altre informazioni sulle dimensioni supportate, vedere Dimensioni dell'istanza.

Per impostare una dimensione di memoria dell'istanza diversa da quella predefinita durante la creazione dell'app:

Specificare il parametro --instance-memory nel comando az functionapp create. Questo esempio crea un'app C# con dimensioni dell'istanza di 4096:

az functionapp create --instance-memory 4096 --resource-group <RESOURCE_GROUP> --name <APP_NAME> --storage-account <STORAGE_NAME> --flexconsumption-location <REGION> --runtime dotnet-isolated --runtime-version 8.0

In qualsiasi momento, è possibile modificare l'impostazione delle dimensioni della memoria dell'istanza usata dall'app.

In questo esempio viene usato il az functionapp scale config set comando per modificare l'impostazione delle dimensioni della memoria dell'istanza su 512 MB:

az functionapp scale config set --resource-group <resourceGroup> --name <APP_NAME> --instance-memory 512

Impostare i conteggi delle istanze sempre pronti

Impostare un numero specifico di istanze sempre pronte per i gruppi di ridimensionamento per funzione o le singole funzioni per mantenere caricate le funzioni e pronte per l'esecuzione. Esistono tre gruppi speciali, come nel ridimensionamento per funzione:

  • http - Tutte le funzioni attivate da HTTP nell'app vengono ridimensionate insieme nelle proprie istanze.
  • durable - Tutte le funzioni attivate da Durable (Orchestration, Activity, Entity) nell'app vengono ridimensionate insieme nelle proprie istanze.
  • blob - Tutte le funzioni attivate da BLOB (Event Grid) nell'app scalano insieme nelle rispettive istanze.

Usare http, durable o blob come nome per l'impostazione della coppia nome-valore per configurare i conteggi sempre pronti per questi gruppi. Per tutte le altre funzioni nell'app, configurare la funzionalità Sempre pronta per ciascuna funzione usando il formato function:<FUNCTION_NAME>=n.

Per definire una o più designazioni di istanza sempre pronte, usare il --always-ready-instances parametro con il az functionapp create comando . In questo esempio viene impostato il numero di istanze sempre pronte per tutte le funzioni attivate da HTTP su 10:

az functionapp create --resource-group <RESOURCE_GROUP> --name <APP_NAME> --storage-account <STORAGE_NAME> --runtime <LANGUAGE_RUNTIME> --runtime-version <RUNTIME_VERSION> --flexconsumption-location <REGION> --always-ready-instances http=10
az functionapp create --resource-group <RESOURCE_GROUP> --name <APP_NAME> --storage-account <STORAGE_NAME> --runtime go --runtime-version 1.0 --functions-version 4 --flexconsumption-location <REGION> --always-ready-instances http=10
az resource update --resource-group <RESOURCE_GROUP> --resource-type Microsoft.Web/sites --name <APP_NAME> --set properties.siteConfig.http20Enabled=false

Il az resource update comando disabilita HTTP/2 nell'app per le funzioni, necessario durante l'anteprima pubblica di Go.

Questo esempio imposta il numero di istanze sempre pronte per tutte le funzioni trigger Durable su 3 e imposta il numero di istanze sempre pronte su 2 per una funzione attivata dal bus di servizio denominata function5:

az functionapp create --resource-group <RESOURCE_GROUP> --name <APP_NAME> --storage-account <STORAGE_NAME> --runtime <LANGUAGE_RUNTIME> --runtime-version <RUNTIME_VERSION> --flexconsumption-location <REGION> --always-ready-instances durable=3 function:function5=2

In questo esempio il numero di istanze sempre pronte viene impostato su 2 per una funzione attivata bus di servizio denominata function5:

az functionapp create --resource-group <RESOURCE_GROUP> --name <APP_NAME> --storage-account <STORAGE_NAME> --runtime go --runtime-version 1.0 --functions-version 4 --flexconsumption-location <REGION> --always-ready-instances function:function5=2
az resource update --resource-group <RESOURCE_GROUP> --resource-type Microsoft.Web/sites --name <APP_NAME> --set properties.siteConfig.http20Enabled=false

Il az resource update comando disabilita HTTP/2 nell'app per le funzioni, necessario durante l'anteprima pubblica di Go.

È anche possibile modificare istanze sempre pronte in un'app esistente aggiungendo o rimuovendo le designazioni di istanza o modificando i conteggi delle designazioni di istanza esistenti.

In questo esempio viene usato il comando az functionapp scale config always-ready set per modificare il numero di istanze sempre pronte per il gruppo trigger HTTP in 10:

az functionapp scale config always-ready set --resource-group <RESOURCE_GROUP> --name <APP_NAME> --settings http=10

Per rimuovere istanze sempre pronte, usare il comando az functionapp scale config always-ready delete, come in questo esempio che rimuove tutte le istanze sempre pronte dal gruppo trigger HTTP e anche da una funzione denominata hello_world:

az functionapp scale config always-ready delete --resource-group <RESOURCE_GROUP> --name <APP_NAME> --setting-names http function:hello_world

Impostare i limiti di concorrenza HTTP

Se non imposti limiti specifici, il sistema determina i valori predefiniti della concorrenza HTTP per le app del piano Flex Consumption in base all'impostazione relativa alle dimensioni dell'istanza. Per altre informazioni, vedere concorrenza del trigger HTTP.

Ecco come impostare i limiti di concorrenza HTTP per un'app esistente:

Usare il comando az functionapp scale config set per impostare limiti di concorrenza HTTP specifici per l'app, indipendentemente dalle dimensioni dell'istanza.

az functionapp scale config set --resource-group <RESOURCE_GROUP> --name <APP_NAME> --trigger-type http --trigger-settings perInstanceConcurrency=10

In questo esempio viene impostato il livello di concorrenza del trigger HTTP su 10. Dopo aver impostato un valore di concorrenza HTTP, l'app mantiene tale valore nonostante le modifiche apportate all'impostazione delle dimensioni dell'istanza dell'app.

Impostare la strategia di aggiornamento del sito

Il piano Flex Consumption supporta in modo univoco due diverse strategie di aggiornamento del sito che controllano il modo in cui l'app per le funzioni gestisce le distribuzioni di codice e le modifiche di configurazione. Per impostazione predefinita, le app del piano Flex Consumption utilizzano la strategia Recreate, che interrompe l'esecuzione delle funzioni attualmente in corso durante le distribuzioni. Per abilitare distribuzioni senza tempi di inattività, è invece possibile configurare la strategia RollingUpdate. Per altre informazioni, vedere Strategie di aggiornamento del sito in Flex Consumption.

Annotazioni

La configurazione della strategia di aggiornamento del sito è attualmente disponibile in anteprima pubblica ed è disponibile solo tramite modelli Bicep o ARM. Non è possibile configurare questa impostazione usando il interfaccia della riga di comando di Azure, il portale di Azure o Visual Studio Code.

Il interfaccia della riga di comando di Azure attualmente non supporta la configurazione della strategia di aggiornamento del sito. Usare modelli Bicep o ARM come descritto in Configurare la strategia di aggiornamento del sito.

Configurare i certificati a livello di sito

Flex Consumption introduce i certificati con ambito sito, un nuovo modello in cui i certificati TLS/SSL hanno come ambito l'app per le singole funzioni anziché essere condivise tra le app nello stesso spazio Web. La tabella seguente illustra i tipi di certificato supportati e il modo in cui ognuno viene aggiunto all'app per le funzioni:

Tipo di certificato Come aggiungere Contribuisce a
Certificato gestito di App Service Creato nel portale per un dominio personalizzato Limite di certificati privati
Certificato del servizio app Acquistato tramite Azure, quindi importato Limite di certificati privati
Certificato importato da Key Vault Importato da Azure Key Vault Limite di certificati privati
Certificato privato caricato (pfx) Caricato come file PFX Limite di certificati privati
Certificato pubblico caricato (.cer) Caricato come un file CER Limite di certificati pubblici

Considerazioni per i certificati con ambito limitato al sito

  • Il supporto per l'utilizzo di certificati con ambito del sito per le app in esecuzione in un piano Flex Consumption è attualmente in anteprima.
  • Le app esistenti create prima che questa funzionalità diventasse disponibile non dispone attualmente di un percorso di migrazione per i certificati. Per usare i certificati con ambito sito, creare una nuova app per le funzioni Flex Consumption.
  • In interfaccia della riga di comando di Azure il supporto per la gestione dei certificati con ambito del sito non è ancora disponibile. Nel frattempo, usare il portale Azure o ARM/Bicep modelli per gestire i certificati.
  • Ogni app supporta un massimo di tre certificati privati e tre certificati pubblici.
  • I certificati privati devono essere esportati come file PFX protetto da password che contiene tutti i certificati intermedi e il certificato radice nella catena di certificati.
  • La crittografia end-to-end (E2E) non è attualmente supportata.
  • I certificati ECC (Elliptic Curve Cryptography) sono supportati quando vengono caricati come PFX.
  • Poiché Flex Consumption viene eseguito in Linux, il codice deve caricare i certificati dai percorsi dei file anziché dall'archivio certificati Windows. Prima di tutto, seguire la procedura descritta in Rendere un certificato accessibile al codice per caricare i certificati nell'ambiente di runtime. Quindi, per istruzioni su come leggere i file di certificato dal codice dell'applicazione, vedere Caricare i certificati nei contenitori Linux/Windows.

Aggiungere un certificato

È possibile aggiungere certificati all'app in diversi modi, a seconda del tipo di certificato. Aggiungere certificati gestiti e Azure gratuiti direttamente nel portale.

Selezionare una delle schede seguenti per vedere come aggiungere un certificato gestito, privato (pfx), pubblico (.cer) o Key Vault gestito.

Per creare e associare un certificato gestito gratuito per un dominio personalizzato:

  1. Nel portale Azure passare all'app per le funzioni.

  2. Nel menu a sinistra espandere Impostazioni e selezionare Domini personalizzati.

  3. Selezionare Aggiungi dominio personalizzato.

  4. In Certificato TLS/SSL, selezionare Certificato gestito di App Service.

  5. In TIPO TLS/SSL selezionare SSL SNI.

  6. Completare la convalida del dominio e selezionare Aggiungi.

    Il certificato gestito viene creato e associato automaticamente al dominio personalizzato. L'emissione del certificato potrebbe richiedere fino a 10 minuti.

Rendere accessibile un certificato al codice

Dopo aver aggiunto un certificato, è necessario renderlo accessibile in modo esplicito al codice della funzione.

  1. Nel portale Azure passare all'app per le funzioni.

  2. Nel menu a sinistra espandere Impostazioni e selezionare Certificati.

  3. Selezionare Bring your own certificates (.pfx) o Public key certificates (.cer).

  4. Selezionare ... (puntini di sospensione) accanto al certificato che si vuole rendere accessibile e quindi scegliere Rendi accessibile al codice dell'app.

Quando si abilita l'opzione Accessibile al codice dell'app, la piattaforma carica il certificato nell'ambiente di runtime in tutte le istanze come file.

I file di certificato sono denominati in base all'impronta digitale e collocati in queste directory:

Tipo di certificato Percorso
Certificati pubblici (.cer) /var/ssl/certs
Certificati privati (pfx) /var/ssl/private

Rinnovare o aggiornare un certificato

I certificati gestiti gratuiti vengono rinnovati automaticamente dalla piattaforma. Per tutti gli altri certificati, il modo in cui si aggiorna un certificato in scadenza dipende dall'origine del certificato:

  • Certificati importati da Key Vault: Quando si rinnova un certificato in Key Vault, il processo in background della piattaforma sincronizza automaticamente il certificato aggiornato con l'app per le funzioni entro 24 ore. La nuova versione del certificato viene caricata in tutte le istanze senza alcuna procedura manuale.

  • Certificati caricati: caricare il nuovo certificato e renderlo accessibile al codice dell'app. Se il codice fa riferimento al certificato tramite identificazione personale, aggiornare eventuali riferimenti all'identificazione personale nelle impostazioni del codice o dell'app.

Visualizzare le aree attualmente supportate

Per visualizzare l'elenco delle aree che attualmente supportano i piani flex consumption, vedere:

  1. Se non è già stato fatto, accedere ad Azure:

    az login
    

    Il comando az login consente di accedere all'account Azure.

  2. Usare il az functionapp list-flexconsumption-locations comando per esaminare l'elenco delle aree che attualmente supportano il consumo flessibile in ordine alfabetico.

    az functionapp list-flexconsumption-locations --query "sort_by(@, &name)[].{Region:name}" -o table
    

Quando si crea un'app nel portale Azure o usando Visual Studio Code, l'elenco delle aree esclude attualmente le aree non supportate.

Monitorare l'app in Azure

Monitoraggio di Azure offre set distinti di metriche per comprendere meglio come funziona l'app per le funzioni in Azure.

  • Metriche della piattaforma: fornisce informazioni dettagliate a livello di infrastruttura
  • Application Insights: fornisce informazioni dettagliate a livello di codice, incluse tracce e log degli errori.

Se si abilita Application Insights nell'app, è possibile:

  • Tenere traccia dei tempi di esecuzione dettagliati e delle dipendenze
  • Monitorare le prestazioni delle singole funzioni
  • Analizzare gli errori e le eccezioni
  • Correlare le metriche della piattaforma con il comportamento dell'applicazione usando query personalizzate

Per altre informazioni, vedere Monitorare Funzioni di Azure.

Metriche supportate

Eseguire questo script per visualizzare tutte le metriche della piattaforma attualmente disponibili per l'app:

appId=$(az functionapp show --name <APP_NAME> --resource-group <RESOURCE_GROUP> --query id -o tsv)
az monitor metrics list-definitions --resource $appId --query "[].{Name:name.localizedValue,Value:name.value}" -o table

In questo esempio sostituire <RESOURCE_GROUP> e <APP_NAME> con il gruppo di risorse e i nomi delle app per le funzioni. Questo script ottiene l'ID app completo e restituisce le metriche della piattaforma disponibili in una tabella.

Visualizza le metriche

È possibile esaminare le metriche correnti nel portale di Azure o usando l'interfaccia della riga di comando di Azure.

Nel portale di Azure è anche possibile creare avvisi delle metriche e aggiungere grafici e altri report ai dashboard nel portale.

Usare questo script per generare un report delle metriche correnti per l'app:

appId=$(az functionapp show --name <APP_NAME> --resource-group <RESOURCE_GROUP> --query id -o tsv)

echo -e "\nAlways-ready and on-demand execution counts..."
az monitor metrics list --resource $appId --metric "AlwaysReadyFunctionExecutionCount" --interval PT1H --output table
az monitor metrics list --resource $appId --metric "OnDemandFunctionExecutionCount" --interval PT1H --output table

echo -e "\nExecution units (MB-ms) in always-ready and on-demand execution counts..."
az monitor metrics list --resource $appId --metric "AlwaysReadyFunctionExecutionUnits" --interval PT1H --output table
az monitor metrics list --resource $appId --metric "OnDemandFunctionExecutionUnits" --interval PT1H --output table

echo -e "\nAlways-ready resource utilization..."
az monitor metrics list --resource $appId --metric "AlwaysReadyUnits" --interval PT1H --output table

echo -e "\nMemory utilization..."
az monitor metrics list --resource $appId --metric "AverageMemoryWorkingSet" --interval PT1H --output table
az monitor metrics list --resource $appId --metric "MemoryWorkingSet" --interval PT1H --output table

echo -e "\nInstance count and CPU utilization..."
az monitor metrics list --resource $appId --metric "InstanceCount" --interval PT1H --output table
az monitor metrics list --resource $appId --metric "CpuPercentage" --interval PT1H --output table

Per altre informazioni sulle metriche per Funzioni di Azure, vedere Monitorare Funzioni di Azure.

Visualizza i log

Quando si connette l'app ad Application Insights, è possibile analizzare meglio le prestazioni dell'app e risolvere i problemi durante l'esecuzione. Nella risorsa di Application Insights per l'app:

  • Usare Prestazioni per analizzare i tempi di risposta e le dipendenze.
  • Usare Errori per identificare eventuali errori che si verificano dopo la migrazione.
  • Creare query personalizzate in Log per analizzare il comportamento della funzione.

Ad esempio, usare questa query per confrontare le percentuali di esito positivo per istanza:

Usare questa query per confrontare le percentuali di esito positivo in base all'istanza:

requests
| where timestamp > ago(7d)
| summarize successCount=countif(success == true), failureCount=countif(success == false) by bin(timestamp, 1h), cloud_RoleName
| render timechart

Usare questa query per analizzare il numero di istanze che elaborano attivamente la funzione:

let _startTime = ago(20m); //Adjust start time as needed
let _endTime = now(); //Adjust end time as needed
let bins = 1s; //Adjust bin as needed - this will give per second results
requests
| where operation_Name == 'EventHubsTrigger' //Replace with the name of the function in the function app that you are analyzing
| where timestamp between(_startTime .. _endTime)
| make-series dcount(cloud_RoleInstance) default=0 on timestamp from _startTime to _endTime step bins
| render columnchart

Visualizzare i costi

Poiché è possibile ottimizzare l'app per regolare le prestazioni rispetto ai costi operativi, è importante tenere traccia dei costi associati all'esecuzione dell'app nel piano Flex Consumption.

Per visualizzare i costi correnti:

  1. Nella pagina dell'app per le funzioni nel portale di Azure selezionare il collegamento al gruppo di risorse.

  2. Nella pagina del gruppo di risorse, selezionare Gestione costi>Analisi costi.

  3. Esaminare i costi correnti e la traiettoria dei costi dell'app stessa.

  4. Facoltativamente, selezionare Gestione costi>Avvisi e quindi + Aggiungi per creare un avviso per l'applicazione.

Ottimizzare l'app

Il piano Flex Consumption offre diverse impostazioni che è possibile ottimizzare per perfezionare le prestazioni dell'app. Le prestazioni e i costi effettivi possono variare in base ai modelli e alla configurazione del carico di lavoro specifici dell'app. Ad esempio, dimensioni di istanze di memoria superiori possono migliorare le prestazioni per le operazioni a elevato utilizzo di memoria, ma a un costo più elevato per periodo attivo.

Ecco alcune modifiche che è possibile apportare per ottimizzare le prestazioni rispetto ai costi: