«Существующее соединение было принудительно закрыто удаленным узлом» во время загрузки файла в хранилище BLOB-объектов Azure - PullRequest
0 голосов
/ 13 мая 2019

Я пытаюсь загрузить несколько файлов в хранилище Azure асинхронно, используя Task.WhenAll(tasks);

Однако я продолжаю сталкиваться со следующей ошибкой

Microsoft.WindowsAzure.Storage.StorageException
  HResult=0x80131500
  Message=Error while copying content to a stream.
  Source=Microsoft.WindowsAzure.Storage
  StackTrace:
   at Microsoft.WindowsAzure.Storage.Core.Executor.Executor.<ExecuteAsyncInternal>d__4`1.MoveNext()
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at Microsoft.WindowsAzure.Storage.Blob.CloudBlockBlob.<UploadFromStreamAsyncHelper>d__34.MoveNext()
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at Microsoft.WindowsAzure.Storage.Blob.CloudBlockBlob.<UploadFromStreamAsyncHelper>d__33.MoveNext()
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at RetsIntegration.Services.AzureBlobStorage.<CreateAsync>d__9.MoveNext() 

Inner Exception 1:
HttpRequestException: Error while copying content to a stream.

Inner Exception 2:
IOException: Unable to read data from the transport connection: An existing connection was forcibly closed by the remote host.

Inner Exception 3:
SocketException: An existing connection was forcibly closed by the remote host

Ошибка возникает через пару минут выполнения задач.

Я создаю несколько задач для загрузки изображений, используя следующую логику

public async Task ProcessTasks(IEnumerable<FileObject> files)
{
    List<Task> tasks = new List<Task>();

    foreach (FileObject file in files)
    {
        string path = GetImageFullName(file, file.Filename);

        Task task Storage.CreateAsync(file.Content, path);

        tasks.Add(task);
    }

    // begings the upload to Azure
    await Task.WhenAll(tasks);
}

Вот реализация метода CreateAsync из класса Storage

public async Task CreateAsync(Stream stream, string path)
{
    var azure = GetAzurePath(path);
    // ContainerFactory is IBlobContainerFactory type
    var container = await ContainerFactory.GetAsync();

    CloudBlockBlob blockBlob = container.GetBlockBlobReference(azure);

    await blockBlob.UploadFromStreamAsync(stream);
}

Вот как я создаю контейнеры Blob. Обратите внимание, что при создании контейнера я увеличиваю время ожидания сервера до 4 часов, что должно быть достаточно для завершения загрузки.

public class DefaultBlobContainerFactory : IBlobContainerFactory
{
    private readonly CloudBlobContainer _container;

    public DefaultBlobContainerFactory(AzureBlobOptions azureBlobOptions)
    {
        try
        {
            CloudBlobClient blobClient = GetClient(azureBlobOptions);
            _container = blobClient.GetContainerReference(azureBlobOptions.DocumentContainer);
        }
        catch (StorageException)
        {
            throw;
        }
    }

    protected virtual CloudBlobClient GetClient(AzureBlobOptions azureBlobOptions)
    {
        if (azureBlobOptions.ConnectionString != null && CloudStorageAccount.TryParse(azureBlobOptions.ConnectionString, out CloudStorageAccount cloudStorageAccount))
        {
            return cloudStorageAccount.CreateCloudBlobClient();
        }

        if (azureBlobOptions.BaseUri != null && azureBlobOptions.Token != null)
        {
            return new CloudBlobClient(azureBlobOptions.BaseUri, new StorageCredentials(azureBlobOptions.Token));
        }

        throw new ArgumentException("One of the following must be set: 'ConnectionString' or 'BaseUri'+'Token'!");
    }

    public async Task<CloudBlobContainer> GetAsync()
    {
        await _container.CreateIfNotExistsAsync(new BlobRequestOptions()
        {
            ServerTimeout = TimeSpan.FromHours(4),
        }, null);

        return _container;
    }
}

Что может быть причиной этой проблемы? Как я могу это исправить?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...