Azure存储队列 - 将响应与请求相关联

时间:2012-02-16 21:20:21

标签: azure queue message-queue azure-storage

当Web角色将消息放入存储队列时,如何轮询特定的相关响应?我希望后端的Worker Role将消息放到响应队列中,目的是让调用者选择响应并从那里开始。

我们的目的是利用Queue将一些繁重的处理卸载到后端的Worker Roles上,以确保Web角色的高性能。但是,在后端Worker完成并做出响应之前,我们不希望响应HTTP请求。

6 个答案:

答案 0 :(得分:4)

我实际上正在做出类似的决定。在我的情况下,我有一个在Web角色中运行的WCF服务,该服务应该将计算卸载到工作者角色。计算结果后,Web角色将向客户端返回答案。

我的基本数据结构知识告诉我,我应该避免使用以非队列方式设计为队列的东西。这意味着队列应始终以类似FIFO的方式进行服务。因此,基本上如果对请求和响应使用队列,等待将数据返回给客户端的线程将必须等待,直到计算消息位于响应队列的“顶部”,这不是最佳的。如果使用Azure表存储响应,则线程会轮询消息,从而产生不必要的开销

我相信这个问题的一个可能的解决方案是使用队列来处理请求。这使得能够使用竞争消费者模式,从而实现负载平衡。在发送到此队列的邮件中,您可以在邮件上设置correlationId property。对于回复,Azure服务总线的pub / sub part(“topics”)部分用于correlation filter。当您的后端处理了请求时,它将结果发布到“responseSubject”,并在原始请求中给出了correlationId。现在,您的客户可以使用该相关过滤器调用CreateSubscribtion(抱歉,我不能发布两个以上的链接,谷歌)来检索此响应,并且应该在发布答案时收到通知。请注意,CreateSubscribtion部分应该只在OnStart方法中完成一次。然后,您可以对该订阅执行异步BeginRecieve,并且当其中一个请求的响应可用时,将在给定的回调中通知该角色。 correlationId将告诉您响应的请求。因此,您的最后一个挑战是将此响应返回给持有客户端连接的线程。

这可以通过使用correlationId(可能是GUID)作为键创建Dictionary并将响应作为值来实现。当您的Web角色获得请求时,它会创建guid,将其设置为correlationId,将其添加到hashset,将消息发送到队列,然后在Guid对象上调用Monitor.Wait()。然后让主题subscribition调用的recieve方法将响应添加到字典中,然后在同一个guid对象上调用Monitor.Notify()。这会唤醒您原来的请求线程,您现在可以将答案返回给您的客户端(或者其他东西。基本上您只是想让您的线程休眠而不会在等待时消耗任何资源)

答案 1 :(得分:3)

Azure Service Bus 上的队列具有更多功能和范例,包括 pub / sub 功能,可以解决跨多个实例处理队列服务的问题。

使用pub / sub的一种方法是为请求设置一个队列,为响应设置一个队列。每个请求实例还将订阅响应队列,并在头部上使用过滤器,以便它只接收针对它的响应。请求消息当然包含放在响应头中的值以驱动过滤器。

答案 2 :(得分:3)

对于基于Service Bus的解决方案,有一些样本可用于实现QueuesTopics (pub-sub)

的请求/响应模式

答案 3 :(得分:2)

让worker角色继续轮询和处理消息。处理完消息后,在从存储队列中删除已处理的消息之前,在表存储中添加所需的corelationId(RowKey)和处理结果。

然后,WebRoles只需要查看具有所需correlationId(RowKey)&的表。 PartitionKey

答案 4 :(得分:2)

查看在worker角色和浏览器客户端之间使用SignalR。因此,您的Web角色会在队列中放置一条消息并将结果返回给浏览器(类似于“等待......”之类的简单事件)并将其连接到SignalR的worker角色。这样你的web角色就可以继续做其他事情而不必等待异步处理的结果,只需浏览器需要。

答案 5 :(得分:1)

Windows Azure队列中没有任何内在功能可以满足您的要求。但是,你可以很容易地自己构建它。在推送到队列中包含消息ID(GUID),并且在处理完成时,让工作人员将具有该消息ID的新消息推送到响应通道队列中。您的Web应用程序可以轮询此队列以确定何时完成给定命令的处理。

我们已经做了类似的事情,并希望使用类似SignalR的东西来帮助在命令完成时回复客户端。