WCF超时异常详细调查

WCF timeout exception detailed investigation

我们有一个应用程序,在iis7上运行了一个wcf服务(*.svc),以及查询该服务的各种客户机。服务器正在运行Win 2008 Server。客户端正在运行Windows 2008 Server或Windows 2003 Server。我得到了以下异常,我已经看到这实际上可能与大量潜在的WCF问题有关。

1
System.TimeoutException: The request channel timed out while waiting for a reply after 00:00:59.9320000. Increase the timeout value passed to the call to Request or increase the SendTimeout value on the Binding. The time allotted to this operation may have been a portion of a longer timeout. ---> System.TimeoutException: The HTTP request to 'http://www.domain.com/WebServices/myservice.svc/gzip' has exceeded the allotted timeout of 00:01:00. The time allotted to this operation may have been a portion of a longer timeout.

我已将超时时间增加到30分钟,错误仍然发生。这告诉我还有其他东西在发挥作用,因为数据的数量永远不会需要30分钟来上传或下载。

错误来了又去了。目前,这种情况更为频繁。如果我有3个客户机同时运行或者100个客户机,这似乎无关紧要,但它仍然会偶尔发生。大多数时候,没有超时,但我仍然每小时有几个。错误来自任何被调用的方法。其中一个方法没有参数并返回一点数据。另一个接受大量数据作为参数,但异步执行。错误总是源于客户机,并且从不在堆栈跟踪中引用服务器上的任何代码。它总是以:

1
2
 at System.Net.HttpWebRequest.GetResponse()
  at System.ServiceModel.Channels.HttpChannelFactory.HttpRequestChannel.HttpChannelRequest.WaitForReply(TimeSpan timeout)

在服务器上:我已尝试(并且当前已尝试)以下绑定设置:

1
maxBufferSize="2147483647" maxReceivedMessageSize="2147483647" maxBufferPoolSize="2147483647"

它似乎没有影响。

我已尝试(并且当前已尝试)以下限制设置:

1
<serviceThrottling maxConcurrentCalls="1500"   maxConcurrentInstances="1500"    maxConcurrentSessions="1500"/>

它似乎没有影响。

我目前有以下WCF服务设置。

1
[ServiceBehavior(InstanceContextMode = InstanceContextMode.Single, ConcurrencyMode = ConcurrencyMode.Single)]

我和ConcurrencyMode.Multiple一起跑了一段时间,但还是出现了错误。

我已尝试重新启动IIS,重新启动基础SQL Server,重新启动计算机。所有这些似乎都没有影响。

我已尝试禁用Windows防火墙。它似乎没有影响。

在客户机上,我有以下设置:

1
2
3
4
5
6
7
maxReceivedMessageSize="2147483647"

<system.net>
    <connectionManagement>
   
</connectionManagement>
</system.net>

我的客户端关闭其连接:

1
2
3
4
5
6
7
8
9
10
var client = new MyClient();

try
{
    return client.GetConfigurationOptions();
}
finally
{
    client.Close();
}

我已更改注册表设置以允许更多传出连接:

1
MaxConnectionsPerServer=24, MaxConnectionsPer1_0Server=32.

我最近刚试过svctraceviewer.exe。我设法在客户端捕获了一个异常。我看到它的持续时间是1分钟。查看服务器端跟踪,我可以看到服务器没有意识到这个异常。我能看到的最长持续时间是10秒。

我研究过在服务器上使用exec sp_who的活动数据库连接。我只有一些(2-3)。我已经使用tcpview研究了来自一个客户机的TCP连接。通常是2-3左右,我见过5-6个。

简单地说,我被难住了。我已经尝试了我能找到的一切,一定是错过了一个世界自然基金会的专家能够看到的非常简单的东西。我的直觉是,在服务器实际接收到消息之前,有什么东西在低层(TCP)上阻塞了我的客户机,或者有什么东西在服务器层排队,从不让他们处理消息。

如果你有我应该看的性能计数器,请告诉我。(请指出哪些值是坏的,因为有些计数器很难破译)。另外,如何记录WCF消息大小?最后,有没有我们的工具可以让我测试我的客户机和服务器之间可以建立多少连接(独立于我的应用程序)

谢谢你的时间!

6月20日增加的额外信息:

我的WCF应用程序执行类似于以下的操作。

1
2
3
4
5
6
7
while (true)
{
   Step1GetConfigurationSettingsFromServerViaWCF(); // can change between calls
   Step2GetWorkUnitFromServerViaWCF();
   DoWorkLocally(); // takes 5-15minutes.
   Step3SendBackResultsToServerViaWCF();
}

使用wireshark,我确实看到了当错误发生时,我有五次TCP重传,随后是TCP重设。我猜第一个是来自WCF的,切断了连接。我得到的异常报告来自第3步超时。

我通过查看TCP流"tcp.stream eq 192"发现了这一点。然后我将过滤器扩展到"tcp.stream eq 192和http和http.request.method eq post",并在这个流中看到6个post。这看起来很奇怪,所以我检查了另一个流,如tcp.stream eq 100。我有三个帖子,这看起来有点正常,因为我打了三个电话。但是,每次wcf调用之后,我都会关闭连接,所以我希望每个流都有一个调用(但我对tcp不太了解)。

进一步研究一下,我将HTTP数据包加载转储到磁盘,以查看这六个调用的位置。

1
2
3
4
5
6
1) Step3
2) Step1
3) Step2
4) Step3 - corrupted
5) Step1
6) Step2

我猜两个并发客户机正在使用相同的连接,这就是我看到重复的原因。但是,我还有一些我无法理解的问题:

a)为什么数据包损坏?随机网络侥幸-也许?使用下面的示例代码gzip加载:http://msdn.microsoft.com/en-us/library/ms751458.aspx-代码在同时使用时是否会偶尔出错?我应该在没有gzip库的情况下进行测试。

b)为什么我会看到步骤1和步骤2在损坏的操作超时后运行?在我看来,这些行动不应该发生。也许我没在看


如果您使用的是.NET客户端,则可能没有设置

1
2
//This says how many outgoing connection you can make to a single endpoint. Default Value is 2
System.Net.ServicePointManager.DefaultConnectionLimit = 200;

这是最初的问题和答案WCF服务限制

更新:

.NET客户端应用程序中的此配置可能正在启动,也可能是在启动测试之前的任何时候。

此外,您还可以在app.config文件中使用它,如下所示

1
2
3
4
5
<system.net>
    <connectionManagement>
     
    </connectionManagement>
  </system.net>


如果你还不想你已encapsulate IT操作服务器端的WCF和添加try块/机会,确保他们是实际上返回的记录。

如果这些行动是表演,完成下一步,然后我会去一个较低的水平,和看实际的传输层。

wireshark或另一个类似的数据包捕获工具可以帮助我们在这一点上。我以为这是一个标准的HTTP端口80上运行过。

Wireshark的运行在客户端。当你开始在选项设置过滤器捕获,捕获到tcp http and host service.example.com-这将减少交通量无关。

如果你能将你的客户通知你确切的时间和启动时间的呼叫,当超时发生。或只是它的仔细监测。

当你得到错误,那么你可以通过wireshark拖网日志找到启动的呼叫。右点击你的包在第一个客户端呼叫出有它(应该是什么样的,service.svc或/和随后service.svc)选择的TCP流。

wireshark要解码整个HTTP会话,这样你可以确保WCF实际上是发送回响应。


我刚刚解决了这个问题。我发现app.config文件中的节点配置错误。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<client>
<endpoint name="WCF_QtrwiseSalesService" binding="wsHttpBinding" bindingConfiguration="ws" address="http://cntgbs1131:9005/MyService/TGE.ISupplierClientManager" contract="*">
</endpoint>
</client>

<bindings>
    <wsHttpBinding>
        <binding name="ws" maxBufferPoolSize="2147483647" maxReceivedMessageSize="2147483647" messageEncoding="Text">
            <readerQuotas maxDepth="2147483647" maxStringContentLength="2147483647" maxArrayLength="2147483647" maxBytesPerRead="2147483647" maxNameTableCharCount="2147483647"/>
            <**security mode="None">**
                <transport clientCredentialType="None"></transport>
            </security>
        </binding>
    </wsHttpBinding>
</bindings>

在节点中确认配置,属性"模式"值为"无"。如果您的值是"transport",则会发生错误。


是否在请求之间关闭与WCF服务的连接?如果不这样做,您将看到这个确切的超时(最终)。


我也遇到了类似的问题。在过去,这与序列化问题有关。如果仍然存在此问题,可以验证是否可以正确序列化要返回的对象。具体来说,如果使用的是具有关系的Linq to SQL对象,那么如果将子对象上的后引用放在父对象上并将该后引用标记为数据成员,则会出现已知的序列化问题。

您可以通过编写控制台应用程序来验证序列化,该应用程序使用服务器端的DataContractSerializer以及客户端使用的任何序列化方法对对象进行序列化和反序列化。例如,在我们当前的应用程序中,我们有WPF和CompactFramework客户机。我编写了一个控制台应用程序来验证是否可以使用DataContractSerializer进行序列化,以及使用XmlDesSerializer进行反序列化。你可以试试。

此外,如果要返回具有子集合的Linq to SQL对象,则可以尝试确保已在服务器端急切地加载了它们。有时,由于延迟加载,返回的对象不会被填充,可能会导致您看到请求多次发送到服务方法的位置的行为。

如果你解决了这个问题,我很想听听是怎么回事,因为我也被它困住了。我已经验证了我的问题不是串行化的,所以我很困惑。

更新:我不确定它是否对您有帮助,但是服务跟踪查看器工具在5天后解决了我的问题,与您的体验非常相似。通过设置跟踪,然后查看原始XML,我发现了导致序列化问题的异常。它与linq-to-sql对象相关,这些对象偶尔会有比成功序列化更多的子对象。将以下内容添加到web.config文件应启用跟踪:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<sharedListeners>
    <add name="sharedListener"
         type="System.Diagnostics.XmlWriterTraceListener"
         initializeData="c:\Temp\servicetrace.svclog" />
  </sharedListeners>
  <sources>
    <source name="System.ServiceModel" switchValue="Verbose, ActivityTracing">
      <listeners>
       
      </listeners>
    </source>
    <source name="System.ServiceModel.MessageLogging" switchValue="Verbose">
      <listeners>
       
      </listeners>
    </source>
  </sources>

结果文件可以用服务跟踪查看器工具打开,也可以只在IE中检查结果。


来自:http://///KB www.codeproject.com WCF WCF _ _ _ .aspx操作超时

To avoid this timeout error, we need
to configure the OperationTimeout
property for Proxy in the WCF client
code. This configuration is something
new unlike other configurations such
as Send Timeout, Receive Timeout etc.,
which I discussed early in the
article. To set this operation timeout
property configuration, we have to
cast our proxy to IContextChannel in
WCF client application before calling
the operation contract methods.


希望它能在msdn博客中帮助您:

http://blogs.msdn.com/tess/archive/2009/01/09/net-hang-my-application-hang-after-i-called-my-wcf-service-a-couple-times.aspx


看起来这个异常消息是非常普通的,由于各种原因可以接收到。我们在Windows8.1机器上部署客户端时遇到了这个问题。我们的WCF客户端运行在Windows服务内部,并不断地轮询WCF服务。Windows服务在非管理员用户下运行。通过在WCF配置中将ClientCredentialType设置为"Windows"以允许身份验证通过,解决了此问题,如下所示:

1
2
3
4
5
      <security mode="None">
        <transport clientCredentialType="Windows" proxyCredentialType="None"
          realm="" />
        <message clientCredentialType="UserName" algorithmSuite="Default" />
      </security>

如果要将对象传递回包含枚举类型的属性(默认情况下未设置该属性,并且该枚举没有映射到0的值)的客户端,也将收到此错误。即enum MyEnum{ a=1, b=2};


你检查WCF的痕迹?有一个异常的WCF的倾向和燕子只返回最后超时异常,这是不是你的终点,因为没有任何有意义的回报。


我不是一个WCF的专家,但我想知道如果你不运行在IIS一个DDoS保护。我知道,如果你运行一个体验几乎同步连接到服务器和客户端在一个单点服务器的调用,它停止responding嫌疑人a DDoS攻击。所以它不会直到他们持有的连接开放时间要慢的客户端下他的攻击。

多连接来自不同的IP的机器/ a的问题应该不多。

它在这个MSDN上的更多信息:

http://。/en-US /图书馆/ bb463275.aspx

maxconcurrentsession sproperty退房。


你尝试使用clientvia看到消息发送,使用SOAP工具包或什么?这可以帮助到湖,如果错误是来自客户端或从它在别的地方。