Azure 如何在现实世界中读取多个队列?

Azure 如何在现实世界中读取多个队列?,azure,message-queue,azure-storage-queues,azure-servicebus-queues,Azure,Message Queue,Azure Storage Queues,Azure Servicebus Queues,这里有一个理论问题: 当我使用消息队列构建应用程序时,我需要多个队列支持用于不同目的的不同数据类型。假设我有20个队列(例如,一个用于创建新用户,一个用于处理新订单,一个用于编辑用户设置等) 我将使用“最少”1个web角色和1个工作者角色将此部署到Windows Azure 如何以正确的方式读取所有这20个队列?这是我的想法,但我在这方面几乎没有实际经验: 创建一个在辅助角色“main”类中生成20个线程的类。让这些线程中的每一个都执行一个方法来轮询不同的队列,并让所有这些线程在每次轮询之间休眠

这里有一个理论问题:

当我使用消息队列构建应用程序时,我需要多个队列支持用于不同目的的不同数据类型。假设我有20个队列(例如,一个用于创建新用户,一个用于处理新订单,一个用于编辑用户设置等)

我将使用“最少”1个web角色和1个工作者角色将此部署到Windows Azure

如何以正确的方式读取所有这20个队列?这是我的想法,但我在这方面几乎没有实际经验:

创建一个在辅助角色“main”类中生成20个线程的类。让这些线程中的每一个都执行一个方法来轮询不同的队列,并让所有这些线程在每次轮询之间休眠(当然,使用一种增加休眠时间的退避机制)

这导致有20个线程(或21?)和20个正在被主动轮询的队列,导致大量消息被浪费(每次轮询一个空队列时,它将作为消息计费)


如何解决这个问题?

< P>如果存储队列上的退避机制对你来说不够,我建议你考虑服务总线队列。使用服务总线队列,您不必进行如此激进的轮询

您仍然需要实现轮询队列的循环,但接收超时使其比使用存储队列时的持续轮询机制更轻松

在下面的示例中,我尝试从队列接收消息。如果未找到任何消息,它将保持连接打开30秒,以查看是否有新消息。如果30秒后没有消息到达,Receive方法将返回null(我将有一个循环试图再次调用Receive)。请注意,最大超时时间为24天

MessagingFactory factory = MessagingFactory.Create(ServiceBusEnvironment.CreateServiceUri("sb", ServiceNamespace, string.Empty), credentials); 
QueueClient myQueueClient = factory.CreateQueueClient("TestQueue");
myQueueClient.Receive(new TimeSpan(hours: 0, minutes: 0, seconds: 30));

为要读取的每个队列弹出线程是一个好主意,但是看到CLR线程池的容量限制,您还应该考虑异步接收消息(例如使用<强> TaskFutual.FromAsync < /强>):

另一种策略是使用单个或更少的队列,这样队列可以支持多种类型的消息。如果您的系统架构能够支持此方法,则此方法更易于管理且成本更低

在现实世界中,我成功地使用了多个队列(出于可伸缩性的目的),每个队列都在由计时器事件触发的单独线程上读取。根据队列上的负载和应用程序的需要,计时器事件被更改为以动态变化的间隔为队列提供服务。

我阅读了其他答案(非常好的答案),并想对此发表自己的见解

坚持使用Windows Azure队列,正如@Lucifure所描述的:我真的不认为需要多个队列,除了两种情况:

  • 你需要不同的优先级。您最不希望看到的是一条高优先级消息被数百条低优先级消息所阻塞。为这些创建hi pri队列
  • 消息读取+删除的数量将超过每秒500个事务的目标。在这种情况下,创建多个队列,将事务量分散到各个存储分区(一个存储帐户每秒将处理超过5K个事务)
如果您坚持使用单个队列(基于存储,而不是服务总线),则可以一次读取消息块(最多32个)。您可以轻松制定一种格式,帮助您区分消息类型(可能有一个简单的前缀)。然后,将消息传递给适当的线程进行处理。服务总线队列没有多消息读取,尽管它们允许预取(这会导致缓冲消息下载到缓存中)

一个队列优于多个队列的优点:您可以消除(或大大减少)“许多队列没有消息,导致空读取”的问题

如果需要更高的吞吐量,您可以随时增加执行队列读取和调度的线程数

记住,每次删除都是原子的;没有配料。至于队列轮询:您考虑退避是正确的。您不需要在成功读取消息(或消息块)后退出。当你尝试阅读后什么也看不到时,就退后一步


与服务总线队列相比有一个很好的优势:WindowsAzure队列为您提供了一个大致的消息计数(这在考虑扩展到多个实例时非常有用)。服务总线队列不提供这一点。

我的问题不是关于退避机制,而是关于“从多个队列读取”部分。您是否有一个示例,说明如何使用fromsync实现这一点?如果我们有200个队列而不是20个呢?如何在不创建太多线程的情况下解决这个问题?我现在看到,我对您的示例看得不够好,我以为它只是关于TPL的,但它是关于Azure的。现在阅读:)您在队列中放入了什么类型的数据(即,如果您将所有不同类型混合在一起,您的工作人员如何知道它将从队列中取出什么类型的数据)?如果您使用服务总线队列,则您正在处理代理消息。此BrokeredMessage对象有一个名为Properties的属性,您可以向其中添加接收消息时可以使用的自定义信息。基本上使用自描述消息。。。我使用了一个封装实际消息对象的信封类,类似于类信封。信封包含实际的消息对象及其类型名,并被序列化为XML并放入队列中。读取时,解析XML以获取类型名称,然后反序列化为实际消息并发送到消息处理程序。可以使用更复杂但更简单的方法。Sandrino关于在服务总线队列中使用代理消息的评论也是一个非常可行的策略。但是您如何知道