首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >WCF超时异常详细调查

WCF超时异常详细调查
EN

Stack Overflow用户
提问于 2009-06-11 14:35:07
回答 9查看 111.7K关注 0票数 94

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

代码语言:javascript
复制
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个客户端同时运行,这似乎并不重要,它仍然偶尔发生一次。大多数时候,没有超时,但我每小时仍然会有几次。该错误来自所调用的任何方法。其中一个方法没有参数,并返回一些数据。另一个接受大量数据作为参数,但异步执行。错误始终来自客户端,并且从不在堆栈跟踪中引用服务器上的任何代码。它总是以:

代码语言:javascript
复制
 at System.Net.HttpWebRequest.GetResponse()
  at System.ServiceModel.Channels.HttpChannelFactory.HttpRequestChannel.HttpChannelRequest.WaitForReply(TimeSpan timeout)

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

代码语言:javascript
复制
maxBufferSize="2147483647" maxReceivedMessageSize="2147483647" maxBufferPoolSize="2147483647"

它似乎没有什么影响。

我已经尝试(并且目前拥有)以下限制设置:

代码语言:javascript
复制
<serviceThrottling maxConcurrentCalls="1500"   maxConcurrentInstances="1500"    maxConcurrentSessions="1500"/>

它似乎没有什么影响。

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

代码语言:javascript
复制
[ServiceBehavior(InstanceContextMode = InstanceContextMode.Single, ConcurrencyMode = ConcurrencyMode.Single)]

我用ConcurrencyMode.Multiple运行了一段时间,错误仍然出现。

我尝试过重新启动IIS,重新启动底层SQL Server,重新启动机器。所有这些似乎都不会产生影响。

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

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

代码语言:javascript
复制
maxReceivedMessageSize="2147483647"

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

我的客户端关闭其连接:

代码语言:javascript
复制
var client = new MyClient();

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

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

代码语言:javascript
复制
MaxConnectionsPerServer=24, MaxConnectionsPer1_0Server=32.

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

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

简单地说,我被难住了。我已经尝试了我能找到的一切,一定是遗漏了一些非常简单的东西,WCF专家将能够看到。我的直觉是,在服务器实际接收消息之前,有什么东西在低层(TCP)阻塞了我的客户端,和/或有什么东西在服务器层将消息排入队列,而从不让它们处理。

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

耽误您时间,实在对不起!

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

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

代码语言:javascript
复制
while (true)
{
   Step1GetConfigurationSettingsFromServerViaWCF(); // can change between calls
   Step2GetWorkUnitFromServerViaWCF();
   DoWorkLocally(); // takes 5-15minutes. 
   Step3SendBackResultsToServerViaWCF();
}

使用WireShark,我确实看到当错误发生时,我有五次TCP重新传输,随后是TCP重置。我的猜测是RST来自WCF,正在终止连接。我收到的异常报告来自Step3超时。

我通过查看tcp流"tcp.stream eq192“发现了这一点。然后我将我的过滤器扩展到“http eq192和tcp.stream eq POST”,并在此期间看到了6个帖子。这看起来很奇怪,所以我检查了另一个流,比如tcp.stream eq 100。我有三个帖子,这看起来更正常,因为我在做三个电话。但是,我确实会在每次WCF调用后关闭连接,因此我希望每个流都有一个调用(但我对TCP了解不多)。

进一步研究后,我将http数据包负载转储到磁盘上,以查看这六个数据包在哪里调用。

代码语言:javascript
复制
1) Step3
2) Step1
3) Step2
4) Step3 - corrupted
5) Step1
6) Step2

我的猜测是两个并发客户端正在使用相同的连接,这就是为什么我看到重复的原因。然而,我仍然有几个我不能理解的问题:

a)为什么报文损坏?随机网络--也许吧?使用以下示例代码对加载进行this压缩:http://msdn.microsoft.com/en-us/library/ms751458.aspx -当并发使用时,代码会偶尔出现错误吗?我应该在没有gzip库的情况下进行测试。

b)为什么在损坏的操作超时后,我会看到步骤1和步骤2正在运行?在我看来,这些操作似乎不应该发生。也许我没有看到正确的流,因为我对TCP的理解有缺陷。我还有其他同时出现的流。我应该调查其他流--快速浏览一下流190-194,就会发现Step3 POST有正确的有效负载数据(没有损坏)。让我再看一遍gzip库。

EN

回答 9

Stack Overflow用户

发布于 2009-06-17 17:05:48

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

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

Wireshark或其他类似的数据包捕获工具在这一点上可能非常有用。我假设这是在标准端口80的HTTP上运行的。

在客户端上运行Wireshark。在启动捕获时的选项中,将捕获筛选器设置为tcp http and host service.example.com -这将减少不相关的通信量。

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

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

Wireshark将对整个HTTP会话进行解码,因此您可以确保WCF实际上是在发回响应。

票数 3
EN

Stack Overflow用户

发布于 2009-08-20 14:55:30

我也遇到了类似的问题。在过去,这与序列化问题有关。如果您仍然有这个问题,您是否可以验证您可以正确序列化要返回的对象。具体地说,如果使用的是具有关系的Linq- to -Sql对象,则如果在子对象上放置对父对象的反向引用并将该反向引用标记为DataMember,则会出现已知的序列化问题。

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

此外,如果要返回具有子集合的Linq- to -Sql对象,则可以尝试确保已在服务器端立即加载了这些对象。有时,由于延迟加载,返回的对象不会被填充,并可能导致您看到的多次将请求发送到服务方法的行为。

如果你已经解决了这个问题,我很想听听是怎么解决的,因为我也被困在这个问题上了。我已经确认了我的问题不是序列化,所以我很困惑。

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

代码语言:javascript
复制
<sharedListeners>
    <add name="sharedListener"
         type="System.Diagnostics.XmlWriterTraceListener"
         initializeData="c:\Temp\servicetrace.svclog" />
  </sharedListeners>
  <sources>
    <source name="System.ServiceModel" switchValue="Verbose, ActivityTracing" >
      <listeners>
        <add name="sharedListener" />
      </listeners>
    </source>
    <source name="System.ServiceModel.MessageLogging" switchValue="Verbose">
      <listeners>
        <add name="sharedListener" />
      </listeners>
    </source>
  </sources>

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

票数 2
EN

Stack Overflow用户

发布于 2011-04-05 06:54:13

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

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/981475

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档