背景:File upload
我的方案:我需要将大量文件上传到Azure blob,它可能是10,000到100,000个文件。 每个文件大小为10KB-50KB。
我在上面的讨论中使用了解决方案,我看到文件快速上传,但是,我有这么多文件,所以我发现我的应用程序导致CPU使用率非常高,总是100%...更糟糕的是下一步我需要运行数百个进程,我的意思是我需要运行数百个进程,每个进程需要上传10,000个或更多文件。我已经测试过它,直到现在,我没有看到很多奇怪的问题,例如异常“连接关闭”等......
你们有没有想法减少任务的CPU使用率......
答案 0 :(得分:0)
我看到的问题是你旋转了这么多线程,你只需要管理所有排队的线程,即使在技术上他们不会同时尝试运行所有线程,你也会在资源方面超载机器。它们将占用RAM并且在没有RAM的情况下,将使用SWAP空间 - 这将使机器陷入非荣耀的火焰中。
我会使用队列(azure queue,msmq,Systems.Collections.Queue)来排队所有对象,使用有限数量的线程来处理文件,使用后台链接中描述的异步方法然后线程完成检查队列中的下一个项目并处理该项目。我的建议是使用非内存队列 - 我将在下面解释。主要的好处是保存ram,这样你的软件就不会因为队列太大而崩溃或变慢。
Parallel.ForEach等节省了很多时间,但是当你处理很多物品时,它真的会破坏你机器的性能 - 如果机器发生故障,那么除非你在某处有一个检查点,否则你无法从中恢复。使用持久队列不仅可以正确管理机器资源,还可以正确管理过程中的位置。
然后,您可以使用像MSMQ这样的持久性队列,或者在云中使用Azure队列,在多台计算机上进行扩展。如果您使用检查azure队列大小的服务,您甚至可以不时调出实例来减少负载,然后终止额外的实例。
这是我要实施的方案:
使用标准的ThreadPool大小 当您检测到新文件/批处理时 - 提交到队列 每次在队列中插入新项目时都会触发事件(如果是内存队列) 让进程检查队列(如果是持久队列) 如果队列中有新项,请首先检查ThreadPool中是否有空格忽略(如果没有删除项,则使用PEEK方法) - 如果有空格,则将工作线添加到ThreadPool 进程线程(在ThreadPool下运行)应该执行,然后检查队列中是否有另一个项目 - 如果没有 - 线程死了,这很好
使用此方法,您可以使用1台计算机或50,000计算机运行此程序 - 如果您使用超过1台计算机的持久队列,则不会出现任何问题。当然,如果您正在使用Azure队列,请确保您正确地测试重复项目,因为您可以将一个排队的项目交给另一台机器。
这是一种简单的方法,可扩展,如果使用持久性队列(甚至是文件系统)可以从故障中恢复。但是,通过强制它管理包含100万个项目的ThreadPool,滥用资源不会使机器过载。
希望这有帮助
答案 1 :(得分:0)
简单地说,去一个线程池实现,让20个线程(因为这可能是你的网络带宽可以同时处理的),每次上传需要2-3秒,这将需要4左右5个小时,这是可以接受的。确保在上载之间不共享存储或容器实例,这可能导致“连接已关闭”错误。
答案 2 :(得分:0)
我是微软技术推广人员,我开发了一个示例和免费工具(无支持/不保证)来帮助解决这些问题。
二进制文件和源代码可在此处获取:https://blobtransferutility.codeplex.com/
Blob Transfer Utility是一个GUI工具,用于向/从Windows Azure Blob存储上载和下载数千个小/大文件。
功能强>
第一和第三个功能是您的问题的答案。
您可以从示例代码中了解我是如何做到的,或者您只需运行该工具并执行您需要执行的操作。