批量上载大量图像到Azure Blob存储

我有大约110,000张各种格式的图像(jpg,png和gif)和大小(2-40KB)本地存储在我的硬盘上。 我需要将它们上传到Azure Blob存储。 在执行此操作时,我需要设置一些元数据和blob的ContentType,否则它是直接批量上传。

我目前正在使用以下内容来处理一次上传一个图像(并行超过5-10个并发任务)。

static void UploadPhoto(Image pic, string filename, ImageFormat format) { //convert image to bytes using(MemoryStream ms = new MemoryStream()) { pic.Save(ms, format); ms.Position = 0; //create the blob, set metadata and properties var blob = container.GetBlobReference(filename); blob.Metadata["Filename"] = filename; blob.Properties.ContentType = MimeHandler.GetContentType(Path.GetExtension(filename)); //upload! blob.UploadFromStream(ms); blob.SetMetadata(); blob.SetProperties(); } } 

我想知道是否还有其他技术可以用来处理上传,以尽可能快地完成。 此特定项目涉及将大量数据从一个系统导入另一个系统,并且出于客户原因,它需要尽快发生。

好的,这就是我做的。 我在一个异步链中运行BeginUploadFromStream(),然后是BeginSetMetadata(),然后是BeginSetProperties(),并行超过5-10个线程(ElvisLive和knightpfhor的建议的组合)。 这有效,但是超过5个线程的任何东西都有可怕的性能,每个线程需要花费20秒(一次只能处理10个图像的页面)才能完成。

那么,总结性能差异:

  • 异步:5个线程,每个线程运行一个异步链,每个线程一次处理十个图像(出于统计原因分页): ~15.8秒(每个线程)。
  • 同步:1个线程,一次10个图像(由于统计原因分页): ~3.4秒

好的,这很有意思。 同步上传blob的一个实例比另一个方法中的每个线程执行好5倍。 因此, 即使运行5个线程的最佳异步平衡也能实现相同的性能

因此,我调整了我的图像文件导入,将图像分成每个包含10,000张图像的文件夹。 然后我使用Process.Start()为每个文件夹启动我的blob上传器的实例。 我在此批次中有170,000个图像可供使用,因此这意味着上传者的17个实例。 当我在笔记本电脑上运行所有这些时,所有这些设备的性能均达到每组约4.3秒

简而言之,我只是为每10,000张图像运行一个blob上传器实例,而不是试图让线程最佳地工作,而是同时在一台机器上运行。 总体性能提升?

  • Async Attempts: 14-16小时 ,基于运行一两个小时的平均执行时间。
  • 与17个独立实例同步:约1小时5分钟。

你绝对应该在几个流中并行上传(即同时发布多个文件),但在你做任何实验(错误地)显示没有好处之前,请确保你实际增加了ServicePointManager.DefaultConnectionLimit的值:

ServicePoint对象允许的最大并发连接数。 默认值为2。

使用默认值2,对于任何目标,最多可以有两个未完成的HTTP请求。

由于您上传的文件非常小,我认为您编写的代码可能与您可以获得的效率相当。 根据您的评论,您似乎已经尝试并行运行这些上传,这实际上是我唯一的其他代码建议。

我怀疑为了获得最大的吞吐量,将为您的硬件,连接和文件大小找到合适的线程数。 您可以尝试使用Azure吞吐量分析器来更轻松地找到此平衡。

微软的Extreme Computing小组也提出了提高吞吐量的基准和建议 。 它专注于部署在Azure上的工作者角色的吞吐量,但它会让您了解您可能希望的最佳效果。

您可能希望增加ParallelOperationThreadCount,如下所示。 我没有检查最新的SDK,但在1.3中,限制为64.未设置此值会导致较低的并发操作。

 CloudBlobClient blobStorage = new CloudBlobClient(config.AccountUrl, creds); // todo: set this in blob extensions blobStorage.ParallelOperationThreadCount = 64 

如果并行方法上传的内容比串行方法多5倍,那么你也可以

  • 有可怕的带宽
  • 有一台很慢的电脑
  • 做错了

即使我不使用内存流也不使用任何其他漂亮的东西,我的命令行util在并行运行时得到了相当大的提升,我只是生成文件名的字符串数组,然后使用Parallel.ForEach上传它们。

此外, Properties.ContentType调用可能会让您回头很多。 就个人而言,我从不使用它们,我想它们甚至不应该重要,除非您想通过直接URL在浏览器中查看它们。

您可以随时尝试上传的异步方法。

 public override IAsyncResult BeginUploadFromStream ( Stream source, AsyncCallback callback, Object state 

http://msdn.microsoft.com/en-us/library/windowsazure/ee772907.aspx