简体   繁体   English

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

[英]Chatroom functionality with WCF, duplex callbacks vs polling?

I am using WCF and I am putting a chatroom facility in my C# program. 我正在使用WCF ,我在我的C#程序中放了一个聊天室设施。 So I need to be able to send information from the server to the clients for two events - 所以我需要能够从服务器向客户端发送两个事件的信息 -

  • When a user connects/disconnects I update the list of connected users and send that back to all clients for display in a TextBlock 当用户连接/断开连接时,我更新已连接用户的列表并将其发送回所有客户端以在TextBlock中显示
  • When a user posts a message, I need the server to send that message out to all clients 当用户发布消息时,我需要服务器将该消息发送给所有客户端

So I am looking for advice on the best way of implementing this. 所以我正在寻找有关实施此方法的最佳方法的建议。 I was going to use netTcpBinding for duplex callbacks to clients but then I ran into some issues regarding not being able to call back the client if the connection is closed. 我打算使用netTcpBinding对客户端进行双工回调,但后来遇到一些问题,如果连接关闭则无法回调客户端。 I need to use percall instances for scalibility. 我需要使用percall实例来提高可扩展性。 I was advised in this thread that I shouldnt leave connections open as it would 'significantly limit scalibity' - WCF duplex callbacks, how do I send a message to all clients? 在这个帖子中我被告知我不应该打开连接,因为它会“显着限制scalibity” - WCF双工回调,如何向所有客户端发送消息?

However I had a look through the book Programming WCF Services and the author seems to state that this is not an issue because 'In between calls, the client holds a reference on a proxy that doesn't have an actual object at the end of the wire. 但是,我查看了编程WCF服务一书,作者似乎说这不是问题,因为'在两次调用之间,客户端持有对代理的引用,该代理在结尾处没有实际对象。线。 This means that you can dispose of the expensive resources the service instance occupies long before the client closes the proxy' 这意味着您可以在客户端关闭代理之前很久就处理服务实例占用的昂贵资源

  1. So which is correct, is it fine to keep proxies open on clients? 那么哪个是正确的,保持代理在客户端打开是否正常?
  2. But even if that is fine it leads to another issue. 但即使这很好,也会导致另一个问题。 If the service instances are destroyed between call, how can they do duplex callbacks to update the clients? 如果在呼叫之间销毁服务实例,他们如何进行双工回调以更新客户端? Regarding percall instances, the author of Programming WCF Services says 'Because the object will be discarded once the method returns, you should not spin off background threads or dispatch asynchronous calls back into the instance' 关于percall实例,编程WCF服务的作者说'因为一旦方法返回就会丢弃该对象,你不应该脱离后台线程或将异步调用发送回实例'
  3. Would I be better off having clients poll the service for updates? 让客户轮询服务以获取更新会更好吗? I would have imagined that this is much more inefficient than duplex callbacks, clients could end up polling the service 50+ times as often as using a duplex callback. 我可以想象这比双工回调效率低得多,客户端最终可能会使用双工回调频繁地轮询服务50倍。 But maybe there is no other way? 但也许别无他法? Would this be scalable? 这可以扩展吗? I envisage several hundred concurrent users. 我设想了几百个并发用户。

Since I am guilty of telling you that server callbacks won't scale, I should probably explain a bit more. 因为我告诉你服务器回调不会扩展,我应该解释一下。 Let me start by addressing your questions: 首先让我谈谈你的问题:

  1. Without owning the book in question, I can only assume that the author is either referring to http-based transports or request-response only, with no callbacks. 如果不拥有相关书籍,我只能假设作者要么仅提到基于http的传输或请求响应,而没有回调。 Callbacks require one of two things- either the server needs to maintain an open TCP connection to the client (meaning that there are resources in use on the server for each client), or the server needs to be able to open a connection to a listening port on the client. 回调需要两件事之一 - 服务器需要维护与客户端的开放TCP连接(意味着服务器上有每个客户端使用的资源),或者服务器需要能够打开连接到监听客户端上的端口。 Since you are using netTcpBinding, your situation would be the former. 由于您使用的是netTcpBinding,因此您的情况将是前者。 wsDualHttpBinding is an example of the latter, but that introduces a lot of routing and firewall issues that make it unworkable over the internet (I am assuming that the public internet is your target environment here- if not, let us know). wsDualHttpBinding是后者的一个例子,但是它引入了许多路由和防火墙问题,使得它在互联网上无法工作(我假设公共互联网是你的目标环境 - 如果没有,请告诉我们)。

  2. You have intuitively figured out why server resources are required for callbacks. 您已经直观地弄清楚了回调需要服务器资源的原因。 Again, wsDualHttpBinding is a bit different, because in that case the server is actually calling back to the client over a new connection in order to send the async reply. 同样,wsDualHttpBinding有点不同,因为在这种情况下,服务器实际上是通过新连接回调客户端以发送异步回复。 This basically requires ports to be opened on the client's side and punched through any firewalls, something that you can't expect of the average internet user. 这基本上要求在客户端打开端口并穿过任何防火墙,这是普通互联网用户所不能想到的。 Lots more on that here: WSDualHttpBinding for duplex callbacks 这里有更多: WSDualHttpBinding用于双工回调

  3. You can architect this a few different ways, but it's understandable if you don't want the overhead (and potential for delay) of the clients constantly hammering the server for updates. 您可以通过几种不同的方式对此进行构建,但如果您不希望客户端的开销(以及延迟的可能性)不断地敲击服务器以进行更新,那么这是可以理解的。 Again, at several hundred concurrent users, you are likely still within the range that one good server could handle using callbacks, but I assume you'd like to have a system that can scale beyond that if needed (or at peak times). 同样,在几百个并发用户中,您可能仍然处于一个好的服务器可以使用回调处理的范围内,但我认为您希望系统能够在需要时(或在高峰时间)扩展到超出该范围的系统。 What I'd do is this: 我要做的是:

    1. Use callback proxies (I know, I told you not to)... Clients connecting create new proxies, which are stored in a thread-safe collection and occasionally checked for live-ness (and purged if found to be dead). 使用回调代理(我知道,我告诉过你不要)...客户端连接创建新的代理,这些代理存储在线程安全的集合中,偶尔检查生存(如果发现死亡则清除)。

    2. Instead of having the server post messages directly from one client to another, have the server post the messages to some Message Queue Middleware . 不要让服务器直接从一个客户端向另一个客户端发布消息,而是让服务器将消息发布到某个Message Queue Middleware There are tons of these out there- MSMQ is popular with Windows, ActiveMQ and RabbitMQ are FOSS (Free Open Source Software), and Tibco EMS is popular in big enterprises (but can be very expensive). 有很多这些 - MSMQ受Windows欢迎, ActiveMQRabbitMQ是FOSS(免费开源软件), Tibco EMS在大企业中很受欢迎(但可能非常昂贵)。 What you probably want to use is a topic, not a queue (more on queues vs topics here ). 你可能想使用是一个主题,而不是一个队列(更多关于队列VS主题在这里 )。

    3. Have a thread (or several threads) on the server dedicated to reading messages off of the topic, and if that message is addressed to a live session on that server , deliver that message to the proxy on the server. 在服务器上有一个专门用于读取主题消息的线程(或多个线程), 如果该消息发送到该服务器上的实时会话 ,则将该消息传递给服务器上的代理。

Here's a rough sketch of the architecture: 这是架构的草图:

队列支持的聊天架构

This architecture should allow you to automatically scale out by simply adding more servers, and load balancing new connections among them. 此体系结构应允许您通过简单地添加更多服务器来自动扩展,并在它们之间负载平衡新连接。 The message queueing infrastructure would be the only limiting factor, and all of the ones I mentioned would scale beyond any likely use case you'd ever see. 消息排队基础设施将是唯一的限制因素,我提到的所有内容都将超出您所见过的任何可能的用例。 Because you'd be using topics and not queues, every message would be broadcast to each server- you might need to figure out a better way of distributing the messages, like using hash-based partitioning. 因为您将使用主题而不是队列,所以每条消息都将被广播到每个服务器 - 您可能需要找出一种更好的方式来分发消息,例如使用基于散列的分区。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM