Azure Service Bus - 双向通信性能挑战

时间:2012-09-26 13:11:54

标签: asp.net-mvc-3 azure azure-web-roles servicebus azureservicebus

我需要在发布服务器和订阅服务器之间建立双向通信。这是为了方便前端MVC3应用程序使用关联过滤器定义订阅,然后将消息放到主题上。最后,MVC3控制器调用SubscriptionClient上的BeginReceive(),并等待响应。

问题似乎是创建和删除这些Subscription对象。开销很大,并且会使应用程序变慢。这并不是说要解决的各种限制,例如主题上的订阅数量不超过2000个。

在发布者和订阅者之间建立这种双向通信的最佳做法是什么?我们希望MVC3应用程序发布消息,然后等待对该确切消息的响应(通过CorrelationId属性和CorrelationFilter)。我们已经缓存了NamespaceManager和MessagingFactory,因为它们在资源方面也非常昂贵,并且还因为我们被告知Service Bus使用显式配置模型,我们需要在角色启动期间预先创建大部分内容。

因此,这给我们留下了将请求与响应相关联的挑战,以及创建和删除订阅的巨大开销。还有什么更好的做法?我们应该保留SubscriptionClient的缓存,并每次交换过滤器吗?其他人都做了什么?我需要通过Web角色群集获得每秒5到10,000个MVC3请求的请求吞吐量。我们已经在使用AsyncController并在SubscriptionClient上使用异步BeginReceive()。它似乎是数以千计的订阅的创建和删除,此时系统正在窒息。

UPDATE1: 根据此处提供的出色建议,我们更新了此解决方案,以便在每个Web角色实例上保留SubscriptionClient对象的缓存。此外,我们已迁移到面向MessageSession的方法。

然而,这仍然没有缩放。似乎AcceptMessageSession()是一个非常昂贵的操作。 MessageSession对象是否也应该被缓存并重新使用?每个打开的MessageSession对象是否都使用与服务总线的连接?如果是这样,是否会计入订阅的并发连接配额?

非常感谢。我想我们到了那里。 Web上的大多数示例代码显示:在客户端上创建Topic(),然后是CreateSubscription(),然后是CreateSubscriptionClient(),然后是BeginReceive(),然后拆除所有对象。我可以说的是,如果你在现实生活中这样做,你的服务器就会被粉碎,你很快就可以在连接上完成。

我们需要通过这件事每秒发出数千个请求,很明显这些对象必须被高速缓存和重用。那么,MessageSession还有另一个要缓存的项目吗?我将获得有趣的缓存,因为我们必须实现一个引用计数机制,其中一次只能给出一个对MessageSession的引用,因为这是针对http请求特定的请求/响应,我们不能有其他订阅者同时使用MessageSession对象。

UPDATE2: 好吧,缓存MessageSession以便重复使用是不可行的,因为它们只与订阅时的LockDuration一样长。这是一个无赖,因为最大LockDuration是5分钟。这些似乎是短期的pub / sub,而不是长期运行的分布式进程。看起来我们需要回到轮询Azure表。

内容/评注 由于规模潜力及其持久性和交付语义,我们尝试构建Service Bus。但是,似乎有些情况下,它们之间的大量请求/响应不适合它。发布部分运行良好,并且在后端拥有竞争的消费者是很好的,但是有一个前端请求等待定义的单一消费者响应,根本不能很好地扩展,因为MessageSessions需要太长时间才能完成通过AcceptMessageSession()或BeginAcceptMessageSession()创建,因为它们不适合缓存。

如果某人有其他观点,我很乐意听到。

3 个答案:

答案 0 :(得分:4)

此场景是一个经典的请求/响应,也是使用会话的好选择。这是另一种相关机制。创建一个简单的请求队列和响应队列。每个Web角色线程都为请求创建一个唯一的sessionid,并将该值放入brokeredmessage的“ReplyToSessionID”属性中。此线程还使用sessionid值调用响应队列上的AcceptMessageSession,以便锁定它。代理消息被发送到请求队列,所有工作者角色竞争消息。当一个辅助角色获得一个请求时,它会处理它,创建一个响应消息并在请求的响应消息= replytosessinid上设置sessionid属性。然后将其发送到响应队列,并仅传递给已锁定该会话ID的线程。详细示例using sessions is here。此处有2个额外样本使用QueuesTopics来实现请求响应关联。

答案 1 :(得分:1)

对于单个发件人和收件人,您只需要一个主题/订阅。您可以在同一订阅上设置多个correlation filters,从而使您需要的所有响应都显示在同一订阅中。目前,我们在单个订阅上支持最多100,000个关联过滤器实例,并且可以添加/删除这些实例(如果需要,可以使用事务)以及主题/订阅上的消息发送/接收操作。

此外,您可以使用带操作的规则,根据匹配的过滤器,根据需要使用其他属性标记邮件。

答案 2 :(得分:1)

另一种方法是使用相关ID和回调委托字典在Web角色实例上执行消息关联。

每个Web角色(发布者)实例都有一个订阅,由单个订阅ID过滤到响应主题。

在发送消息之前,该消息的回调将在字典中注册,并将相关ID作为密钥。相关id和订阅id与消息一起发送,使得响应可以与相关id一起发送回正确的订阅。

每个Web角色实例都监视单个订阅,并在收到响应时删除字典条目并调用回调。