WCF的聊天室功能,双工回调与轮询?

时间:2011-12-19 22:02:13

标签: c# wcf chatroom

我正在使用WCF,我正在我的C#计划中设置聊天室设施。所以我需要能够从服务器向客户端发送两个事件的信息 -

  • 当用户连接/断开连接时,我会更新已连接用户的列表并将其发送回所有客户端,以便在TextBlock中显示
  • 当用户发布消息时,我需要服务器将该消息发送给所有客户端

所以我正在寻找有关实施此方法的最佳方法的建议。我打算使用netTcpBinding对客户端进行双工回调,但后来遇到一些问题,如果连接关闭则无法回调客户端。我需要使用percall实例来提高可扩展性。我在这个帖子中被告知我不应该打开连接,因为它会“显着限制scalibity” - WCF duplex callbacks, how do I send a message to all clients?

然而,我查看了编程WCF服务一书,作者似乎表明这不是问题,因为'在两次调用之间,客户端持有对没有实际对象的代理的引用。电线的末端。这意味着您可以在客户端关闭代理“

之前处理服务实例占用的昂贵资源
  1. 那么哪个是正确的,保持代理在客户端打开是不是很好?
  2. 但即使这很好,也会导致另一个问题。如果在呼叫之间销毁服务实例,他们如何进行双工回调以更新客户端?关于percall实例,编程WCF服务的作者说'因为一旦方法返回就会丢弃该对象,你不应该脱离后台线程或将异步调用发送回实例'
  3. 让客户轮询服务以获取更新会更好吗?我可以想象这比双工回调效率低得多,客户端最终可能会使用双工回调频繁地轮询服务50倍。但也许别无他法?这可以扩展吗?我设想了几百个并发用户。

1 个答案:

答案 0 :(得分:1)

由于我告诉你服务器回调不会扩展,我应该解释一下。首先让我谈谈你的问题:

  1. 在没有相关书籍的情况下,我只能假设作者要么只是引用基于http的传输,要么只是请求 - 响应,没有回调。回调需要两件事之一 - 服务器需要维护与客户端的开放TCP连接(意味着服务器上有每个客户端使用的资源),或者服务器需要能够打开连接到监听客户端上的端口。由于您使用的是netTcpBinding,因此您的情况将是前者。 wsDualHttpBinding是后者的一个例子,但是它引入了很多路由和防火墙问题,使得它在互联网上无法工作(我假设公共互联网是你的目标环境 - 如果没有,请告诉我们。)

  2. 您已经直观地弄清楚了回调需要服务器资源的原因。同样,wsDualHttpBinding有点不同,因为在这种情况下,服务器实际上是通过新连接回调客户端以发送异步回复。这基本上要求在客户端打开端口并穿过任何防火墙,这是普通互联网用户所不能想到的。这里有更多内容:WSDualHttpBinding for duplex callbacks

  3. 您可以通过几种不同的方式对此进行构建,但如果您不希望客户端的开销(以及延迟的可能性)不断地敲击服务器以进行更新,那么这是可以理解的。同样,在几百个并发用户中,您可能仍然处于一个好的服务器可以使用回调处理的范围内,但我认为您希望系统能够在需要时(或在高峰时间)扩展到超出该范围的系统。我要做的是:

    1. 使用回调代理(我知道,我告诉过你不要)...连接创建新代理的客户端,这些代理存储在一个线程安全的集合中,偶尔也会检查是否为live-ness(并且如果发现则被清除)死了。

    2. 让服务器将消息发布到某些Message Queue Middleware,而不是让服务器直接从一个客户端向另一个客户端发布消息。其中有很多这些 - MSMQ受Windows欢迎,ActiveMQRabbitMQ是FOSS(免费开源软件),Tibco EMS在大型企业中很受欢迎(但可能非常昂贵)。你可能想要使用的是一个主题,而不是一个队列(更多关于队列与主题here)。

    3. 在服务器上有专门用于读取主题消息的线程(或多个线程),如果该消息发送到该服务器上的实时会话,则传递该消息到服务器上的代理。

  4. 这是架构的草图:

    Queue-backed Chat Architecture

    此架构应允许您通过简单地添加更多服务器来自动扩展,并在它们之间对新连接进行负载平衡。消息排队基础设施将是唯一的限制因素,我提到的所有内容都将超出您所见过的任何可能的用例。因为您将使用主题而不是队列,所以每条消息都会被广播到每个服务器 - 您可能需要找出一种更好的方式来分发消息,例如使用基于散列的分区。