我需要在发布者和订阅者之间建立双向通信。这是为了方便前端 MVC3 应用程序使用相关过滤器定义订阅,然后将消息放置到主题上。最后,MVC3 控制器在 SubscriptionClient 上调用 BeginReceive(),并等待响应。
问题似乎是这些订阅对象的创建和删除。开销是巨大的,它会减慢应用程序的速度。更不用说要解决的各种限制,例如一个主题不超过 2000 个订阅。
在发布者和订阅者之间建立这种双向通信的最佳实践是什么?我们希望 MVC3 应用程序发布一条消息,然后等待对该确切消息的响应(通过 CorrelationId 属性和 CorrelationFilter)。我们已经缓存了 NamespaceManager 和 MessagingFactory,因为它们在资源方面也非常昂贵,而且还因为我们被告知 Service Bus 使用显式配置模型,我们需要在角色启动期间预先创建大部分这些东西。
因此,这给我们带来了将请求与响应关联起来的挑战,以及创建和删除订阅的巨大开销。有什么更好的做法?我们是否应该保留 SubscriptionClients 的缓存,并每次交换过滤器?其他人都做什么?我需要通过 Web 角色集群获得每秒 5 到 10,000 个 MVC3 请求的请求吞吐量。我们已经在使用 AsyncController 并在 SubscriptionClient 上使用异步 BeginReceive()。在这一点上,似乎是成千上万的订阅的创建和删除正在阻塞系统。
更新1: 根据此处提供的重要建议,我们更新了此解决方案,以在每个 Web 角色实例上保留 SubscriptionClient 对象的缓存。此外,我们已迁移到面向 MessageSession 的方法。
但是,这仍然没有缩放。看来 AcceptMessageSession() 是一个非常昂贵的操作。MessageSession 对象是否也应该被缓存和重用?每个打开的 MessageSession 对象是否都使用到服务总线的连接?如果是这样,这是否计入订阅的并发连接配额?
非常感谢。我认为我们正在到达那里。Web 上的大多数示例代码显示:Create Topic(),然后 CreateSubscription(),然后 CreateSubscriptionClient(),然后在客户端上 BeginReceive(),然后拆除所有对象。我只能说,如果你在现实生活中这样做,你的服务器就会崩溃,你很快就会用尽连接。
我们需要通过这个东西每秒发出数千个请求,很明显这些对象必须被大量缓存和重用。那么,MessageSession 是另一个要缓存的项目吗?我会享受缓存的乐趣,因为我们必须实现一个引用计数机制,一次只能给出一个对 MessageSession 的引用,因为这是针对特定于 http 请求的请求/响应,我们不能有其他的订阅者同时使用 MessageSession 对象。
UPDATE2: 好的,缓存 MessageSession 以供重复使用是不可行的,因为它们的生存时间与订阅上的 LockDuration 一样长。这是一个无赖,因为最大 LockDuration 是 5 分钟。这些似乎是针对短期发布/订阅的,而不是针对长期运行的分布式进程。看起来我们需要回到轮询 Azure 表。
总结/评论 我们尝试在服务总线上构建,因为它具有规模潜力及其持久性和交付语义。但是,似乎有些情况(其中的大量请求/响应)不适合它。发布部分工作得很好,在后端有竞争的消费者很好,但是让前端请求等待一个定义的、单一的消费者响应,根本不能很好地扩展,因为 MessageSessions 需要太长时间才能完成通过 AcceptMessageSession() 或 BeginAcceptMessageSession() 创建,因为它们不适合缓存。
如果有人有另一种观点,我很想听听。