Compartir vía


Transferencia de datos con la biblioteca de movimiento de datos

Nota:

En este artículo se indica cómo trabajar con la versión 2.0.XX de la biblioteca de movimiento de datos de Azure Storage. La versión 2.0.XX está actualmente en mantenimiento y la biblioteca solo recibe correcciones para incidencias de integridad y seguridad de datos. No se agregará ninguna nueva funcionalidad ni características y la biblioteca no admitirá nuevas versiones del servicio de almacenamiento.

Las versiones beta de una biblioteca de movimiento de datos moderna están actualmente en desarrollo. Para más información, consulte Biblioteca cliente común de Movimiento de datos de Azure Storage para .NET en GitHub.

La biblioteca de movimiento de datos de Azure Storage es una biblioteca multiplataforma de código abierto que se ha diseñado para carga, descarga y copia de alto rendimiento de blobs y archivos. La biblioteca de movimiento de datos proporciona métodos útiles que no están disponibles en la biblioteca de cliente de Azure Storage para .NET. Estos métodos permiten establecer el número de operaciones paralelas, realizar un seguimiento del progreso de la transferencia, reanudar fácilmente una transferencia cancelada y mucho más.

Esta biblioteca también utiliza .NET Core, lo que significa que puede usarla para crear aplicaciones .NET para Windows, Linux y MacOS. Para más información sobre .NET Core, consulte la documentación de .NET Core. Esta biblioteca también funciona para las aplicaciones de .NET Framework tradicionales para Windows.

En este documento se muestra cómo crear una aplicación de consola de .NET Core que se ejecuta en Windows, Linux y MacOS y se llevan a cabo los siguientes escenarios:

  • Cargar archivos y directorios en Blob Storage.
  • Definir el número de operaciones paralelas al transferir datos.
  • Seguir el progreso de la transferencia de datos.
  • Reanudar la transferencia de datos cancelada.
  • Copiar el archivo desde la dirección URL en Blob Storage.
  • Copiar de Blob Storage a Blob Storage.

Requisitos previos

Configurar

  1. Visite la guía de instalación de .NET Core para instalar el SDK de .NET Core. Cuando seleccione el entorno, elija la opción de línea de comandos.
  2. Desde la línea de comandos, cree un directorio para el proyecto. Vaya a este directorio y escriba dotnet new console -o <sample-project-name> para crear un proyecto de consola en C#.
  3. Abra este directorio en Visual Studio Code. Este paso puede realizarse rápidamente a través de la línea de comandos; para ello, escriba code . en Windows.
  4. Instale la extensión de C# desde Visual Studio Code Marketplace. Reinicie Visual Studio Code.
  5. Llegados a este punto, debe ver dos mensajes. Uno es para agregar "recursos necesarios para compilar y depurar". Seleccione "Sí." El otro mensaje es para restaurar dependencias no resueltas. Seleccione "restaurar."
  6. Modifique launch.json de .vscode para usar un terminal externo como consola. Esta configuración debe leerse como "console": "externalTerminal"
  7. Visual Studio Code permite depurar aplicaciones de .NET Core. Presione F5 para ejecutar la aplicación y compruebe que la configuración funciona. Debería ver que se imprime "Hola mundo" en la consola.

Incorporación de la biblioteca de movimiento de datos al proyecto

  1. Agregue la versión más reciente de la biblioteca de movimiento de datos a la sección dependencies del archivo <project-name>.csproj. En el momento de la escritura, esta versión sería "Microsoft.Azure.Storage.DataMovement": "0.6.2".
  2. Debe aparecer un mensaje para restaurar el proyecto. Seleccione el botón "restaurar". También puede restaurar el proyecto desde la línea de comandos escribiendo el comando dotnet restore en la raíz del directorio del proyecto.

Modifique <project-name>.csproj:

<Project Sdk="Microsoft.NET.Sdk">
    <PropertyGroup>
        <OutputType>Exe</OutputType>
        <TargetFramework>netcoreapp2.0</TargetFramework>
    </PropertyGroup>
    <ItemGroup>
        <PackageReference Include="Microsoft.Azure.Storage.DataMovement" Version="0.6.2" />
        </ItemGroup>
    </Project>

Configuración del marco de trabajo de la aplicación

Lo primero que hacemos es configurar el marco de código para nuestra aplicación. Este código nos pide un nombre de cuenta de almacenamiento y una clave de cuenta y usa esas credenciales para crear un objeto CloudStorageAccount. Este objeto se usa para interactuar con nuestra cuenta de almacenamiento en todos los escenarios de transferencia. El código también nos pedirá que elijamos el tipo de operación de transferencia que se desea ejecutar.

Modifique Program.cs:

using System;
using System.Threading;
using System.Threading.Tasks;
using System.Diagnostics;
using Microsoft.Azure.Storage;
using Microsoft.Azure.Storage.Blob;
using Microsoft.Azure.Storage.DataMovement;

namespace DMLibSample
{
    public class Program
    {
        public static void Main()
        {
            Console.WriteLine("Enter Storage account name:");
            string accountName = Console.ReadLine();

            Console.WriteLine("\nEnter Storage account key:");
            string accountKey = Console.ReadLine();

            string storageConnectionString = "DefaultEndpointsProtocol=https;AccountName=" + accountName + ";AccountKey=" + accountKey;
            CloudStorageAccount account = CloudStorageAccount.Parse(storageConnectionString);

            ExecuteChoice(account);
        }

        public static void ExecuteChoice(CloudStorageAccount account)
        {
            Console.WriteLine("\nWhat type of transfer would you like to execute?\n1. Local file --> Azure Blob\n2. Local directory --> Azure Blob directory\n3. URL (e.g. Amazon S3 file) --> Azure Blob\n4. Azure Blob --> Azure Blob");
            int choice = int.Parse(Console.ReadLine());

            if(choice == 1)
            {
                TransferLocalFileToAzureBlob(account).Wait();
            }
            else if(choice == 2)
            {
                TransferLocalDirectoryToAzureBlobDirectory(account).Wait();
            }
            else if(choice == 3)
            {
                TransferUrlToAzureBlob(account).Wait();
            }
            else if(choice == 4)
            {
                TransferAzureBlobToAzureBlob(account).Wait();
            }
        }

        public static async Task TransferLocalFileToAzureBlob(CloudStorageAccount account)
        {

        }

        public static async Task TransferLocalDirectoryToAzureBlobDirectory(CloudStorageAccount account)
        {

        }

        public static async Task TransferUrlToAzureBlob(CloudStorageAccount account)
        {

        }

        public static async Task TransferAzureBlobToAzureBlob(CloudStorageAccount account)
        {

        }
    }
}

Importante

En este ejemplo de código se usa una cadena de conexión para autorizar el acceso a la cuenta de almacenamiento. Esta configuración es por ejemplo. Las cadenas de conexión y las claves de acceso de la cuenta deben usarse con precaución en el código de aplicación. Si la clave de acceso de la cuenta se pierde o se coloca por accidente en una ubicación no segura, el servicio puede volverse vulnerable. Cualquier persona que tenga la clave de acceso puede autorizar las solicitudes en la cuenta de almacenamiento y tiene acceso eficaz a todos los datos.

Carga de un archivo local a un blob

Agregue los métodos GetSourcePath y GetBlob a Program.cs:

public static string GetSourcePath()
{
    Console.WriteLine("\nProvide path for source:");
    string sourcePath = Console.ReadLine();

    return sourcePath;
}

public static CloudBlockBlob GetBlob(CloudStorageAccount account)
{
    CloudBlobClient blobClient = account.CreateCloudBlobClient();

    Console.WriteLine("\nProvide name of Blob container:");
    string containerName = Console.ReadLine();
    CloudBlobContainer container = blobClient.GetContainerReference(containerName);
    container.CreateIfNotExistsAsync().Wait();

    Console.WriteLine("\nProvide name of new Blob:");
    string blobName = Console.ReadLine();
    CloudBlockBlob blob = container.GetBlockBlobReference(blobName);

    return blob;
}

Modifique el método TransferLocalFileToAzureBlob:

public static async Task TransferLocalFileToAzureBlob(CloudStorageAccount account)
{
    string localFilePath = GetSourcePath();
    CloudBlockBlob blob = GetBlob(account);
    Console.WriteLine("\nTransfer started...");
    await TransferManager.UploadAsync(localFilePath, blob);
    Console.WriteLine("\nTransfer operation complete.");
    ExecuteChoice(account);
}

Este código nos pide la ruta de acceso a un archivo local, el nombre de un contenedor nuevo o existente y el nombre de un nuevo blob. El método TransferManager.UploadAsync realiza la carga con esta información.

Presione F5 para ejecutar la aplicación. Puede comprobar que se ha producido la carga mediante la visualización de la cuenta de Storage con el Explorador de Microsoft Azure Storage.

Establecimiento del número de operaciones paralelas

La biblioteca de movimiento de datos ofrece la capacidad de establecer el número de operaciones paralelas para aumentar el rendimiento de la transferencia de datos. De forma predeterminada, la biblioteca de movimiento de datos establece el número de operaciones paralelas en 8 veces el número de núcleos de la máquina.

Tenga en cuenta que muchas operaciones paralelas en un entorno de ancho de banda bajo pueden sobrecargar la conexión de red y evitar que las operaciones se completen completamente. Debe experimentar con esta configuración para determinar qué funciona mejor en función del ancho de banda de red disponible.

En este ejemplo, agregamos código que nos permite establecer el número de operaciones paralelas. También agregamos código que tarda cuánto tiempo tarda la transferencia en completarse.

Agregar un método SetNumberOfParallelOperations a Program.cs:

public static void SetNumberOfParallelOperations()
{
    Console.WriteLine("\nHow many parallel operations would you like to use?");
    string parallelOperations = Console.ReadLine();
    TransferManager.Configurations.ParallelOperations = int.Parse(parallelOperations);
}

Modifique el método ExecuteChoice para usar SetNumberOfParallelOperations:

public static void ExecuteChoice(CloudStorageAccount account)
{
    Console.WriteLine("\nWhat type of transfer would you like to execute?\n1. Local file --> Azure Blob\n2. Local directory --> Azure Blob directory\n3. URL (e.g. Amazon S3 file) --> Azure Blob\n4. Azure Blob --> Azure Blob");
    int choice = int.Parse(Console.ReadLine());

    SetNumberOfParallelOperations();

    if(choice == 1)
    {
        TransferLocalFileToAzureBlob(account).Wait();
    }
    else if(choice == 2)
    {
        TransferLocalDirectoryToAzureBlobDirectory(account).Wait();
    }
    else if(choice == 3)
    {
        TransferUrlToAzureBlob(account).Wait();
    }
    else if(choice == 4)
    {
        TransferAzureBlobToAzureBlob(account).Wait();
    }
}

Modifique el método TransferLocalFileToAzureBlob para usar un temporizador:

public static async Task TransferLocalFileToAzureBlob(CloudStorageAccount account)
{
    string localFilePath = GetSourcePath();
    CloudBlockBlob blob = GetBlob(account);
    Console.WriteLine("\nTransfer started...");
    Stopwatch stopWatch = Stopwatch.StartNew();
    await TransferManager.UploadAsync(localFilePath, blob);
    stopWatch.Stop();
    Console.WriteLine("\nTransfer operation completed in " + stopWatch.Elapsed.TotalSeconds + " seconds.");
    ExecuteChoice(account);
}

Seguimiento del progreso de transferencia

Puede realizar un seguimiento del progreso de la transferencia durante la operación de transferencia mediante la creación de un objeto TransferContext. El objeto TransferContext tiene dos formas: SingleTransferContext para transferencias de archivos únicos y DirectoryTransferContext para transferencias de directorios.

Agregue los métodos GetSingleTransferContext y GetDirectoryTransferContext a Program.cs:

public static SingleTransferContext GetSingleTransferContext(TransferCheckpoint checkpoint)
{
    SingleTransferContext context = new SingleTransferContext(checkpoint);

    context.ProgressHandler = new Progress<TransferStatus>((progress) =>
    {
        Console.Write("\rBytes transferred: {0}", progress.BytesTransferred );
    });

    return context;
}

public static DirectoryTransferContext GetDirectoryTransferContext(TransferCheckpoint checkpoint)
{
    DirectoryTransferContext context = new DirectoryTransferContext(checkpoint);

    context.ProgressHandler = new Progress<TransferStatus>((progress) =>
    {
        Console.Write("\rBytes transferred: {0}", progress.BytesTransferred );
    });

    return context;
}

Modifique el método TransferLocalFileToAzureBlob para usar GetSingleTransferContext:

public static async Task TransferLocalFileToAzureBlob(CloudStorageAccount account)
{
    string localFilePath = GetSourcePath();
    CloudBlockBlob blob = GetBlob(account);
    TransferCheckpoint checkpoint = null;
    SingleTransferContext context = GetSingleTransferContext(checkpoint);
    Console.WriteLine("\nTransfer started...\n");
    Stopwatch stopWatch = Stopwatch.StartNew();
    await TransferManager.UploadAsync(localFilePath, blob, null, context);
    stopWatch.Stop();
    Console.WriteLine("\nTransfer operation completed in " + stopWatch.Elapsed.TotalSeconds + " seconds.");
    ExecuteChoice(account);
}

Reanudación de una transferencia cancelada

Otra característica que ofrece la biblioteca de movimiento de datos es la capacidad de reanudar una transferencia cancelada. A continuación, agregamos código que nos permite cancelar temporalmente la transferencia escribiendo c, y a continuación, reanudamos la transferencia 3 segundos más tarde.

Modifique el método TransferLocalFileToAzureBlob:

public static async Task TransferLocalFileToAzureBlob(CloudStorageAccount account)
{
    string localFilePath = GetSourcePath();
    CloudBlockBlob blob = GetBlob(account);
    TransferCheckpoint checkpoint = null;
    SingleTransferContext context = GetSingleTransferContext(checkpoint);
    CancellationTokenSource cancellationSource = new CancellationTokenSource();
    Console.WriteLine("\nTransfer started...\nPress 'c' to temporarily cancel your transfer...\n");

    Stopwatch stopWatch = Stopwatch.StartNew();
    Task task;
    ConsoleKeyInfo keyinfo;
    try
    {
        task = TransferManager.UploadAsync(localFilePath, blob, null, context, cancellationSource.Token);
        while(!task.IsCompleted)
        {
            if(Console.KeyAvailable)
            {
                keyinfo = Console.ReadKey(true);
                if(keyinfo.Key == ConsoleKey.C)
                {
                    cancellationSource.Cancel();
                }
            }
        }
        await task;
    }
    catch(Exception e)
    {
        Console.WriteLine("\nThe transfer is canceled: {0}", e.Message);
    }

    if(cancellationSource.IsCancellationRequested)
    {
        Console.WriteLine("\nTransfer will resume in 3 seconds...");
        Thread.Sleep(3000);
        checkpoint = context.LastCheckpoint;
        context = GetSingleTransferContext(checkpoint);
        Console.WriteLine("\nResuming transfer...\n");
        await TransferManager.UploadAsync(localFilePath, blob, null, context);
    }

    stopWatch.Stop();
    Console.WriteLine("\nTransfer operation completed in " + stopWatch.Elapsed.TotalSeconds + " seconds.");
    ExecuteChoice(account);
}

Hasta ahora, nuestro valor de checkpoint se ha establecido null. Ahora, si se cancela la transferencia, recuperaremos el último punto de comprobación de dicha transferencia y luego utilizaremos este nuevo punto de comprobación en nuestro contexto de la transferencia.

Transferencia de un directorio local a Blob Storage

La biblioteca movimiento de datos permite transferir un directorio de archivos y todos sus subdirectorios, como se muestra en el ejemplo siguiente.

En primer lugar, agregue el método GetBlobDirectory a Program.cs:

public static CloudBlobDirectory GetBlobDirectory(CloudStorageAccount account)
{
    CloudBlobClient blobClient = account.CreateCloudBlobClient();

    Console.WriteLine("\nProvide name of Blob container. This can be a new or existing Blob container:");
    string containerName = Console.ReadLine();
    CloudBlobContainer container = blobClient.GetContainerReference(containerName);
    container.CreateIfNotExistsAsync().Wait();

    CloudBlobDirectory blobDirectory = container.GetDirectoryReference("");

    return blobDirectory;
}

A continuación, modifique TransferLocalDirectoryToAzureBlobDirectory:

public static async Task TransferLocalDirectoryToAzureBlobDirectory(CloudStorageAccount account)
{
    string localDirectoryPath = GetSourcePath();
    CloudBlobDirectory blobDirectory = GetBlobDirectory(account);
    TransferCheckpoint checkpoint = null;
    DirectoryTransferContext context = GetDirectoryTransferContext(checkpoint);
    CancellationTokenSource cancellationSource = new CancellationTokenSource();
    Console.WriteLine("\nTransfer started...\nPress 'c' to temporarily cancel your transfer...\n");

    Stopwatch stopWatch = Stopwatch.StartNew();
    Task task;
    ConsoleKeyInfo keyinfo;
    UploadDirectoryOptions options = new UploadDirectoryOptions()
    {
        Recursive = true
    };

    try
    {
        task = TransferManager.UploadDirectoryAsync(localDirectoryPath, blobDirectory, options, context, cancellationSource.Token);
        while(!task.IsCompleted)
        {
            if(Console.KeyAvailable)
            {
                keyinfo = Console.ReadKey(true);
                if(keyinfo.Key == ConsoleKey.C)
                {
                    cancellationSource.Cancel();
                }
            }
        }
        await task;
    }
    catch(Exception e)
    {
        Console.WriteLine("\nThe transfer is canceled: {0}", e.Message);
    }

    if(cancellationSource.IsCancellationRequested)
    {
        Console.WriteLine("\nTransfer will resume in 3 seconds...");
        Thread.Sleep(3000);
        checkpoint = context.LastCheckpoint;
        context = GetDirectoryTransferContext(checkpoint);
        Console.WriteLine("\nResuming transfer...\n");
        await TransferManager.UploadDirectoryAsync(localDirectoryPath, blobDirectory, options, context);
    }

    stopWatch.Stop();
    Console.WriteLine("\nTransfer operation completed in " + stopWatch.Elapsed.TotalSeconds + " seconds.");
    ExecuteChoice(account);
}

Hay algunas diferencias entre este método y el método para cargar un único archivo. Ahora estamos usando TransferManager.UploadDirectoryAsync y el método getDirectoryTransferContext que hemos creado anteriormente. Además, ahora proporcionamos un valor de options a nuestra operación de carga, lo que nos permite indicar que deseamos incluir los subdirectorios en nuestra carga.

Copia de un archivo desde una dirección URL a un blob

Ahora, vamos a agregar código que nos permite copiar un archivo desde una dirección URL a un blob de Azure.

Modifique TransferUrlToAzureBlob:

public static async Task TransferUrlToAzureBlob(CloudStorageAccount account)
{
    Uri uri = new Uri(GetSourcePath());
    CloudBlockBlob blob = GetBlob(account);
    TransferCheckpoint checkpoint = null;
    SingleTransferContext context = GetSingleTransferContext(checkpoint);
    CancellationTokenSource cancellationSource = new CancellationTokenSource();
    Console.WriteLine("\nTransfer started...\nPress 'c' to temporarily cancel your transfer...\n");

    Stopwatch stopWatch = Stopwatch.StartNew();
    Task task;
    ConsoleKeyInfo keyinfo;
    try
    {
        task = TransferManager.CopyAsync(uri, blob, CopyMethod.ServiceSideAsyncCopy, null, context, cancellationSource.Token);
        while(!task.IsCompleted)
        {
            if(Console.KeyAvailable)
            {
                keyinfo = Console.ReadKey(true);
                if(keyinfo.Key == ConsoleKey.C)
                {
                    cancellationSource.Cancel();
                }
            }
        }
        await task;
    }
    catch(Exception e)
    {
        Console.WriteLine("\nThe transfer is canceled: {0}", e.Message);
    }

    if(cancellationSource.IsCancellationRequested)
    {
        Console.WriteLine("\nTransfer will resume in 3 seconds...");
        Thread.Sleep(3000);
        checkpoint = context.LastCheckpoint;
        context = GetSingleTransferContext(checkpoint);
        Console.WriteLine("\nResuming transfer...\n");
        await TransferManager.CopyAsync(uri, blob, CopyMethod.ServiceSideAsyncCopy, null, context, cancellationSource.Token);
    }

    stopWatch.Stop();
    Console.WriteLine("\nTransfer operation completed in " + stopWatch.Elapsed.TotalSeconds + " seconds.");
    ExecuteChoice(account);
}

Un caso de uso importante para esta característica es cuando necesita mover datos de otro servicio en la nube a Azure. Si tiene una dirección URL que le proporciona acceso al recurso, puede mover fácilmente ese recurso a blobs de Azure mediante el método TransferManager.CopyAsync. Este método también introduce un parámetro CopyMethod. La siguiente tabla muestra las opciones disponibles para este parámetro:

Nombre del miembro Valor Descripción
SyncCopy 0 Descargue los datos del origen a la memoria y cargue los datos de la memoria en el destino. Solo está disponible actualmente para copiar desde un recurso de Azure Storage a otro.
ServiceSideAsyncCopy 1 Envíe una solicitud de copia de inicio a Azure Storage para permitir que realice la copia; supervise el progreso de la operación de copia hasta que se complete la copia.
ServiceSideSyncCopy 2 Copie el contenido de cada fragmento con Poner bloque desde dirección URL, Anexar bloque desde dirección URL o Poner página desde dirección URL.

Copia de un blob

Otra característica proporcionada por la biblioteca de movimiento de datos es la capacidad de copiar de un recurso de Azure Storage a otro.

Modifique el método TransferAzureBlobToAzureBlob:

public static async Task TransferAzureBlobToAzureBlob(CloudStorageAccount account)
{
    CloudBlockBlob sourceBlob = GetBlob(account);
    CloudBlockBlob destinationBlob = GetBlob(account);
    TransferCheckpoint checkpoint = null;
    SingleTransferContext context = GetSingleTransferContext(checkpoint);
    CancellationTokenSource cancellationSource = new CancellationTokenSource();
    Console.WriteLine("\nTransfer started...\nPress 'c' to temporarily cancel your transfer...\n");

    Stopwatch stopWatch = Stopwatch.StartNew();
    Task task;
    ConsoleKeyInfo keyinfo;
    try
    {
        task = TransferManager.CopyAsync(sourceBlob, destinationBlob, CopyMethod.SyncCopy, null, context, cancellationSource.Token);
        while(!task.IsCompleted)
        {
            if(Console.KeyAvailable)
            {
                keyinfo = Console.ReadKey(true);
                if(keyinfo.Key == ConsoleKey.C)
                {
                    cancellationSource.Cancel();
                }
            }
        }
        await task;
    }
    catch(Exception e)
    {
        Console.WriteLine("\nThe transfer is canceled: {0}", e.Message);
    }

    if(cancellationSource.IsCancellationRequested)
    {
        Console.WriteLine("\nTransfer will resume in 3 seconds...");
        Thread.Sleep(3000);
        checkpoint = context.LastCheckpoint;
        context = GetSingleTransferContext(checkpoint);
        Console.WriteLine("\nResuming transfer...\n");
        await TransferManager.CopyAsync(sourceBlob, destinationBlob, CopyMethod.SyncCopy, null, context, cancellationSource.Token);
    }

    stopWatch.Stop();
    Console.WriteLine("\nTransfer operation completed in " + stopWatch.Elapsed.TotalSeconds + " seconds.");
    ExecuteChoice(account);
}

En este ejemplo, se establece el parámetro booleano de TransferManager.CopyAsync en CopyMethod.SyncCopy para indicar que desea hacer una copia sincrónica. Esta configuración significa que el recurso se descarga primero en la máquina local y, a continuación, se carga en Azure Blob. La opción de copia sincrónica es una excelente manera de asegurarse de que la operación de copia tiene una velocidad constante. En cambio, la velocidad de una copia asincrónica del lado servidor depende del ancho de banda de red disponible en el servidor, el cual puede fluctuar. Sin embargo, la copia sincrónica podría generar costos de salida adicionales en comparación con la copia asincrónica. El enfoque recomendado es usar la copia sincrónica en una máquina virtual de Azure que se encuentra en la misma región que la cuenta de almacenamiento de origen para evitar el costo de salida.

La aplicación de movimiento de datos ahora está completa. El ejemplo de código completo está disponible en GitHub.

Pasos siguientes

Documentación de referencia de la biblioteca de movimiento de datos de Azure Storage.

Sugerencia

Administre recursos de Azure Blob Storage con el Explorador de Azure Storage. El Explorador de Azure Storage es una aplicación independiente y gratuita de Microsoft que permite administrar recursos de Azure Blob Storage. Mediante el Explorador de Azure Storage, puede crear visualmente, leer, actualizar y eliminar blobs y contenedores de blobs, así como administrar el acceso a los suyos.