我有大约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();
}
}
我想知道是否还有其他技术可以用来处理上传,尽可能快地进行上传。这个特殊的项目涉及将大量数据从一个系统导入另一个系统,以及出于客户原因,它需要尽快发生。
答案 0 :(得分:7)
好的,这就是我的所作所为。我在一个异步链中运行BeginUploadFromStream(),然后是BeginSetMetadata(),然后是BeginSetProperties(),并行超过5-10个线程(ElvisLive和knightpfhor的建议的组合)。这种方法很有效,但是超过5个线程的表现都非常糟糕,每个线程需要花费20秒钟(一次只能处理10个图像)。
所以,总结性能差异:
好的,这很有意思。同步上传blob的一个实例比另一个方法中的每个线程执行好5倍。所以,即使运行5个线程的最佳异步平衡也能实现基本相同的性能。
因此,我调整了我的图像文件导入,将图像分成每个包含10,000张图像的文件夹。然后我使用Process.Start()为每个文件夹启动我的blob上传器的实例。我在此批次中有170,000个图像可供使用,因此这意味着上传者的17个实例。在我的笔记本电脑上运行所有这些功能时,所有这些功能的性能均达到 ~4.3秒每套。
长话短说,我只是为每10,000张图片运行一个blob上传器实例,而不是试图让线程最佳地工作,而是同时在一台机器上运行。总体性能提升?
答案 1 :(得分:3)
你绝对应该在多个流中并行上传(即同时发布多个文件),但在你做任何实验(错误地)显示没有好处之前,请确保你实际增加ServicePointManager.DefaultConnectionLimit
的值:
ServicePoint允许的最大并发连接数 宾语。默认值为2.
默认值为2时,对于任何目标,最多可以有两个未完成的HTTP请求。
答案 2 :(得分:1)
由于您上传的文件非常小,我认为您编写的代码可能与您可以获得的效率相当。根据您的评论,您似乎已经尝试并行运行这些上传,这实际上是我唯一的其他代码建议。
我怀疑为了获得最大的吞吐量,将为您的硬件,连接和文件大小找到合适的线程数。您可以尝试使用Azure Throughput Analyzer来更轻松地找到这种平衡。
微软的Extreme Computing小组也benchmarks and suggestions on improving throughput。它专注于部署在Azure上的工作者角色的吞吐量,但它会让您了解您希望的最佳效果。
答案 3 :(得分:1)
您可能希望增加ParallelOperationThreadCount,如下所示。我没有检查最新的SDK,但在1.3中限制为64.未设置此值会导致较低的并发操作。
CloudBlobClient blobStorage = new CloudBlobClient(config.AccountUrl, creds);
// todo: set this in blob extensions
blobStorage.ParallelOperationThreadCount = 64
答案 4 :(得分:1)
如果并行方法上传的内容比串行方法多5倍,那么你要么
我的命令行util在并行运行时获得了相当大的提升,即使我不使用内存流也没有任何其他漂亮的东西,我只是生成文件名的字符串数组,然后用{{1上传它们}}
此外,Parallel.ForEach
调用可能会让您回头相当多。我个人从不使用它们,我想它们甚至不应该重要,除非你想通过直接的URL在浏览器中查看它们。
答案 5 :(得分:0)
您可以随时尝试上传的异步方法。
public override IAsyncResult BeginUploadFromStream (
Stream source,
AsyncCallback callback,
Object state
)
http://msdn.microsoft.com/en-us/library/windowsazure/ee772907.aspx