WCF 超时太快和“连接意外关闭”异常

Posted

技术标签:

【中文标题】WCF 超时太快和“连接意外关闭”异常【英文标题】:WCF timing out too soon & 'Connection was closed unexpectedly' exception 【发布时间】:2014-04-25 19:28:01 【问题描述】:

当调用返回字符串“success”的方法时,WCF 客户端会在 120 秒后返回上述异常。服务器的日志显示它完全执行并在大约 3 分钟内完成。启用跟踪后,我看不到任何错误。 任何帮助将不胜感激,因为类似问题的其他建议很遗憾没有帮助。谢谢!

编辑 - 已解决:原来客户端使用的是 Smoothwall 过滤设备,该设备在两分钟后关闭连接。

例外:

System.ServiceModel.CommunicationException The underlying connection was closed: The connection was closed unexpectedly.
Stack Trace:    at System.Net.HttpWebRequest.GetResponse()
   at System.ServiceModel.Channels.HttpChannelFactory.HttpRequestChannel.HttpChannelRequest.WaitForReply(TimeSpan timeout)

内部异常:

System.Net.WebException The underlying connection was closed: The connection was closed unexpectedly.The underlying connection was closed: The connection was closed unexpectedly.
Stack Trace:    at System.Net.HttpWebRequest.GetResponse()
   at System.ServiceModel.Channels.HttpChannelFactory.HttpRequestChannel.HttpChannelRequest.WaitForReply(TimeSpan timeout)

据我所知,绑定设置正确,超时时间超过 120 秒。这是客户端绑定:

<bindings>
  <customBinding>
      <binding name="CustomBinding_IPHG" closeTimeout="00:05:00"
          openTimeout="00:05:00" receiveTimeout="00:15:00" sendTimeout="00:15:00">
          <security authenticationMode="SecureConversation" requireDerivedKeys="false">
              <localClientSettings maxClockSkew="00:30:00" />
              <localServiceSettings maxClockSkew="00:30:00" />
              <secureConversationBootstrap authenticationMode="UserNameOverTransport">
                  <localClientSettings maxClockSkew="00:30:00" />
                  <localServiceSettings maxClockSkew="00:30:00" />
              </secureConversationBootstrap>
          </security>
          <textMessageEncoding>
              <readerQuotas maxStringContentLength="5242880" />
          </textMessageEncoding>
          <httpsTransport maxReceivedMessageSize="6553600" useDefaultWebProxy="true" />
      </binding>
  </customBinding>
</bindings>
<behaviors>
<endpointBehaviors>
<behavior name="commonBehaviour">
  <dataContractSerializer maxItemsInObjectGraph="2147483647"/>
  <clientCredentials>
    <serviceCertificate>
      <authentication certificateValidationMode="PeerOrChainTrust"/>
    </serviceCertificate>
  </clientCredentials>
</behavior>
</endpointBehaviors>
</behaviors>

这是服务器绑定:

<bindings>
  <customBinding>
    <binding name="CommonBinding" closeTimeout="00:05:00" openTimeout="00:05:00" receiveTimeout="00:15:00" sendTimeout="00:15:00">
      <transactionFlow />
      <security authenticationMode="SecureConversation" requireDerivedKeys="false">
        <secureConversationBootstrap authenticationMode="UserNameOverTransport">
          <localServiceSettings maxClockSkew="00:30:00" />
          <localClientSettings maxClockSkew="00:30:00" />
        </secureConversationBootstrap>
        <localServiceSettings maxClockSkew="00:30:00" />
        <localClientSettings maxClockSkew="00:30:00" />
      </security>
      <textMessageEncoding>
        <readerQuotas maxStringContentLength="41943040"/>
      </textMessageEncoding>
      <httpsTransport maxBufferSize="41943040" maxReceivedMessageSize="41943040" />
    </binding>
  </customBinding>
</bindings>
<behaviors>
  <serviceBehaviors>
    <behavior name="BehaviorRBS">
      <serviceMetadata httpsGetEnabled="true" httpGetEnabled="false" />
      <serviceDebug includeExceptionDetailInFaults="true" httpHelpPageEnabled="false" />
      <dataContractSerializer maxItemsInObjectGraph="2147483647" />
      <serviceCredentials>
        <userNameAuthentication userNamePasswordValidationMode="Custom" customUserNamePasswordValidatorType="PHGAPI.PHGUserNamePassValidator, PHGAPI"/>
        <serviceCertificate
                findValue="*.domainname.com"
                x509FindType="FindBySubjectName"
                storeLocation="LocalMachine"
                storeName="My" />
      </serviceCredentials>
      <serviceThrottling maxConcurrentCalls="200" maxConcurrentSessions="400" maxConcurrentInstances="600" />
    </behavior>
  </serviceBehaviors>
</behaviors>
<services>
    <service behaviorConfiguration="BehaviorRBS" name="PHGAPI.iAPI">
      <endpoint address="" binding="customBinding" bindingConfiguration="CommonBinding" contract="PHGAPI.IiAPI" />
    </service>
</services>

这是相关方法的接口:

[OperationContract]
string SetSuspensions(List<Suspension> suspensions);

【问题讨论】:

它看起来像是被编辑掉了,但是我有没有看到你说服务器完成了它的执行?此错误可能是从服务器抛出的,而不是超时。需要明确的是,它是客户端对服务器错误的响应。 可能是结果序列化问题? @paqogomez 我已经在服务器上写入了一个日志文件,它在'返回“成功”之前立即写入日志;'线。此日志条目发生在大约 3 分钟后,也就是客户端收到异常后大约一分钟。因此,我相信服务器运行良好。 @IgorK,我首先建议查看support.microsoft.com/kb/2538826 并在那里实施建议的调整。顺便说一句,.NET 4.5 的 WCF 运行时已经得到了很大的改进。除此之外,您是否检查过该客户的计算机是否运行任何防病毒/网络过滤器或具有限制性防火墙/代理配置? 还有两件事:try disabling KeepAlive、check WCF and ASP.NET timeouts。 【参考方案1】:

我会查看默认值为 120 秒的 WCF 和相关配置设置。为此,您可能需要查看 HTTP.sys connectionTimeout 值。

来自 Microsoft 文档: 由于以下原因,可以认为连接处于非活动状态:

HTTP.sys Timer_ConnectionIdle 计时器已过期。连接 已过期并保持空闲状态。 HTTP.sys Timer_EntityBody 计时器已过期。连接已过期 在请求实体主体到达之前。当很明显一个 请求有一个实体主体,HTTP API 开启 Timer_EntityBody 计时器。最初,此计时器的限制设置为 连接超时值。每次另一个数据指示 收到此请求后,HTTP API 将重置计时器以提供 在 connectionTimeout 中指定的连接更多分钟 属性。 HTTP.sys Timer_AppPool 计时器已过期。连接已过期 因为请求在应用程序池队列中等待的时间过长 服务器应用程序出列并处理它。此超时持续时间 是连接超时。

默认值为 00:02:00(两分钟)。

http://www.iis.net/configreference/system.applicationhost/sites/sitedefaults/limits

祝你好运。

【讨论】:

不幸的是,这并没有奏效,尽管我真的很希望它会。 IIS 站点被调整为 900 秒的连接超时,但是 120 秒后客户端上发生了相同的超时。客户端(控制台应用程序)是否有类似的超时? 以下可能会有所帮助,因为操作似乎有类似的问题:***.com/questions/14266854/… 位于 C:\Windows\System32\LogFiles\HTTPERR\httperr1.log 的日志文件可能会提供一些关于超时原因的见解。 除了 HttpSys 日志之外,服务器和客户端上的 WCF 跟踪文件似乎是一个很好的信息来源,尤其是任何服务器与客户端的通信/异常的时间。如果您尚未设置跟踪,以下链接可能会有所帮助:msdn.microsoft.com/en-us/library/ms733025(v=vs.110).aspx【参考方案2】:

追踪这些问题可能会很痛苦。请尝试以下方法来帮助追踪问题。

1) 确定问题出在哪里,即客户端或服务器。在 IDE 中以调试模式启动 Service,然后使用 WCF Test client 而不是您自己的客户端来排除客户端配置问题。

2) 安装并使用Fiddler2 来检查去往\来自服务的HTTP 消息。您将看到服务是否返回响应以及其中的内容。

3) 假设这是一个同步调用,保持一个线程打开三分钟无论如何对性能都是不利的。也许考虑重构服务以更快地返回数据或使其成为async。

【讨论】:

1) Fiddler 仅适用于客户端堆栈。 2)即使客户端完成异步连接仍然可能超时【参考方案3】:

根据您的问题和下面的 cmets 中发布的信息,在我看来,这个方程式的客户端部分出现了超时。由于生成客户端的默认超时非常小。只需让您的客户修改他们的配置以增加超时时间。

--exert(客户端配置)--

<configuration>
    <startup> 
        <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" />
    </startup>
    <system.serviceModel>
        <bindings>
            <basicHttpBinding>
                <binding name="BasicHttpBinding_IService1" closeTimeout="00:10:00" openTimeout="00:10:00" receiveTimeout="00:10:00" sendTimeout="00:10:00"  />
            </basicHttpBinding>
        </bindings>
        <client>
            <endpoint address="http://localhost:8733/Design_Time_Addresses/WcfServiceLibrary1/Service1/"
                binding="basicHttpBinding" bindingConfiguration="BasicHttpBinding_IService1"
                contract="ServiceReference1.IService1" name="BasicHttpBinding_IService1" />
        </client>
    </system.serviceModel>
</configuration>

您使用的绑定不同,但所有绑定都具有这些属性。我通常会增加所有超时,但对你来说最重要的是“receiveTimeout”

【讨论】:

谢谢,我确实认为这也是客户问题。客户端绑定已经有 15 分钟的超时 - 这在原始帖子中列出。我已要求客户仔细检查任何网络过滤器,以防导致此问题。【参考方案4】:

客户在哪里? (同一个公司网络,同一个国家)

客户端的网速是多少?

参数 List suspends 的字节大小是多少?

您是否尝试使用 Fiddler 或其他一些网络包软件来捕获传输?

在之前的工作中,有一种情况是服务器中的每个错误都记录到不同的服务器;问题是带有 10,000 行错误行的传入消息被发送到日志,但不是作为单个失败错误,而是作为相同错误的 10,000 倍。

将这个 200MB 以上的巨大对象序列化到另一台服务器会导致内部网络被视为 100% 利用率并使服务器运行 100%,因此 IIS 无法及时响应任何其他请求。

我并不是说这可能是你的情况,我只是分享我遇到的超时情况,问题不在于超时的方法,而在于服务中的另一个组件。

【讨论】:

您建议在客户端还是服务器端使用 Fiddler? 双方都可以访问吗?如果问题出在单个客户端,那么在客户端。如果有多个客户端,则检查服务器中的流量【参考方案5】:

建议您在业务逻辑方法中使用事务范围。

如果您遇到此类错误,请停止您的数据库服务器并重新启动。我认为这可能会解决您的问题。因为有时数据库流量拥塞所花费的时间比开发人员预期的要长。因此,如果您的应用程序很重,请减少从应用程序到服务器的数据库调用。

【讨论】:

以上是关于WCF 超时太快和“连接意外关闭”异常的主要内容,如果未能解决你的问题,请参考以下文章

延迟加载 - (实体框架)底层连接意外关闭

异常:“请求被中止:连接意外关闭”调用两个方法时相同的对象

WCF超时异常详查

C# Streamreader:连接意外关闭

Python 2:SMTPServerDisconnected:连接意外关闭

Django 发送电子邮件:SMTPServerDisconnected:连接意外关闭