保持WCF回调通道无限期开放 / 如果客户端出现故障,则重新连接

16

我目前正在尝试设置类似于这样的东西:

  • 一个服务器端的Windows WCF服务通过TCP侦听来自客户端Windows服务的连接。
  • 当收到连接(客户端调用服务上的CheckIn方法)时,服务通过OperationContext.Current.GetCallbackChannel<T>获取一个回调通道。
  • 此通道与唯一键存储在一个集合中(具体而言,我将回调接口、通道和键存储在List<ClientConnection>中,其中每个属性都是一项)
  • 现在应该能够基于该唯一键将调用传递到该客户端服务

这在开始时工作正常,但经过一段时间后就会停止——我再也无法将调用传递给客户端。我认为这是因为连接已经在内部断开了,我正在尝试使用一个死连接。

考虑到这一点,我有以下问题:

  • 我如何告诉WCF我想无限期地(或尽可能长时间地)保持这些TCP连接?
  • 我如何从客户端端检查我的与服务器的连接是否仍然有效,以便在连接被破坏时放弃它并再次与服务器进行检查?

我可以想出笨拙的解决方案,但我希望这里有人告诉我正确的方法。


1
只是给大家一些信息——我们最终没有使用WCF作为我们的解决方案,因为我们正在编写一个潜在的高流量服务器应用程序,而且有很多问题需要处理。我们遇到了一些性能问题,我们的服务器应用程序在某个时候崩溃了。可能可以修复,但最终我们选择使用RabbitMQ代替。 - Joshua Evensen
谢谢提到RabbitMQ,我之前不太熟悉它。 - PaulF
1个回答

16

当您从客户端建立连接时,应在您的TCP绑定中设置两个超时值(您将传递给ClientBase<>或DuplexClientBase<>的绑定):

NetTcpBinding binding = new NetTcpBinding();
binding.ReceiveTimeout = TimeSpan.FromHours(20f);
binding.ReliableSession.InactivityTimeout = TimeSpan.FromHours(20f);

我的示例将超时时间设置为20个小时,你可以根据需要使用任何值。然后WCF将尝试在此期间保持客户端和服务器连接。默认时间相对较短(大约5分钟?),这可能解释了为什么您的连接会断开。

每当客户端和服务器之间存在通信问题(包括WCF本身关闭通道),WCF将在客户端中引发故障事件,您可以处理该事件以进行适当的操作。在我的项目中,我将我的派生对象DuplexClientBase<>转换为ICommunicationObject,以获取Faulted事件并将其转发到我的类中公开的OnFaulted事件:

ICommunicationObject communicationObject = this as ICommunicationObject;
communicationObject.Faulted +=
   new EventHandler((sender, e) => { OnFaulted(sender, e); });
在上面的代码片段中,this是我的WCF客户端类型的一个实例,这个类型在我的情况下派生自DuplexClientBase<>。在这个事件中你要做什么取决于你的应用程序。在我的情况下,应用程序是一个非关键的UI,所以如果发生WCF故障,我只需向最终用户显示一个消息框并关闭应用程序 - 如果总是这么容易就好了!

请问在客户端还是服务器端出现错误时,在哪里编写以下代码并在OnFaulted事件中执行什么操作? ICommunicationObject communicationObject = this as ICommunicationObject; communicationObject.Faulted += new EventHandler((sender, e) => { OnFaulted(sender, e); }); - KomalJariwala
@KomalJariwala,communicationObject.Faulted事件可在客户端上使用,从您的ClientBase派生对象中获取。我编辑了上面的答案以澄清这一点,并解释了我自己在OnFaulted实现中可以使用的简单代码。 - PaulF
但是服务器端的错误怎么办?如果这发生在客户端,我可以重新连接。但是在双工通信中,似乎服务器无法重新连接。 - qakmak
@qakmak,我认为这是一个无论超时如何都必须处理的情况。客户端消失而不告诉服务器的原因有很多。如果服务器有重要信息要告诉该客户端,它只能等待看看客户端是否重新连接。如果客户端重新连接,您可以获得当前回调通道。 - PaulF
1
服务器无法重新连接到客户端 - 除非客户端被公开暴露。 - Joshua Evensen
显示剩余2条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接