Ottimizzazione delle prestazioni per caricamenti e download con JavaScript

Quando un'applicazione trasferisce i dati usando la libreria client di Archiviazione di Azure per JavaScript, esistono diversi fattori che possono influire sulla velocità, sull'utilizzo della memoria e persino sull'esito positivo o negativo della richiesta. Per ottimizzare le prestazioni e l'affidabilità per i trasferimenti di dati, è importante essere proattivi nella configurazione delle opzioni di trasferimento della libreria client in base all'ambiente in cui viene eseguita l'app.

Questo articolo illustra diverse considerazioni per l'ottimizzazione delle opzioni di trasferimento dei dati. Se ottimizzata correttamente, la libreria client può distribuire in modo efficiente i dati tra più richieste, con conseguente miglioramento della velocità operativa, dell'utilizzo della memoria e della stabilità di rete.

Ottimizzazione delle prestazioni per i caricamenti

L'ottimizzazione corretta delle opzioni di trasferimento dei dati è fondamentale per ottenere prestazioni affidabili per i caricamenti. I trasferimenti di archiviazione vengono partizionati in diversi sottotrasferimenti in base ai valori di questi argomenti. Le dimensioni massime di trasferimento supportate variano in base all'operazione e alla versione del servizio, quindi assicurarsi di controllare la documentazione per determinare i limiti. Per altre informazioni sui limiti delle dimensioni di trasferimento per l'archiviazione BLOB, vedere Dimensionare le destinazioni per l'archiviazione BLOB.

Impostare le opzioni di trasferimento per i caricamenti

È possibile configurare le proprietà in BlockBlobParallelUploadOptions per migliorare le prestazioni per le operazioni di trasferimento dei dati. Nella tabella seguente sono elencate le proprietà che è possibile configurare, insieme a una descrizione:

Proprietà Descrizione
blockSize Dimensione massima del blocco da trasferire per ogni richiesta come parte di un'operazione di caricamento. Per altre informazioni, vedere blockSize.
maxSingleShotSize Se le dimensioni dei dati sono minori o uguali a questo valore, i dati vengono caricati in un'unica partizione anziché suddivisi in blocchi. Se i dati vengono caricati in una volta sola, la dimensione del blocco viene ignorata. Il valore predefinito è 256 MB. Se si personalizza questa proprietà, è necessario utilizzare un valore minore o uguale a 256 MB. Per altre informazioni, vedere maxSingleShotSize.
concurrency Il numero massimo di richieste parallele generate in qualsiasi momento come parte di un singolo trasferimento parallelo.

Nota

Le librerie client useranno le impostazioni predefinite per ogni opzione di trasferimento dei dati, se non specificato altrimenti. Queste impostazioni predefinite sono in genere efficienti in un ambiente data center, ma non sono adatte per gli ambienti consumer domestici. Le opzioni di trasferimento dei dati non ottimizzate possono comportare operazioni eccessivamente lunghe e persino timeout delle richieste. È consigliabile essere proattivi nel testare questi valori e ottimizzarli in base alle esigenze dell'applicazione e dell'ambiente.

maxSingleShotSize

Il valore maxSingleShotSize è la dimensione massima del BLOB in byte per un caricamento di una singola richiesta.

Se le dimensioni dei dati sono minori o uguali a maxSingleShotSize, il BLOB viene caricato con una singola richiesta Put BLOB. Se le dimensioni del BLOB sono maggiori di maxSingleShotSize o sono sconosciute, il BLOB viene caricato in blocchi usando una serie di chiamate Put Block seguite da Put Block List.

È importante notare che il valore specificato per blockSize non limita il valore definito per maxSingleShotSize. L'argomento maxSingleShotSize definisce una limitazione delle dimensioni separata per una richiesta in modo da eseguire l'intera operazione contemporaneamente, senza sottotrasferimenti. Spesso si vuole che maxSingleShotSize sia almeno grande quanto il valore definito per blockSize, se non più grande. A seconda delle dimensioni del trasferimento dei dati, questo approccio può essere più efficiente, poiché il trasferimento viene completato con una singola richiesta ed evita il sovraccarico di più richieste.

Se non si è certi del valore migliore per la situazione, un'opzione sicura consiste nell'impostare maxSingleShotSize sullo stesso valore usato per blockSize.

blockSize

Il valore blockSize è la lunghezza massima di un trasferimento in byte durante il caricamento di un BLOB in blocchi in parti.

Come accennato in precedenza, questo valore non limita maxSingleShotSize, che può essere maggiore di blockSize.

Per mantenere efficiente lo spostamento dei dati, le librerie client potrebbero non raggiungere sempre il valore blockSize per ogni trasferimento. A seconda dell'operazione, il valore massimo supportato per le dimensioni del trasferimento può variare. Per altre informazioni sui limiti delle dimensioni di trasferimento per l'archiviazione BLOB, vedere il grafico in Dimensionare le destinazioni per l'archiviazione BLOB.

Esempio di codice

Nell'esempio di codice seguente viene illustrato come impostare i valori per BlockBlobParallelUploadOptions e includere le opzioni come parte di una chiamata al metodo di caricamento. I valori forniti in questi esempi non sono necessariamente quelli consigliati. Per ottimizzare correttamente questi valori, è necessario considerare le esigenze specifiche dell'app.

// Specify data transfer options
const uploadOptions = {
  blockSize: 4 * 1024 * 1024, // 4 MiB max block size
  concurrency: 2, // maximum number of parallel transfer workers
  maxSingleShotSize: 8 * 1024 * 1024, // 8 MiB initial transfer size
} 

// Create blob client from container client
const blockBlobClient = containerClient.getBlockBlobClient(blobName);

// Upload blob with transfer options
await blockBlobClient.uploadFile(localFilePath, uploadOptions);

In questo esempio il numero massimo di ruoli di lavoro di trasferimento parallelo viene impostato su 2, usando la proprietà concurrency. Impostiamo anche maxSingleShotSize su 8 MiB. Se le dimensioni del BLOB sono inferiori a 8 MiB, è necessaria solo una singola richiesta per completare l'operazione di caricamento. Se le dimensioni del BLOB sono maggiori di 8 MiB, il BLOB viene caricato in blocchi con una dimensione massima di 4 MiB, come definito nella proprietà blockSize.

Considerazioni sulle prestazioni per i caricamenti

Durante un caricamento, le librerie client di archiviazione suddividono un determinato flusso di caricamento in più sottocaricamenti in base alle opzioni di configurazione definite da BlockBlobParallelUploadOptions. Ogni sottocaricamento ha una propria chiamata dedicata all'operazione REST. In questo esempio l'operazione è Put Block. La libreria client di archiviazione gestisce queste operazioni REST in parallelo (a seconda delle opzioni di trasferimento) per completare il caricamento.

Nota

I BLOB in blocchi hanno un numero massimo di 50.000 blocchi. Le dimensioni massime del BLOB in blocchi, quindi, sono pari a 50.000 volte block_size.

Buffering durante i caricamenti

Il livello REST di archiviazione non supporta la ripresa di un'operazione di caricamento REST che è stata interrotta. I singoli trasferimenti vengono completati o persi. Per garantire la resilienza per i caricamenti di flussi, le librerie client di archiviazione eseguono il buffer dei dati per ogni singola chiamata REST prima di avviare il caricamento. Oltre alle limitazioni della velocità di rete, questo comportamento di buffering è un motivo per considerare un valore più piccolo per blockSize, anche quando si effettuano caricamenti in sequenza. La riduzione del valore di blockSize riduce la quantità massima di dati memorizzati nel buffer per ogni richiesta e per ogni retry di una richiesta non riuscita. Se si verificano timeout frequenti durante i trasferimenti di dati di una determinata dimensione, riducendo il valore di blockSize si riduce il tempo di memorizzazione nel buffer e si possono ottenere prestazioni migliori.

Ottimizzazione delle prestazioni per i download

L'ottimizzazione delle opzioni di trasferimento dei dati per i download è disponibile solo quando si usa il metodo downloadToBuffer. Questo metodo scarica un BLOB in parallelo in un buffer in base ai valori definiti in BlobDownloadToBufferOptions. Altri metodi di download non supportano le opzioni di ottimizzazione del trasferimento dei dati.

Impostare le opzioni di trasferimento per i download

I valori seguenti possono essere ottimizzati per i download quando si usa il metodo downloadToBuffer:

  • blockSize: dimensioni massime del blocco da trasferire per ogni richiesta.
  • concurrency: numero massimo di richieste parallele generate in qualsiasi momento come parte di un singolo trasferimento parallelo.

Considerazioni sulle prestazioni per i download

Durante un download con downloadToBuffer, le librerie client di archiviazione suddividono una determinata richiesta di download in più download secondari in base alle opzioni di configurazione definite da BlobDownloadToBufferOptions. Ogni sottodownload ha una propria chiamata dedicata all'operazione REST. A seconda delle opzioni di trasferimento, le librerie client gestiscono queste operazioni REST in parallelo per completare il download.

Esempio di codice

Nell'esempio di codice seguente viene illustrato come impostare i valori per BlobDownloadToBufferOptions e includere le opzioni come parte di una chiamata al metodo downloadToBuffer. I valori forniti in questi esempi non sono necessariamente quelli consigliati. Per ottimizzare correttamente questi valori, è necessario considerare le esigenze specifiche dell'app.

// Specify data transfer options
    const downloadToBufferOptions = {
        blockSize: 4 * 1024 * 1024, // 4 MiB max block size
        concurrency: 2, // maximum number of parallel transfer workers
    }

    // Download data to buffer
    const result = await client.downloadToBuffer(offset, count, downloadToBufferOptions);