【问题标题】:Best way to Architect Azure Worker Role to Process Data from ~10 Queues构建 Azure Worker Role 以处理来自约 10 个队列的数据的最佳方法
【发布时间】:2011-05-04 07:49:13
【问题描述】:

我有一个工作角色,将数据放入大约 10 个需要处理的队列中。有很多数据 - 可能每秒大约 10-100 条消息在各种队列中排队。

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

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

但是,我发现部署的 CPU 利用率很高。几乎始终处于或接近 100%。

我想知道这是否是因为线程饥饿?还是因为访问队列是 RESTful 并且线程最终通过建立连接和减慢速度而相互阻塞?或者,是因为我使用:

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

执行得太快了?

消息的每次处理也会将其保存到 Azure 表存储或数据库 - 因此可能是保存此数据的过程会占用 CPU。

实际上,调试高 CPU 负载非常困难。所以,我的问题是:我是否可以进行一般的架构更改来帮助缓解+防止任何可能存在的问题? (例如,使用不同类型的轮询而不是使用 while(true) - 尽管我认为该示例最终是相同的)。

也许简单地使用 new Thread() 生成新线程并不是最好的方法。

【问题讨论】:

    标签: c# azure architecture azure-storage


    【解决方案1】:

    我建议在您的循环中添加一个 sleep 语句...这种紧密的循环不仅可能会占用 CPU 资源,而且您还需要为存储交易付费。每检查一万次队列,就要花一分钱。这是一个很小的成本,但随着时间的推移,它可能会变得很重要。

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

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

    换句话说,串行而不是并行轮询队列(这应该完全是一个词)。这样,您实际上一次只一件事(如果您的任务是 CPU 密集型的,这很有用),但您仍在检查每个循环中的所有队列。

    【讨论】:

    • 缺少 sleep 语句肯定会导致 CPU 利用率问题。
    • 您可能还希望分批(共 32 条)获取消息。它会更高效、更便宜。
    • 如何获取批量消息?
    • 嗯,在 thread.sleep 为 100 毫秒的情况下,我们落后了超过一百万条消息。我会修改它以找到最佳的 thread.sleep 时间。
    • 调用 q.GetMessages(32) 一次获取 32 条消息。 (IIRC,最大值为 32)
    【解决方案2】:

    CPU 也有同样的问题。这可能是由于 Azure 队列的本地实现效率低下造成的。

    最后我添加了指数睡眠策略(用于实现 - 查看Lokad.CQRS for Azure 项目),其中队列被频繁轮询,但如果其中任何一个都没有消息,我们逐渐开始增加睡眠间隔直到它达到某个上限。如果发现消息 - 我们会立即取消间隔。

    这种方式在整个系统上不会浪费存储事务(和本地开发 CPU),但在多条消息连续出现时保持极快的响应。

    【讨论】:

      【解决方案3】:

      我认为您的问题来自循环实现。轮询必须通过诸如 sleep() 之类的东西来减慢。否则,没有什么能阻止循环消耗 100% CPU Core(这实际上是正常行为)。

      【讨论】:

        【解决方案4】:

        查看 Brian Hitney 的 Scaling Down Azure Roles 视频。基本方法是产生一些线程,每个线程都有一个“worker”,然后监视给定的队列并采取适当的行动。特别是这样可以防止一个队列阻塞其他队列....

        【讨论】:

        【解决方案5】:

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

        MSDN - Best Practices for Maximizing Scalability and Cost Effectiveness of Queue-Based Messaging Solutions on Windows Azure

        它谈到了在有工作要做时添加线程和实例 - 并在没有工作时退出,这样您就不会连续和不必要地从多个线程和实例轮询队列,增加交易成本并将 CPU 变成CPU 利用率恒定为 100% 的加热器。

        【讨论】:

          猜你喜欢
          • 2015-04-15
          • 1970-01-01
          • 1970-01-01
          • 2011-11-19
          • 1970-01-01
          • 1970-01-01
          • 2015-03-17
          • 1970-01-01
          • 2019-08-16
          相关资源
          最近更新 更多