

La versione 4 (V4) di è stata rilasciata\! AWS SDK per .NET 

Per informazioni sulle modifiche sostanziali e sulla migrazione delle applicazioni, consulta l'argomento sulla [ migrazione. ](https://docs.aws.amazon.com/sdk-for-net/v4/developer-guide/net-dg-v4.html)

 [![Orange button with text "Click here for details".](http://docs.aws.amazon.com/it_it/sdk-for-net/v4/developer-guide/images/BannerButton_less-round.png)](https://docs.aws.amazon.com/sdk-for-net/v4/developer-guide/net-dg-v4.html)

Le traduzioni sono generate tramite traduzione automatica. In caso di conflitto tra il contenuto di una traduzione e la versione originale in Inglese, quest'ultima prevarrà.

# Le migliori pratiche prestazionali per AWS SDK per .NET
<a name="net-dg-performance"></a>

Il modo in cui create i client, gestite le risposte e configurate l'applicazione ha un grande effetto sulla velocità effettiva, sulla latenza e sull'uso della memoria. Questo argomento descrive i modelli di utilizzo e configurazione che aiutano le applicazioni a funzionare in modo efficiente e affidabile. Questi modelli sono particolarmente importanti in condizioni di carico elevato o in ambienti con risorse limitate, come contenitori e funzioni serverless. Seguendo queste pratiche è possibile migliorare le prestazioni e prevenire problemi comuni come risposte lente, blocchi e uso elevato della memoria.

Le pratiche più efficaci sono le seguenti:
+ [Riutilizza un singolo client di servizio di lunga durata ](#net-dg-performance-reuse-clients) invece di crearne uno per richiesta.
+ [Elimina le risposte e gli stream ](#net-dg-performance-dispose) in modo che le connessioni di rete vengano restituite al pool di connessioni.
+ [Usa`async`/`await`correttamente ](#net-dg-performance-async) e non bloccare mai le chiamate SDK asincrone.
+ [Configura la garbage collection .NET ](#net-dg-performance-gc) per ambienti vincolati come Amazon ECS. AWS Lambda 
+ [Gestisci le connessioni HTTP ](#net-dg-performance-connections) e i limiti di connessione con un throughput elevato.

Prima di iniziare, assicurati di aver [ impostato il tuo ambiente ](net-dg-config.md) e [ configurato il tuo progetto](configuring-the-sdk.md).

## Riutilizza un singolo client di servizio di lunga durata
<a name="net-dg-performance-reuse-clients"></a>

I client di servizio come [ AmazonS3Client [ AmazonDynamoDBClient ](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/items/DynamoDBv2/TDynamoDBClient.html) sono * thread-safe*, relativamente costosi da costruire ](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/items/S3/TS3Client.html) e duraturi. * * * * La creazione di un client risolve le informazioni sulla regione e sugli endpoint e stabilisce l'infrastruttura HTTP sottostante. Crea un client per servizio e riutilizzalo per tutta la durata dell'applicazione. Se chiami più di una regione, crea un client separato per ciascuna regione.

**avvertimento**  
Non creare un nuovo client di servizio per ogni richiesta o all'interno di un ciclo. La creazione ripetuta di client altera l'infrastruttura HTTP sottostante, aggiungendo una latenza misurabile. Inoltre, può esaurire socket o handle e causare il fallimento o il blocco delle richieste sotto carico.

Nelle applicazioni che utilizzano l'iniezione di dipendenze, registrate il client come singleton. Il metodo di `AddAWSService` estensione del `AWSSDK.Extensions.NETCore.Setup` NuGet pacchetto registra il client con una durata predefinita di. `ServiceLifetime.Singleton` Il client viene creato la prima volta che viene richiesto e la stessa istanza viene riutilizzata per tutta la durata del processo. Per ulteriori informazioni sulla registrazione AWS dei servizi con inserimento delle dipendenze e sulle opzioni di lettura della configurazione, vedere. [AWSSDK.Extensions.NETCore.Setup e iConfiguration](net-dg-config-netcore.md)

È inoltre possibile registrare un client come singleton manualmente.

```
builder.Services.AddSingleton<IAmazonS3>(_ => new AmazonS3Client());
```

**Nota**  
Poiché per impostazione predefinita `AddAWSService` registra il client come singleton, non eliminate il client che fornisce. Se hai bisogno di una durata non predefinita, passa un `ServiceLifetime` valore diverso al parametro opzionale di. `lifetime` `AddAWSService`

Riutilizzare il client ** non ** significa smettere di eliminare le risposte successive all'operazione. Riutilizzate il client per tutta la durata dell'applicazione, ma continuate a eliminare le risposte e i flussi restituiti dalle singole operazioni, come descritto in. [Elimina le risposte e gli stream](#net-dg-performance-dispose)

## Elimina le risposte e gli stream per liberare le connessioni
<a name="net-dg-performance-dispose"></a>

Alcuni oggetti di risposta SDK trasmettono un flusso di rete in tempo reale. L'esempio più comune è [ GetObjectResponse](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/items/S3/TGetObjectResponse.html), che implementa `IDisposable` ed espone il contenuto dell'oggetto tramite la sua proprietà. `ResponseStream` La risposta mantiene una connessione HTTP aperta finché lo stream non viene letto completamente o la risposta non viene eliminata. Se si diffondono queste risposte (ad esempio, richiamando `GetObject` un ciclo senza eliminare ogni risultato), le connessioni aperte si accumulano fino all'esaurimento del pool di connessioni e la chiamata successiva viene bloccata. Questa è la causa delle segnalazioni di download che «si bloccano casualmente» o si bloccano sull'ennesimo oggetto.

Racchiudi sempre una risposta in streaming in una `using` dichiarazione e leggi o copia il relativo stream prontamente.

```
using Amazon.S3;
using Amazon.S3.Model;

// s3Client is a reused, long-lived client.
var request = new GetObjectRequest { BucketName = bucketName, Key = key };

using var response = await s3Client.GetObjectAsync(request);
await response.WriteResponseStreamToFileAsync(filePath, append: false, CancellationToken.None);
```

L'eliminazione della risposta e la sua eliminazione `ResponseStream` sono equivalenti; entrambe chiudono il flusso di rete sottostante e restituiscono la connessione al pool.

**Suggerimento**  
Se ti servono solo i metadati degli oggetti, come dimensione, ora dell'ultima modifica, tipo di contenuto o ETag, chiama or invece di. `GetObjectMetadata` `GetObjectMetadataAsync` `GetObject` L'operazione sui metadati invia una `HEAD` richiesta HTTP e non trasferisce il corpo dell'oggetto, quindi non c'è alcun flusso di contenuti da gestire.  

```
var metadata = await s3Client.GetObjectMetadataAsync(bucketName, key);
Console.WriteLine($"Size: {metadata.ContentLength} bytes");
```

**avvertimento**  
I tipi di risposta e stream, ad esempio, `GetObjectResponse` non implementano un finalizzatore, quindi non puoi fare affidamento su Garbage Collection per rilasciare le loro connessioni al posto tuo. Le risposte e gli stream devono essere eliminati in modo deterministico con o con una chiamata esplicita. `using` `Dispose`

## Usa correttamente async/await
<a name="net-dg-performance-async"></a>

Nel moderno .NET, le operazioni di servizio in AWS SDK per .NET sono asincrone e restituiscono un. `Task` In .NET Framework esistono anche metodi sincroni, ma le chiamate asincrone hanno una scalabilità migliore e sono consigliate. Completa le operazioni con `await` e propagati `async` attraverso ogni livello del codice fino al punto di ingresso. Per ulteriori informazioni sulla programmazione asincrona con l'SDK, consulta. [Programmazione asincrona](sdk-net-async-api.md)

**avvertimento**  
Non bloccare una chiamata SDK asincrona con,, o. `.Result` `.Wait()` `.GetAwaiter().GetResult()` Questo * pattern di * sincronizzazione su asincrono è una causa comune delle applicazioni che si bloccano:  
In caso di caricamento, il blocco delle chiamate consuma i thread più velocemente di quanto possa crescere il pool di thread, quindi le continuazioni non possono essere eseguite. Questa carenza di * thread-pool * appare come un blocco a tempo indeterminato ed è la modalità di errore dominante nel moderno .NET (dove non è presente alcun valore predefinito). ASP.NET Core `SynchronizationContext`
Alcuni contesti acquisiscono un formato`SynchronizationContext`, ad esempio le applicazioni classiche,, e .NET ASP.NET Windows Forms FrameworkWPF. Blazor WebAssembly In questi contesti, il blocco del thread chiamante mentre una continuazione richiede lo stesso thread produce un deadlock. * * Le operazioni nell'SDK vengono utilizzate `ConfigureAwait(false)` internamente, quindi non inviano le loro continuazioni nel contesto acquisito. La situazione di stallo deriva da un `async` codice presente in un'altra parte della catena di chiamate che lo rileva. L'utilizzo di chiamate SDK con `await` tutto il sistema evita completamente il problema.

Il metodo seguente blocca la chiamata asincrona e può bloccare o interrompere il pool di thread.

```
// Anti-pattern: do not do this.
public GetObjectResponse Get(GetObjectRequest request)
{
    return s3Client.GetObjectAsync(request).Result;
}
```

Effettua invece il metodo e la chiamata. `async` `await`

```
public async Task<GetObjectResponse> GetAsync(GetObjectRequest request)
{
    return await s3Client.GetObjectAsync(request);
}
```

Raccomandazioni aggiuntive per il codice asincrono:
+ Effettua una `CancellationToken` risposta a ogni operazione in modo da poter annullare una chiamata lenta o bloccata anziché interromperla. Per ulteriori informazioni, consulta [Utilizzo del `CancellationToken` parametro per i timeout](retries-timeouts.md#timeouts-async).
+ Non inserire eccezioni in un blocco vuoto. `catch` In questo modo si nasconde il vero fallimento e si rende un blocco indistinguibile da un errore. Rileva le eccezioni specifiche e registrale.
+ Quando si genera nuovamente un'eccezione rilevata, `throw;` usatela `throw ex;` in modo da preservare la traccia dello stack originale.
+ Se dovete effettuare una chiamata da un limite sincrono, trattatela come ultima risorsa e isolate il lavoro dal contesto catturato anziché impostare il blocco delle chiamate come modello predefinito.

## Configura la garbage collection .NET per AWS Lambda e Amazon ECS
<a name="net-dg-performance-gc"></a>

Quando un contenitore sembra avere una «perdita di memoria», il garbage collector (GC) .NET potrebbe conservare la memoria recuperata per poterla riutilizzare. Di conseguenza, la memoria di processo può apparire elevata e stabile anche quando l'heap gestito non aumenta. Inoltre, il GC non rileva automaticamente il limite di memoria di un contenitore (il relativo limite cgroup). In un ambiente vincolato, l'heap potrebbe quindi aumentare verso la memoria dell'host anziché il limite del contenitore. Ciò può comportare la chiusura `OutOfMemoryException` o la chiusura del contenitore.

Per aiutare il GC a funzionare bene in ambienti limitati:
+ Imposta un limite di memoria esplicito sul contenitore in modo che il GC rispetti il limite di cgroup, and/or imposta la `DOTNET_GCHeapHardLimit` (un valore di byte assoluto, in esadecimale) o la variabile di ambiente per limitare l'heap gestito. `DOTNET_GCHeapHardLimitPercent` In diversi casi segnalati di esaurimento della memoria di Amazon ECS, l'impostazione di un limite di memoria rigida ha risolto i crash.
+ Sugli host small AWS Lambda e Amazon ECS, valuta la possibilità di disabilitare la garbage collection simultanea (in background) in modo che il raccoglitore non riservi memoria aggiuntiva; ad esempio, imposta la variabile di ambiente su o impostala nel `DOTNET_gcConcurrent` file di progetto. `0` `<ConcurrentGarbageCollection>false</ConcurrentGarbageCollection>`
+ Limita la tua concorrenza. L'avvio di più operazioni contemporaneamente, ad esempio richiamare una raccolta `Task.WhenAll` di grandi dimensioni, aumenta la memoria del processo e può compromettere il pool di connessioni. Limita invece il grado di parallelismo. Ad esempio, evita questo schema illimitato:

  ```
  // Anti-pattern: starts one task per item with no limit.
  await Task.WhenAll(keys.Select(key => s3Client.GetObjectMetadataAsync(bucket, key)));
  ```

  Invece, limita la concorrenza con: `Parallel.ForEachAsync`

  ```
  var options = new ParallelOptions { MaxDegreeOfParallelism = 10 };
  await Parallel.ForEachAsync(keys, options, async (key, token) =>
  {
      await s3Client.GetObjectMetadataAsync(bucket, key, token);
  });
  ```

Per ulteriori informazioni su queste impostazioni, vedi Opzioni di configurazione del [ runtime per la garbage collection ](https://learn.microsoft.com/en-us/dotnet/core/runtime-config/garbage-collector) su learn.microsoft.com. Per indicazioni specifiche sull' AWS elaborazione, consulta il post sul blog di AWS Developer Tools [ Configuring .NET Garbage Collection for Amazon ECS e. AWS Lambda](https://aws.amazon.com/blogs/developer/configuring-net-garbage-collection-for-amazon-ecs-and-aws-lambda)

## Gestisci le connessioni HTTP e i limiti di connessione
<a name="net-dg-performance-connections"></a>

In condizioni di throughput elevato, sono comuni due problemi relativi alla connessione. Il primo è l'apertura di troppe connessioni di breve durata. Ciò esaurisce le porte temporanee, lascia spazio ai socket e aumenta la latenza dell'handshake TCP `TIME_WAIT` e TLS. Il secondo è il numero insufficiente di connessioni disponibili, il che limita il parallelismo. Il riutilizzo di un singolo client di lunga durata (vedi[Riutilizza i client di servizio](#net-dg-performance-reuse-clients)) è la base per un pool di connessioni sano, perché il pooling dipende dal client che viene riutilizzato.

Per regolare il numero di connessioni simultanee per endpoint, imposta la proprietà sulla configurazione del client. `MaxConnectionsPerServer` Quando questa proprietà è `null` (impostazione predefinita), si applica l'`HttpClientHandler`impostazione predefinita sottostante, che è effettivamente illimitata nel moderno .NET. Aumentalo solo quando molte richieste simultanee allo stesso endpoint hanno un collo di bottiglia nelle connessioni. Un buon punto di partenza è il numero massimo di richieste simultanee previste per endpoint. Impostarlo su un valore molto più elevato rispetto alle esigenze del carico di lavoro comporta uno spreco di socket senza migliorare la produttività.

```
using Amazon.S3;

var config = new AmazonS3Config
{
    MaxConnectionsPerServer = 50
};

var s3Client = new AmazonS3Client(config);
```

Se utilizzi già l'iniezione delle dipendenze, configura i tuoi clienti tramite. `AWSSDK.Extensions.NETCore.Setup` Questo è l'approccio consigliato quando si utilizza DI o si registrano diversi client di servizio. Centralizza la configurazione e semplifica l'iniezione e il test dei client. È possibile impostare i valori di configurazione dalla configurazione dell'applicazione anziché nel codice. Per ulteriori informazioni, consulta [AWSSDK.Extensions.NETCore.Setup e iConfiguration](net-dg-config-netcore.md).

Infine, limita il tuo parallelismo in modo da non avviare più operazioni simultanee di quelle consentite dal limite di connessione. Ad esempio, gate call con una `SemaphoreSlim` dimensione pari al limite di connessione:

```
var throttle = new SemaphoreSlim(50); // match MaxConnectionsPerServer
await throttle.WaitAsync(token);
try
{
    await s3Client.GetObjectAsync(request, token);
}
finally
{
    throttle.Release();
}
```

## Configura timeout e tentativi
<a name="net-dg-performance-timeouts"></a>

I timeout e i tentativi hanno un effetto diretto sulle prestazioni percepite. Un `Timeout` valore troppo alto consente a una richiesta bloccata per un lungo periodo di tempo. Quando un servizio sta già restituendo errori di limitazione, una politica di ripetizione aggressiva aggiunge più richieste e può peggiorare la limitazione. Scegliete una politica di ripetizione che soddisfi la tolleranza della vostra applicazione per quanto riguarda la latenza rispetto agli errori e lasciate che le eccezioni reali si propaghino invece di riprovare in modo da mascherare un blocco.

**Nota**  
La `Timeout` proprietà non influisce sulle chiamate asincrone. Se si utilizzano chiamate asincrone, vedere invece. [Utilizzo del `CancellationToken` parametro per i timeout](retries-timeouts.md#timeouts-async)

Per ulteriori informazioni sulle modalità di riprova e sulla `Timeout` proprietà (`ReadWriteTimeout`si applica solo a.NET Framework), insieme ad esempi su come impostarle, vedere. `MaxErrorRetry` [Ritentativi e timeout](retries-timeouts.md)

## Ottimizza lo streaming e i trasferimenti di oggetti di grandi dimensioni (Amazon S3)
<a name="net-dg-performance-streaming"></a>

Per caricare e scaricare oggetti di grandi dimensioni o molti oggetti, utilizzate la [ TransferUtility ](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/items/S3/TTransferUtility.html) classe nel `Amazon.S3.Transfer` namespace. Carica e scarica in parallelo utilizzando trasferimenti in più parti e gestisce flussi, parti e connessioni per te. È più veloce di un trasferimento a flusso singolo ed è il metodo consigliato per spostare oggetti di grandi dimensioni.
+ **Download parallelo in più parti. ** Le versioni precedenti dell'SDK scaricavano un oggetto come flusso singolo, anziché scaricarne parti in parallelo. A partire dalla `AWSSDK.S3` versione 4.0.17, `TransferUtility` fornisce il download in più parti (parallelo) tramite i metodi`DownloadWithResponseAsync`, e`OpenStreamWithResponseAsync`. `DownloadDirectoryWithResponseAsync` Quando si utilizza`OpenStreamWithResponseAsync`, le parti dell'oggetto vengono memorizzate nel buffer mentre si consuma il flusso restituito. Controlla quante parti vengono bufferizzate con la `MaxInMemoryParts` proprietà di. [ TransferUtilityOpenStreamRequest ](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/items/S3/TTransferUtilityOpenStreamRequest.html) Per la maggior parte dei trasferimenti, preferisci`TransferUtility`. Scarica tu stesso gli intervalli di byte con la `ByteRange` proprietà di [ GetObjectRequest ](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/items/S3/TGetObjectRequest.html) solo quando hai bisogno di un intervallo specifico o di uno schema di parallelismo personalizzato. Per ulteriori informazioni, consulta [ Introduzione al supporto per il download in più parti per AWS SDK for .NET Transfer Manager ](https://aws.amazon.com/blogs/developer/introducing-multipart-download-support-for-aws-sdk-for-net-transfer-manager/) nel Developer Tools Blog. AWS 
+ **Lunghezza dei contenuti da caricare. ** Un Amazon S3 `PUT` richiede una lunghezza del contenuto nota e, per impostazione predefinita, l'SDK calcola un checksum sul corpo della richiesta. Quando la lunghezza è nota e lo stream è ricercabile, l'SDK può farlo senza bufferizzare l'intero oggetto in memoria. `TransferUtility`Gestisce automaticamente gli stream non ricercabili mediante il buffering, se necessario. Se invece chiami `PutObjectAsync` direttamente con uno stream non ricercabile (ad esempio il corpo di una richiesta non elaborato), la richiesta può fallire. ASP.NET Core Fornisci uno stream ricercabile, imposta la lunghezza del contenuto in modo esplicito o configura il modo in cui l'SDK calcola i checksum. Per ulteriori informazioni, consulta la sezione Protezione [ dell'integrità ](https://docs.aws.amazon.com/sdkref/latest/guide/feature-dataintegrity.html) dei dati nella Guida di riferimento di SDK e strumenti. AWS 
+ **Dimensionamento delle parti. ** Amazon S3 consente un massimo di 10.000 parti per caricamento multiparte. Quando la lunghezza totale è nota, l'SDK calcola automaticamente una dimensione della parte che rimane entro questo limite. Devi principalmente `PartSize` impostarti per stream la cui lunghezza non è nota in anticipo. Altrimenti, le parti predefinite di piccole dimensioni possono superare il limite per un caricamento molto grande. Una parte di dimensioni maggiori riduce inoltre il sovraccarico per parte, al costo di una maggiore memoria per parte.

## Diagnostica problemi di prestazioni
<a name="net-dg-performance-diagnose"></a>

Quando analizzi un rallentamento, un blocco o una perdita apparente, i seguenti segnali ti aiutano a individuare rapidamente la causa:
+ Un numero crescente di socket nello `TIME_WAIT` stato `CLOSE_WAIT` or (visibili con`netstat`) è l'impronta digitale delle risposte non disposte o dei clienti creati e scartati a ogni richiesta. Consulta [Elimina le risposte e gli stream](#net-dg-performance-dispose) e [Riutilizza i client di servizio](#net-dg-performance-reuse-clients).
+ Abilita le metriche delle richieste e la registrazione delle risposte per confermare che le richieste vengano effettivamente inviate e per misurare la latenza. Imposta le proprietà dell'[LoggingConfig](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/items/Util/TLoggingConfig.html)oggetto su [ AWSConfigs ](https://docs.aws.amazon.com/sdkfornet/v4/apidocs/items/Amazon/TAWSConfigs.html) prima di creare i tuoi client di servizio. Un client acquisisce impostazioni, ad esempio `LogMetrics` quando viene creato.

  ```
  using Amazon;
  
  AWSConfigs.LoggingConfig.LogMetrics = true;
  AWSConfigs.LoggingConfig.LogResponses = ResponseLoggingOption.OnError;
  ```
+ Quando esamini la memoria, distingui la memoria dell'intero processo dall'heap gestito. La memoria di processo elevata ma stabile è spesso la memoria recuperata dal GC piuttosto che una perdita. Consulta [Configura la raccolta dei rifiuti](#net-dg-performance-gc).