2

背景:文件上传

我的场景:我需要将大量文件上传到 Azure blob,可能是 10,000 到 100,000 个文件。每个文件大小为 10KB-50KB。

我在上面讨论中使用了解决方案,我看到文件快速上传,但是,我有这么多文件,以至于我发现我的应用程序导致 CPU 使用率非常高,总是 100% ......更糟糕的是下一步我需要运行数百个进程,我的意思是我需要运行数百个进程,每个进程需要上传10,000个或更多文件。到目前为止,我已经对其进行了测试,但不幸的是,我看到了许多奇怪的问题,例如异常“连接已关闭”等...

你们有减少任务CPU使用率的想法吗?

4

3 回答 3

0

我在这里看到的问题是,您旋转了如此多的线程,以至于您只需管理所有排队的线程,即使从技术上讲它们不会尝试同时运行,您也会使机器资源过载。他们将占用 RAM,并且在没有 RAM 的情况下,将使用 SWAP 空间——这将使机器在非荣耀的火焰中崩溃。

我会使用一个队列(天蓝色队列,msmq,Systems.Collections.Queue)来排队所有对象,使用有限数量的线程,这些线程将使用后台链接中描述的异步方法处理文件,然后线程完成执行检查队列中的下一项并处理该项。我的建议是使用非内存队列——我将在下面解释。主要好处是节省内存,这样您的软件就不会因为队列太大而崩溃或变慢。

Parallel.ForEach 等可以节省大量时间,但在处理大量项目时确实会破坏机器的性能 - 如果机器出现故障,那么除非您在某处有检查点,否则您将无法从中恢复。使用持久队列不仅可以让您正确管理机器资源,还可以正确管理您在流程中的位置。

然后,您可以使用 MSMQ 之类的持久队列或如果在云中使用 Azure 队列,在多台机器上进行扩展。如果您使用检查 azure 队列有多大的服务,您甚至可以不时启动实例以减少负载,然后终止额外的实例。

这是我要实现的场景:

使用标准 ThreadPool 大小 当您检测到新文件/批处理时 - 提交到队列 每次在队列中插入新项目时触发事件(如果是内存队列) 让进程检查队列(如果是持久队列) 如果新项目在队列中,首先检查 ThreadPool 中是否有空间 如果没有则忽略(使用 PEEK 方法,因此您不会删除该项目) - 如果有空间,则将工作线程添加到 ThreadPool 进程线程(在 ThreadPool 下运行)应该执行,然后检查队列中是否有另一个项目 - 如果没有 - 线程死亡,这很好

使用这种方法,您可以在 1 台机器或 50,000 台机器上运行它——只要您为超过 1 台机器使用持久队列,您就不会遇到任何问题。当然,如果您使用 Azure 队列,请确保您对重复项目进行了正确的测试,因为您可能会收到已被提供给另一台计算机的排队项目。

这是一种简单的方法,可扩展,并且如果使用持久队列(甚至是文件系统)可以从故障中恢复。但是,它不会通过强制它管理包含 100 万个以上项目的 ThreadPool 来滥用资源来使机器过载。

希望这可以帮助

于 2012-10-12T20:24:26.957 回答
0

简单地说,去实现一个线程池,让有 20 个线程(因为这可能是你的网络带宽可以同时处理的数量),每次上传需要 2-3 秒,大约需要 4-5 小时,这是可以接受的。确保您没有在上传之间共享存储或容器实例,这可能会导致“连接已关闭”错误。

于 2012-10-12T20:31:52.787 回答
0

我是 Microsoft 技术布道者,我开发了一个示例和免费工具(不支持/不保证)来帮助解决这些情况。

二进制文件和源代码可在此处获得:https ://blobtransferutility.codeplex.com/

Blob 传输实用程序是一个 GUI 工具,用于向/从 Windows Azure Blob 存储上传和下载数千个小/大文件。

特征:

  • 创建要上传/下载的批次
  • 设置内容类型
  • 并行传输文件
  • 将大文件拆分为并行传输的较小部分

第一个和第三个功能是您问题的答案。

您可以从示例代码中了解我是如何做到的,或者您可以简单地运行该工具并做您需要做的事情。

于 2013-03-12T08:00:22.300 回答