为什么我的WCF频道失败了?

时间:2010-08-18 16:59:14

标签: c# wcf exception

我有一台运行单个程序的计算机,可以在另外4台计算机上管理多达48个单独的进程。我有这样设置的WCF服务(每个进程一个):

    public void StartService(Uri uri, string identifier)
    {
        unitMetaData = identifier;
        var binding = new WSDualHttpBinding(WSDualHttpSecurityMode.None);
        binding.ReliableSession.InactivityTimeout = TimeSpan.FromDays(20);
        var reader = binding.ReaderQuotas as XmlDictionaryReaderQuotas;
        reader.MaxStringContentLength = WCFContentSize; // 16777216
        service = new ServiceHost(this, uri);
        service.Faulted += TestService_Faulted;
        service.AddServiceEndpoint(
            typeof(IController),
            binding,
            identifier);
        service.Open();
    }

以下是远程进程的代码:

    public void Connect()
    {
        // External binding used to change the WCF XML text content size
        var binding = new WSDualHttpBinding(WSDualHttpSecurityMode.None);
        binding.ReliableSession.InactivityTimeout = TimeSpan.FromDays(20);
        var reader = binding.ReaderQuotas as XmlDictionaryReaderQuotas;
        reader.MaxStringContentLength = WCFContentSize; // 16777216
        DuplexChannelFactory<IController> factory = new DuplexChannelFactory<IController>(new InstanceContext(this), binding);
        controllerChannel = factory.CreateChannel(new EndpointAddress(controllerAddress, new DnsEndpointIdentity(controllerAddress.DnsSafeHost), new System.ServiceModel.Channels.AddressHeaderCollection()));
        ((IClientChannel)controllerChannel).OperationTimeout = TimeSpan.FromSeconds(ChannelOperationTimeoutInSeconds); // 300
        controllerChannel.RequestTestData();
    }

我有一些代码会调用远程“Ping()”函数,该函数在每个远程进程上大约每30秒返回一个字符串“Pong”。我这样做是为了确保连接保持打开,因为我遇到了ReliableSession超时问题。偶尔(对于生产代码来说太常见)我从一个测试进程连接的服务中获得以下异常:

An ExceptionDetail, likely created by IncludeExceptionDetailInFaults=true, whose value is:
System.ServiceModel.CommunicationObjectFaultedException: The communication object, System.ServiceModel.Channels.ServerReliableDuplexSessionChannel, cannot be used for communication because it is in the Faulted state.

Server stack trace: 
   at System.ServiceModel.Channels.TransmissionStrategy.WaitQueueAdder.Wait(TimeSpan timeout)
   at System.ServiceModel.Channels.TransmissionStrategy.InternalAdd(Message message, Boolean isLast, TimeSpan timeout, Object state, MessageAttemptInfo& attemptInfo)
   at System.ServiceModel.Channels.ReliableOutputConnection.InternalAddMessage(Message message, TimeSpan timeout, Object state, Boolean isLast)
   at System.ServiceModel.Channels.ReliableDuplexSessionChannel.OnSend(Message message, TimeSpan timeout)
   at System.ServiceModel.Channels.DuplexChannel.Send(Message message, TimeSpan timeout)
   at System.ServiceModel.Dispatcher.DuplexChannelBinder.Request(Message message, TimeSpan timeout)
   at System.ServiceModel.Channels.ServiceChannel.Call(String action, Boolean oneway, ProxyOperationRuntime operation, Object[] ins, Object[] outs, TimeSpan timeout)
   at System.ServiceModel.Channels.ServiceChannelProxy.InvokeService(IMethodCallMessage methodCall, ProxyOperationRuntime operation)
   at System.ServiceModel.Channels.ServiceChannelProxy.Invoke(IMessage message)

Exception rethrown at [0]: 
   at System.Runtime.Remoting.Proxies.RealProxy.HandleReturnMessage(IMessage reqMsg, IMessage retMsg)
   at System.Runtime.Remoting.Proxies.RealProxy.PrivateInvoke(MessageData& msgData, Int32 type)
   at SEL.MfgTestDev.ESS.ServiceContracts.ITestProcessClient.Ping()
   at SEL.MfgTestDev.ESS.Testing.Service.TestService.Ping() in C:\Projects\Mfg_TestDev_ESS_Rev3\branches\MSU-5-18-2010\ESS.Testing.Service\TestService.cs:line 349

那是怎么回事?为什么它突然陷入了错误的状态。有没有办法可以解决连接出现故障的原因?

3 个答案:

答案 0 :(得分:9)

对于生产环境不是一个好主意,但您可以尝试在服务器和客户端上启用WCF tracing。您希望找到更好的错误描述。

顺便说一下。你有可靠的会话问题,因为它在10分钟不活动后超时。您为可靠会话设置了不活动超时,但在绑定时也会收到超时,默认情况下为10分钟。如果10分钟内没有消息到达,应用程序会话将被关闭=服务实例被销毁,可靠会话也将关闭。

修改

问题描述不足。建筑也很奇怪。没有一种服务通过双工信道与48个客户端通信,但是通过双工信道与一个客户端进行48次相同的服务通信。这当然可以添加常见方案中未知的其他问题,因此真正需要诊断(跟踪/性能计数器)!

当检查Connect方法的代码时,它甚至看起来像客户端回调是与所有48个服务进行单一通信,不是吗?在该回调上使用什么并发模式?如果并发模式为单一,则在调用回调时可能存在超时问题,因为消息大小设置为16MB。如果所有48个进程在同一时间发送16MB消息,则它们将按FIFO顺序排队和处理。默认设置要求在30秒内处理,否则发生超时异常并且通道出现故障。如果并发模式是多次的,那么回调实现中仍然可能存在一些同步问题。

答案 1 :(得分:2)

如果您未将服务例外包含在FaultExceptionFaultException<T>中,您的频道可能处于出现故障状态:

http://blogs.msdn.com/b/pedram/archive/2008/01/25/wcf-error-handling-and-some-best-practices.aspx

我假设某些其他服务调用抛出异常,通道出现故障,然后当您尝试ping服务时,您将获得您描述的异常。

答案 2 :(得分:0)

假设您正在使用相同的通道来ping远程服务和其他远程调用(这是ping的权利的全部内容吗?),可能是其他方法调用之一除外/超时并且出现故障信道?

另外,在ServiceBehaviors的配置中,'includeExceptionDetailInFaults'是否设置为true? e.g。

<behaviors>
   <behavior name="MyServiceBehaviors">
      <serviceDebug includeExceptionDetailInFaults="true" />
   </behavior>
</behaviors>

在调试期间,这很有用,因为它允许您查看来自服务器的异常消息,但缺点是如果您的频道也出现故障,那么在生产环境中最好将其关闭。