4

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

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

因此,我正在寻找有关实施此方法的最佳方法的建议。我打算使用netTcpBinding对客户端的双工回调,但后来我遇到了一些关于如果连接关闭则无法回调客户端的问题。我需要使用 percall 实例来实现可扩展性。我在这个线程中被告知我不应该打开连接,因为它会“显着限制可伸缩性” - WCF双工回调,我如何向所有客户端发送消息?

但是,我浏览了 Programming WCF Services 一书,作者似乎指出这不是问题,因为“在调用之间,客户端在代理的末尾持有一个没有实际对象的引用金属丝。这意味着您可以在客户端关闭代理之前很久就处理服务实例占用的昂贵资源'

  1. 那么哪个是正确的,让代理在客户端上保持打开状态可以吗?
  2. 但即使这很好,它也会导致另一个问题。如果服务实例在调用之间被销毁,它们如何进行双工回调来更新客户端?关于 percall 实例,Programming WCF Services 的作者说“因为一旦方法返回对象将被丢弃,你不应该分离后台线程或将异步调用分派回实例”
  3. 让客户轮询服务以获取更新会更好吗?我会想象这比双工回调效率低得多,客户端最终可能会像使用双工回调一样频繁地轮询服务 50 次以上。但也许没有别的办法?这可以扩展吗?我设想有数百个并发用户。
4

1 回答 1

1

由于我告诉您服务器回调不会扩展,因此我可能应该多解释一下。让我从解决您的问题开始:

  1. 如果没有这本书,我只能假设作者指的是基于 http 的传输或仅指请求-响应,没有回调。回调需要两件事之一 - 服务器需要保持与客户端的开放 TCP 连接(意味着服务器上每个客户端都有资源正在使用中),或者服务器需要能够打开与监听的连接客户端上的端口。由于您使用的是 netTcpBinding,因此您的情况将是前者。wsDualHttpBinding 是后者的一个例子,但它引入了许多路由和防火墙问题,使其无法在 Internet 上运行(我假设公共 Internet 是您的目标环境 - 如果不是,请告诉我们)。

  2. 您已经直观地理解了为什么回调需要服务器资源。同样,wsDualHttpBinding 有点不同,因为在这种情况下,服务器实际上是通过新连接回调客户端以发送异步回复。这基本上需要在客户端打开端口并通过任何防火墙,这是普通互联网用户无法预料的。这里有更多内容:用于双工回调的 WSDualHttpBinding

  3. 您可以通过几种不同的方式来构建它,但如果您不希望客户端不断敲击服务器以进行更新的开销(和潜在的延迟),这是可以理解的。同样,对于数百个并发用户,您可能仍在一台好的服务器可以使用回调处理的范围内,但我假设您希望拥有一个可以在需要时(或在高峰时间)扩展的系统。我要做的是:

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

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

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

这是架构的粗略草图:

队列支持的聊天架构

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

于 2011-12-20T05:03:05.067 回答