Перенос данных с помощью библиотеки перемещения данных

Примечание.

Эта статья содержит рекомендации по работе с библиотекой перемещения данных служба хранилища Azure версии 2.0.XX. Версия 2.0.XX в настоящее время находится в режиме обслуживания, и библиотека получает исправления только для проблем с целостностью данных и безопасностью. Новые функциональные возможности или функции не будут добавлены, а новые версии службы хранилища не будут поддерживаться библиотекой.

Бета-версии современной библиотеки перемещения данных в настоящее время находятся в разработке. Дополнительные сведения см. в служба хранилища Azure клиентской библиотеке "Перемещение данных" для .NET на сайте GitHub.

Библиотека перемещения данных службы хранилища Azure — это кроссплатформенная библиотека открытого кода, предназначенная для высокопроизводительной передачи, скачивания и копирования больших двоичных объектов и файлов. Библиотека перемещения данных предоставляет удобные методы, которые недоступны в клиентской библиотеке службы хранилища Azure для .NET. Эти методы позволяют задать количество параллельных операций, отслеживать ход передачи, легко возобновлять отмененную передачу и многое другое.

Эта библиотека также использует .NET Core, а это означает, что ее можно применять при создании приложений .NET для Windows, Linux и MacOS. Дополнительные сведения о .NET Core см. документации по .NET Core. Эта библиотека также подходит для традиционных приложений .NET Framework для Windows.

В этом документе показано, как создать консольное приложение .NET Core, которое работает в Windows, Linux и MacOS и выполняет приведенные ниже функции.

  • Передача файлов и каталогов в хранилище BLOB-объектов.
  • Определение количества параллельных операций при передаче данных.
  • Отслеживание выполнения передачи данных.
  • Возобновление отмененной передачи данных.
  • Копирование файла по URL-адресу в хранилище BLOB-объектов.
  • Копирование из хранилища BLOB-объектов в хранилище BLOB-объектов.

Необходимые компоненты

Настройка

  1. Ознакомьтесь с руководством по установке .NET Core, чтобы установить .NET Core SDK. При выборе среды щелкните параметр командной строки.
  2. В командной строке создайте каталог для проекта. Перейдите в этот каталог и введите dotnet new console -o <sample-project-name> для создания проекта консольного приложения C#.
  3. Откройте этот каталог в Visual Studio Code. Этот шаг можно быстро выполнить, введя в командной строке code . в Windows.
  4. Установите расширение C# из Marketplace для Visual Studio Code. Перезапустите Visual Studio Code.
  5. На этом этапе должны отобразиться два запроса. Одним из них является добавление "необходимых ресурсов для сборки и отладки". Выберите "Да". Другой запрос — восстановление неразрешенных зависимостей. Выберите "Восстановить".
  6. Измените launch.json в .vscode, чтобы использовать внешний терминал в качестве консоли. Этот параметр следует читать как "console": "externalTerminal".
  7. Visual Studio Code позволяет отлаживать приложения .NET Core. Нажмите клавишу F5, чтобы запустить приложение и проверить настройки. В консоли должно появиться сообщение "Hello World!"

Добавление в проект библиотеки перемещения данных

  1. Добавьте последнюю версию библиотеки перемещения данных в раздел dependencies файла <project-name>.csproj. На момент написания статьи это версия "Microsoft.Azure.Storage.DataMovement": "0.6.2".
  2. Должен появиться запрос на восстановление проекта. Нажмите кнопку "Восстановить". Можно также восстановить проект из командной строки, введя команду dotnet restore в корневом каталоге проекта.

Измените <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>

Настройка платформы приложений

Первое, что мы делаем, — это настройка платформы кода для нашего приложения. Этот код запрашивает имя учетной записи хранения и ключ учетной записи хранения и использует эти учетные данные для создания CloudStorageAccount объекта. Этот объект используется для взаимодействия с нашей учетной записью хранения во всех сценариях передачи. Код также предлагает выбрать тип операции передачи, которую нужно выполнить.

Измените 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)
        {

        }
    }
}

Внимание

В этом примере кода используется строка подключения для авторизации доступа к учетной записи хранения. Эта конфигурация используется для примера. Строки подключения и ключи доступа к учетной записи должны использоваться с осторожностью в коде приложения. Если ключ доступа к учетной записи потерян или случайно помещен в небезопасное расположение, ваша служба может стать уязвимой. Любой пользователь, имеющий ключ доступа, может авторизовать запросы к учетной записи хранения и эффективно иметь доступ ко всем данным.

Отправка локального файла в большой двоичный объект

Добавьте методы GetSourcePath и GetBlob в 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;
}

Измените метод 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);
}

Этот код запрашивает путь к локальному файлу, имя нового или существующего контейнера и имя нового большого двоичного объекта. На основе этой информации метод TransferManager.UploadAsync выполняет передачу.

Нажмите клавишу F5, чтобы запустить приложение. Чтобы проверить, выполнена ли передача, можно просмотреть свою учетную запись хранения в Microsoft Azure Storage Explorer.

Настройка количества параллельных операций

Библиотека перемещения данных предоставляет возможность задать количество параллельных операций для увеличения пропускной способности передачи данных. По умолчанию библиотека перемещения данных задает количество параллельных операций, равное 8 * числу ядер в компьютере.

Имейте в виду, что многие параллельные операции в среде с низкой пропускной способностью могут перегружать сетевое подключение и фактически предотвращать завершение операций. Этот параметр следует поэкспериментировать, чтобы определить, что лучше всего работает на основе доступной пропускной способности сети.

В этом примере мы добавим код, позволяющий задать количество параллельных операций. Кроме того, мы добавим код, который требуется для завершения передачи.

Добавьте SetNumberOfParallelOperations в метод 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);
}

Измените метод ExecuteChoice, чтобы использовать 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();
    }
}

Измените метод TransferLocalFileToAzureBlob, чтобы использовать таймер.

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);
}

Отслеживание выполнения передачи

Вы можете отслеживать ход передачи во время операции передачи, создав TransferContext объект. Объект TransferContext поставляется в двух формах: SingleTransferContext для передачи отдельных файлов и DirectoryTransferContext для передачи каталогов.

Добавьте методы GetSingleTransferContext и GetDirectoryTransferContext в 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;
}

Измените метод TransferLocalFileToAzureBlob, чтобы использовать 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);
}

Возобновление отмененной передачи

Еще одной функцией, предлагаемой библиотекой перемещения данных, является возможность возобновления отмененной передачи. Затем мы добавим код, позволяющий временно отменить передачу, введя cввод, а затем возобновить передачу через 3 секунды.

Измените метод 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);
}

До сих пор для нашего checkpoint значения задано nullзначение . Теперь, если мы отменим передачу, то получим ее последнюю контрольную точку, а затем используем эту новую контрольную точку в контексте передачи.

Перенос локального каталога в хранилище BLOB-объектов

Библиотека перемещения данных позволяет передавать каталог файлов и все его вложенные каталоги, как показано в следующем примере.

Сначала добавьте метод GetBlobDirectory в 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;
}

Затем измените 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);
}

Существует ряд различий между этим методом и методом для передачи отдельного файла. Сейчас мы используем методы TransferManager.UploadDirectoryAsync и getDirectoryTransferContext, созданные ранее. Кроме того, мы задаем значение options для нашей операции передачи. Это позволяет указать, что в нее нужно включить подкаталоги.

Копирование файла из URL в BLOB-объект

Теперь давайте добавим код, который позволяет скопировать файл по URL-адресу в большой двоичный объект Azure.

Измените 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);
}

Одним из важных вариантов использования этой функции является перемещение данных из другой облачной службы в Azure. Если у вас есть URL-адрес, предоставляющий доступ к ресурсу, вы можете легко переместить этот ресурс в большие двоичные объекты Azure с помощью TransferManager.CopyAsync метода. Этот метод также представляет параметр CopyMethod . В следующей таблице показаны доступные параметры для этого параметра:

Имя участника значение Описание
SyncCopy 0 Скачайте данные из источника в память и отправьте данные из памяти в место назначения. В настоящее время доступно только для копирования из одного служба хранилища Azure ресурса в другой.
ServiceSideAsyncCopy 1 Отправьте запрос на начальное копирование, чтобы служба хранилища Azure, чтобы позволить ему выполнять копирование; следите за выполнением операции копирования до завершения копирования.
ServiceSideSyncCopy 2 Скопируйте содержимое каждого блока с url-адресом put block from URL, добавить блокировку из URL-адреса или поставить страницу из URL-адреса.

Копирование BLOB-объекта

Другая функция, предоставляемая библиотекой перемещения данных, — возможность копирования из одного служба хранилища Azure ресурса в другой.

Измените метод 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);
}

В этом примере мы присваиваем логическому параметру в TransferManager.CopyAsync значение CopyMethod.SyncCopy, чтобы указать, что нам нужно выполнить синхронное копирование. Эта конфигурация означает, что ресурс сначала загружается на локальный компьютер, а затем отправляется в БОЛЬШОЙ двоичный объект Azure. Синхронное копирование — отличный способ обеспечить постоянную скорость копирования. Напротив, скорость асинхронного копирования на стороне сервера зависит от доступной пропускной способности на сервере, которая может меняться. Однако синхронная копия может создать дополнительные затраты исходящего трафика по сравнению с асинхронной копией. Рекомендуется использовать синхронную копию в виртуальной машине Azure, которая находится в том же регионе, что и исходная учетная запись хранения, чтобы избежать затрат на исходящий трафик.

Приложение для перемещения данных завершено. Полный пример кода можно найти на сайте GitHub.

Следующие шаги

Справочная документация по библиотеке перемещения данных службы хранилища Azure.

Совет

Управление ресурсами хранилища BLOB-объектов Azure с помощью Обозревателя службы хранилища Azure Обозреватель службы хранилища Azure — это бесплатное автономное приложение Майкрософт, которое позволяет управлять ресурсами хранилища BLOB-объектов Azure. С помощью Обозревателя службы хранилища Azure вы можете визуализировать, читать, обновлять и удалять контейнеры больших двоичных объектов и сами большие двоичные объекты, а также управлять доступом к ним.