【问题标题】:Why is my WCF channel failing?为什么我的 WCF 通道失败?
【发布时间】:2010-08-18 16:59:14
【问题描述】:

我有一台运行单个程序的计算机,该程序在其他 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

那么发生了什么?为什么它突然以故障状态结束。有什么方法可以让我知道连接出现故障的原因吗?

【问题讨论】:

    标签: c# wcf exception


    【解决方案1】:

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

    顺便说一句。您遇到了可靠会话的问题,因为它在 10 分钟不活动后超时。您为可靠会话设置了不活动超时,但绑定时也有接收超时,默认为 10 分钟。如果 10 分钟内没有消息到达,则应用程序会话关闭 = 服务实例被破坏并且可靠会话也被关闭。

    编辑:

    问题描述不充分。建筑也很奇怪。没有一项服务通过双工通道与 48 个客户端进行通信,而是有 48 个相同的服务通过双工通道与 1 个客户端进行通信。这当然会增加常见场景中不知道的其他问题,因此确实需要诊断(跟踪/性能计数器)!

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

    【讨论】:

    • 我同意,WCF 在调试方面公开的信息非常少。据我所知,如果您在抛出错误后重新使用代理客户端或通道,您将收到此异常。确保也使用 SvcTraceViewer.exe。祝你好运。
    • 主机 PC 上的单个应用程序中运行着 48 个服务。在另外 4 台 PC 上运行(最多)48 个独立的远程进程。我目前正在使用 ConcurrencyMode 作为通信两端的单一模式。关于需要在 30 年代处理的部分与似乎正在发生的事情相吻合。
    • 16MB 是问题所在,在我们的测试过程中,我们曾一度使网络和系统完全过载。感谢您帮助我们(我和 Firoso)解决问题,我们已将其减少到 128KB,并且没有其他问题。
    【解决方案2】:

    如果您不将服务异常包装到FaultExceptionFaultException&lt;T&gt;,您的频道可能处于故障状态:

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

    我假设其他一些服务调用引发异常,通道出现故障,然后当您尝试 ping 服务时,您会收到您描述的异常。

    【讨论】:

      【解决方案3】:

      假设您使用与其他远程调用相同的通道来 ping 远程服务(这就是该 ping 的重点对吗?)可能是其他方法调用之一异常/超时并导致您的频道?

      另外,在您的 ServiceBehaviors 配置中,“includeExceptionDetailInFaults”是否设置为 true?例如

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

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

      【讨论】:

      • 这并没有真正解决问题,只是提供了一个调试建议。
      • 我认为 includeExceptionDetailInFaults 不建议仅用于生产,因为它可能会暴露您系统的内部详细信息,即它与安全相关-
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-03-07
      • 1970-01-01
      • 1970-01-01
      • 2017-04-24
      • 2014-04-08
      • 2020-01-04
      相关资源
      最近更新 更多