我有一个工人角色将数据投入大约10个队列中,需要处理。有很多数据 - 大概每秒钟大约10-100条消息,以各种排队排队。

队列保存不同的数据并分别处理它们。特别是一个非常活跃的单一队列。

我现在设置它的方式,我是一个单独的工作角色,催生了10个不同的线程,每个线程都执行一个具有一段时间(true){从队列中获取消息的方法}。每当队列中的数据得到备份时,我们只是启动更多此类过程,以帮助加快队列的数据处理。另外,由于一个队列更有活跃,因此我实际上启动了许多指向相同方法的线程来处理该队列的数据。

但是,我看到部署的CPU利用率很高。几乎不断或接近100%。

我想知道这是否是由于线程饥饿?还是因为访问队列是宁静的,并且线程最终通过连接并放慢速度而彼此阻止彼此?还是因为我使用:

while(true)
{
   var message = get message from queue;
   if(message != null)
   {
       //process message
   }
}

而且执行得太快了吗?

消息的每次处理也将其保存到Azure表存储或DB中 - 因此,可以保存该数据的过程使CPU吞噬了CPU。

实际上,很难调试高CPU负载。因此,我的问题是:我能做的一般体系结构更改是否有助于减轻 +防止可能存在的任何可能的问题? (例如,不使用不同类型的轮询使用时(true) - 尽管我认为最终在该示例中是相同的)。

也许简单地使用新线程()产卵新线程并不是最好的选择。

有帮助吗?

解决方案

我建议在您的循环中放一个睡眠声明……不仅循环可能会抓住CPU资源,而且还需要支付存储交易费用。每一千次检查队列,就花费一分钱。这是一个很小的成本,但随着时间的流逝,它可能会加起来。

我也经常使用这样的代码:

while(true) { var msg = q1.GetMessage(); if (msg != null) { ... } msg = q2.GetMessage(); if (msg != null) { ... } }

换句话说,将排队串行而不是偏见进行轮询(这应该是一个单词)。这样你实际上只是 正在做 一次一件事(如果您的任务是CPU为中性的,则有用),但是您仍在检查每个循环中的所有队列。

其他提示

CPU也有同样的问题。这可能是由于非效率的局部实施而引起的。

最后,我添加了指数睡眠政策(用于实施 - 在 lokad.cqrs for Azure 项目),在队列经常进行轮询的情况下,但是如果这两个消息都没有消息,我们逐渐开始增加睡眠间隔,直到达到某个上限为止。如果发现消息 - 我们立即删除间隔。

这样,整体系统不会浪费存储交易(和本地开发CPU),但是如果多个消息连续出现,请保持极高的响应。

查看 缩放天蓝色角色 布莱恩·希特尼(Brian Hitney)的视频。基本的方法是产生一些线程,每个线程都与“工人”相比监视给定的队列并适当起作用。特别是这使一个队列无法阻止其他队列。

我认为您的问题来自循环实施。必须像睡眠()之类的东西放慢投票。否则,没有什么可以阻止循环消耗100%CPU核心(实际上这是正常行为)。

有一篇很棒的MSDN文章涵盖了所有这些

MSDN-最大化基于队列的消息解决方案在Windows Azure上的可扩展性和成本效益的最佳实践

它谈到了添加工作要做的添加线程和实例 - 并在没有工作时退缩,因此您不会从mutliple线程和实例中连续且不必要地进行轮询队列,从而增加了交易成本,并将CPU变成加热器常数100%CPU利用率。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top