WCF超时异常详细调查如何实现?

内容来源于 Stack Overflow,并遵循CC BY-SA 3.0许可协议进行翻译与使用

  • 回答 (2)
  • 关注 (0)
  • 查看 (71)

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

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个,似乎并不重要,但它仍会偶尔发生。大多数时候,没有超时,但我仍然每小时得到几个。错误来自任何被调用的方法。其中一种方法没有参数并返回一点数据。另一个需要大量的数据作为参数,但是异步执行。错误总是来自客户端,并且从不在堆栈跟踪中引用服务器上的任何代码。它总是以:

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

在服务器上:我尝试过(现在有)以下绑定设置:

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

它似乎没有影响。

我试过(现在有)以下限制设置:

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

它似乎没有影响。

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

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

我跑ConcurrencyMode.Multiple了一段时间,错误仍然发生。

我试过重新启动IIS,重新启动我的底层SQL Server,重新启动机器。所有这些似乎都没有影响。

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

在客户端,我有这些设置:

maxReceivedMessageSize="2147483647"

<system.net>
    <connectionManagement>
    <add address="*" maxconnection="16"/>
</connectionManagement> 
</system.net>

我的客户关闭了它的连接:

var client = new MyClient();

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

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

MaxConnectionsPerServer=24, MaxConnectionsPer1_0Server=32.

我现在刚刚尝试过SvcTraceViewer.exe。我设法在客户端捕捉到一个例外。我看到它的持续时间是1分钟。看看服务器端跟踪,我可以看到服务器不知道这个异常。我能看到的最长持续时间是10秒。

我查看exec sp_who了服务器上使用的活动数据库连接。我只有几个(2-3)。我使用TCPview从一个客户端查看了TCP连接。它通常是2-3左右,我看到了5或6。

简而言之,我很难过。我尝试了所有我能找到的东西,并且必须错过WCF专家能够看到的非常简单的东西。我的直觉是,在服务器实际接收到消息之前和/或某些东西在服务器级别排队消息并且从不让他们处理消息之前,某些东西阻止了我的客户端在低级别(TCP)。

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

我的WCF应用程序做了类似于以下内容。

while (true)
{
   Step1GetConfigurationSettingsFromServerViaWCF(); // can change between calls
   Step2GetWorkUnitFromServerViaWCF();
   DoWorkLocally(); // takes 5-15minutes. 
   Step3SendBackResultsToServerViaWCF();
}

使用WireShark,我确实看到,当发生错误时,我有五个TCP重新传输,随后是TCP重置。我的猜测是RST来自WCF,会导致连接中断。我得到的例外报告是从Step3超时。

我通过查看tcp流“tcp.stream eq 192”发现了这一点。然后我将过滤器扩展为“tcp.stream eq 192和http和http.request.method eq POST”,并在此流中看到了6个POST。这看起来很奇怪,所以我检查了另一个流,例如tcp.stream eq 100.我有三个POST,这看起来更正常一些,因为我正在进行三个调用。但是,在每次WCF调用之后,我都会关闭连接,所以我希望每个流都有一个调用(但我对TCP的了解不多)。

多调查一下,我把http数据包加载到磁盘上,看看这六个调用在哪里。

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在损坏的操作超时后运行?在我看来,这些操作应该不会发生。也许我不是在看正确的流,因为我对TCP的理解是有缺陷的。我有其他的流同时发生。我应该调查其他流 - 快速浏览流190-194显示Step3 POST具有合适的有效负载数据(未损坏)。推动我再次查看gzip库。

提问于
用户回答回答于

如果你使用.Net客户端,那么你可能没有设置

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

这个配置进入.net客户端应用程序可能会在启动或开始测试之前。

此外,你可以在app.config文件中使用它,就像下面一样

<system.net>
    <connectionManagement>
      <add maxconnection = "200" address ="*" />
    </connectionManagement>
  </system.net>
用户回答回答于

如果你还没有尝试过 - 在try / finally块中封装你的服务器端WCF操作,并添加日志记录以确保它们实际返回。

如果这些显示操作正在完成,那么我的下一步将是进入较低级别,并查看实际的传输层。

Wireshark或其他类似的数据包捕获工具在这一点上可能相当有帮助。我假设这是通过HTTP在标准端口80上运行。

在客户端运行Wireshark。在开始捕获的选项中,将捕获过滤器设置为tcp http and host service.example.com - 这将减少不相关的流量。

如果可以,请修改客户端以通知您确切的开始调用时间以及发生超时的时间。或者只是密切监视它。

当遇到错误时,可以浏览Wireshark日志以查找呼叫的开始。右键单击第一个包含客户端调用的数据包(应该是GET /service.svc或POST /service.svc),然后选择Follow TCP Stream。

Wireshark将解码整个HTTP会话,所以你可以确保WCF实际上发送回应。

扫码关注云+社区