【问题标题】:Upload blocks in parallel in blob storage在 blob 存储中并行上传块
【发布时间】:2023-01-25 03:33:53
【问题描述】:

我正在尝试将其转换为并行以缩短文件的上传时间,但根据我的尝试,它并没有及时发生很大变化。 我想并排上传块,然后确认它们。我怎么能设法并行进行呢?

public static async Task UploadInBlocks
    (BlobContainerClient blobContainerClient, string localFilePath, int blockSize)
{
    string fileName = Path.GetFileName(localFilePath);
    BlockBlobClient blobClient = blobContainerClient.GetBlockBlobClient(fileName);

    FileStream fileStream = File.OpenRead(localFilePath);

    ArrayList blockIDArrayList = new ArrayList();

    byte[] buffer;

    var bytesLeft = (fileStream.Length - fileStream.Position);

    while (bytesLeft > 0)
    {
        if (bytesLeft >= blockSize)
        {
            buffer = new byte[blockSize];
            await fileStream.ReadAsync(buffer, 0, blockSize);
        }
        else
        {
            buffer = new byte[bytesLeft];
            await fileStream.ReadAsync(buffer, 0, Convert.ToInt32(bytesLeft));
            bytesLeft = (fileStream.Length - fileStream.Position);
        }

        using (var stream = new MemoryStream(buffer))
        {
            string blockID = Convert.ToBase64String
                (Encoding.UTF8.GetBytes(Guid.NewGuid().ToString()));
            
            blockIDArrayList.Add(blockID);


            await blobClient.StageBlockAsync(blockID, stream);
        }

        bytesLeft = (fileStream.Length - fileStream.Position);

    }

    string[] blockIDArray = (string[])blockIDArrayList.ToArray(typeof(string));

    await blobClient.CommitBlockListAsync(blockIDArray);
}

【问题讨论】:

  • “我正在尝试将其转换为并行以缩短文件的上传时间”-它不会:上传受网络 IO 限制,但并行化只对受 CPU 限制的活动有利。由于并发网络连接和传输的开销,您更有可能以这种方式减慢速度。
  • 您的 while 循环运行缓慢:您在循环内分配大缓冲区:不要那样做- 我认为您的代码也不正确,因为您没有检查fileStream.ReadAsync 的返回值。你不应该在循环中做new MemoryStream——也不应该做像Convert.ToBase64String (Encoding.UTF8.GetBytes(Guid.NewGuid().ToString())这样令人费解的事情——因为Guid.ToString()返回已经是URI安全的Base16数字,所以带有UTF8字节和Base64编码的rigmaore只是去混淆视听,没有任何好处。
  • 此外,您的整个代码是...重新发明轮子:GetBlockBlobClient 已经可以非常有效地直接上传 FileStream - 哦,您的代码中还有另一个错误:FileStream 不是真正的异步除非你使用 isAsync ctor。还有另一个错误:var bytesLeft = (fileStream.Length - fileStream.Position); 将始终只是 fileStream.Length 开始 - 如果您尝试使用大于 2GB 的文件,Convert.ToInt32(bytesLeft) 将失败。

标签: c# azure azure-blob-storage parallel.foreach


【解决方案1】:

当然。你不应该期待任何改进 - 恰恰相反。 Blob 存储没有任何简单的吞吐量限制,这将受益于在多个流中上传,并且您已经在执行极轻量级的 I/O,这将完全受 I/O 限制。

好的 I/O 代码绝对不会从并行化中获益。无论您投入多少工人,管道都只是这个thick 并且不允许您传递更多数据。

你所有的代码只是重新实现了 blob 存储库已经非常有效的机制......你做得更糟,毫无意义的分配,错误的参数和新的错误机会。不要那样做。该库可以很好地处理流。

【讨论】:

  • 然而,这也有例外——虽然当管道已经饱和时显然并发不会有帮助,但对 Azure Blob 存储 blob 枚举等事物有多个并发请求肯定要快得多,因为客户端的大部分时间是花费在等待 Azure 返回响应上——事情在它们的末端是负载平衡的(但在客户端,如果你知道如何正确地做,这些并发请求都可以使用单个线程进行)。
猜你喜欢
  • 2020-08-12
  • 1970-01-01
  • 2014-08-16
  • 2016-10-27
  • 1970-01-01
  • 2017-12-14
  • 1970-01-01
  • 2015-11-30
  • 2019-04-06
相关资源
最近更新 更多