我有一个工作者角色,负责将数据抛入大约10个需要处理的队列中。有大量的数据-可能每秒大约有10-100条消息在不同的队列中排队。
队列保存不同的数据,并分别处理它们。特别是有一个非常活跃的队列。
按照我现在设置的方式,我有一个单独的工作者角色,它产生10个不同的线程,每个线程执行一个方法,该方法有一个while(true){get message from queue and process it}。每当备份队列中的数据时,我们只需启动更多这样的进程,以帮助加快队列中数据的处理速度。另外,因为有一个队列比较活跃,所以我实际上启动了许多指向同一方法的线程来处理该队列中的数据。
但是,我发现部署的CPU利用率很高。几乎一直保持在100%或接近100%。
我想知道这是不是因为线程匮乏?或者是因为访问队列是RESTful的,并且线程通过进行连接和减慢速度而最终阻塞彼此?或者,是因为我使用:
while(true)
{
var message = get message from queue;
if(message != null)
{
//process message
}
}
而且执行得太快了?
消息的每一次处理都会将其保存到Azure表存储或数据库中-因此,可能是保存此数据的过程占用了CPU。
实际上,调试高CPU负载真的很难。所以,我的问题是:我是否可以进行一般性的架构更改,以帮助缓解或防止可能存在的任何问题?(例如,不是使用while(true),而是使用不同类型的轮询-尽管我可以想象在这个示例的结尾是相同的)。
也许简单地使用new Thread()产生新的线程并不是最好的方法。
发布于 2010-11-03 14:28:57
我建议在你的循环中放一个睡眠语句...这个紧凑的循环不仅可能会占用CPU资源,而且还会为存储事务付费。每检查一万次队列,它就会花费一分钱。这是一个很小的成本,但随着时间的推移,它可能会变得非常重要。
我也经常使用这样的代码:
while(true) { var msg = q1.GetMessage(); if (msg != null) { ... } msg = q2.GetMessage(); if (msg != null) { ... } }
换句话说,串行地而不是并行地轮询队列(这完全应该是一个单词)。这样一来,您实际上一次只做了一件事(如果您的任务是CPU相关的,则很有用),但是您仍然要检查每个循环中的所有队列。
发布于 2010-11-03 14:33:35
CPU也有同样的问题。这可能是由Azure队列的低效本地实现引起的。
最后,我添加了指数休眠策略(用于实现-在Lokad.CQRS for Azure项目中查看),其中队列被频繁轮询,但如果其中任何一个都没有消息,我们就会逐渐增加休眠间隔,直到它达到某个上限。如果消息被发现,我们立即丢弃间隔。
通过这种方式,系统总体上不会浪费存储事务(和本地开发CPU),但如果连续收到多个消息,则会保持极高的响应速度。
发布于 2010-11-04 20:38:16
看看布赖恩·希特尼的Scaling Down Azure Roles视频。基本的方法是产生一定数量的线程,每个线程都有一个"worker“,它监视给定的队列并适当地执行操作。特别是,这可以防止一个队列阻塞其他队列。
https://stackoverflow.com/questions/4084499
复制相似问题