WCF超时异常详细调查


94

我们有一个应用程序,该应用程序具有在IIS7上运行的WCF服务(* .svc),以及各种查询该服务的客户端。该服务器正在运行Win 2008 Server。客户端正在运行Windows 2008 Server或Windows 2003 Server。我遇到了以下异常,事实上,该异常可能与大量潜在的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邮件大小?最后,是否有我们可以使用的工具来测试我可以在客户端和服务器之间建立多少连接(独立于应用程序)

谢谢你的时间!

6月20日添加了其他信息:

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

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

使用WireShark,我确实看到错误发生时,我进行了5次TCP重传,随后进行了TCP重置。我的猜测是RST是来自WCF终止的连接。我收到的异常报告来自Step3超时。

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

经过更多调查,我将http数据包负载转储到磁盘上,以查看这六个调用在哪里。

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

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

a)为什么数据包损坏了?随机网络fl幸-也许?使用以下示例代码将负载压缩:http : //msdn.microsoft.com/zh-cn/library/ms751458.aspx-并发使用时,该代码是否偶尔会出现错误?我应该在没有gzip库的情况下进行测试。

b)为什么在损坏的操作超时后仍可以运行步骤1和步骤2?在我看来,似乎不应该进行这些操作。也许因为我对TCP的理解存在缺陷,所以我没有找到正确的流。我还有其他同时出现的信息流。我应该研究其他流-快速浏览流190-194会显示Step3 POST具有适当的有效负载数据(未损坏)。促使我再次查看gzip库。


杰森-您曾经解决这个问题吗?是DefaultConnectionLimit设置吗?
SFun28 2011年

2
@JasonKealey-与许多其他问题相反,您不能被指责在发布问题之前没有自己尝试一下:)我喜欢您的问题是如此详尽,并包括所有重要细节。这些症状你描述看起来非常像我的,所以我希望的解决方案是一样的好:)
岛之风Bråthen如此阐述道

Answers:


51

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

//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文件中,如下所示

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

这看起来很有希望。我将其包含在下一个可伸缩性测试中进行测试。它看起来完全像是将其崩溃的随机设置:)感谢指针。
杰森·基利

1
@Jason:如果您是服务器程序员,那么您会知道保持服务器的可伸缩性在您手中非常重要,即使在使用上述方法后,他也正在遭受并发性问题。简而言之,如果您可以看一下以下问题stackoverflow.com/questions/2637175/wcf-network-cost,我在客户端和服务器之间的延迟为31ms,因此需要减少延迟。
Mubashar'4

3
只用了一年,但是我终于在设置了此标志的应用程序上进行了另一次压力测试。该问题似乎已解决,所以我给您最好的答案。对于这是需要解决的最后一个难题,我并不感到惊讶,但是需要确保所有其他要素都到位以确保不会发生错误。非常感谢!
杰森·基利2011年

2
@Aris:在.net客户端应用程序中,在启动时或设置全局配置的任何位置,如果要使其保持可配置状态,则可以将其添加到配置文件中,例如<system.net> <connectionManagement> <add maxconnection = “ 200”地址=“ *” /> </ connectionManagement> </system.net>
Mubashar 2014年

3

如果您尚未尝试过-将服务器端WCF操作封装在try / finally块中,然后添加日志以确保它们实际上已返回。

如果这些表明操作已完成,那么我的下一步就是去一个较低的层次,并查看实际的传输层。

此时,Wireshark或其他类似的数据包捕获工具可能会很有帮助。我假设它在标准端口80上通过HTTP运行。

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

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

遇到错误时,可以遍历Wireshark日志以查找呼叫的开始。右键单击第一个发送您的客户端的数据包(应该是GET /service.svc或POST /service.svc之类),然后选择“跟随TCP流”。

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


我已经在服务器上登录-为此没有错误。我现在正在运行WireShark,以查看可以找到的内容。鉴于流量很大,分析起来很麻烦,但如果有发现,我会报告。
贾森·基利

在过去的六个小时中,我运行了WireShark,并收集了大约60k帧。该客户今天仅报告了一个例外。我确实在发送错误电子邮件后看到一个标记为RST(重置)的TCP连接,这很可能是WCF正在终止连接。我将有效负载(525k)保存到磁盘。我验证了还有87个其他调用,其有效载荷大小相近。我确实看到了一些TCP重传,但是在其他调用中也看到了一些(没有失败)。开始怀疑我的网络硬件和电缆。
贾森·凯利2009年

即使在本地网络上,TCP重新传输的存在也不一定很糟糕。如果有可能将两个端点物理连接​​到单个交换机,那也许值得一试,但是我不抱希望解决这个问题。如果可以的话-创建一个非常基本的客户端应用程序,该应用程序只会将一些流量来回传递到您的服务器,而没有其他事情。这可以帮助消除应用程序中可能引起超时的任何问题。

另外,您提到看到TCP重置数据包-服务器当时是否传递了任何形式的响应(或者它是否在等待更多数据)?RST和前一个数据包之间是否存在明显的延迟?

服务器是远程的。我打算在本地创建测试环境,以查看是否有帮助。至于RST,它是在五个TCP重传的最后一个之后34秒发送的。(重传之间的间隔为1到8秒)。那有什么线索吗?
贾森·基利

2

来自:http : //www.codeproject.com/KB/WCF/WCF_Operation_Timeout_.aspx

为避免此超时错误,我们需要 在WCF客户端代码中为Proxy 配置OperationTimeout属性。与其他配置(例如,发送超时,接收超时等)不同,该配置是新的东西,我在本文前面已经讨论过。要设置此操作超时属性配置,必须在调用操作协定方法之前将代理转换为WCF客户端应用程序中的IContextChannel。


我已经试过了。无论我设置了多长时间,它仍然会超时,但这是没有意义的,因为操作时间不那么长,并且所有其他执行相同查询的客户端在这段时间内都可以运行。
贾森·基利2009年

我的测试证明,OperationTimeout只是覆盖了配置中的ReceiveTimeout。因此,没有任何用处。
dudeNumber4 2012年

2

我有一个非常相似的问题。在过去,这与序列化问题有关。如果仍然存在此问题,可以验证是否可以正确序列化要返回的对象。具体来说,如果您使用的是具有关系的Linq-To-Sql对象,则在子对象上向父对象放置反向引用并将该反向引用标记为DataMember时,就会遇到已知的序列化问题。

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

另外,如果返回的是具有子集合的Linq-To-Sql对象,则可以尝试确保已将它们急切地加载到服务器端。有时,由于延迟加载,未填充返回的对象,并且可能会导致您在将请求多次发送到服务方法的地方看到该行为。

如果您已经解决了这个问题,我很想听听如何解决,因为我也一直坚持下去。我已经验证我的问题不是序列化,所以我很茫然。

更新:我不确定是否可以帮到您,但Service Trace Viewer Tool经过5天与您非常相似的经历后才解决了我的问题。通过设置跟踪,然后查看原始XML,我发现了导致序列化问题的异常。它与Linq-to-SQL对象有关,该对象偶尔具有比成功序列化更多的子对象。将以下内容添加到您的web.config文件中应启用跟踪:

<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>

可以使用Service Trace Viewer Tool或仅在IE中打开结果文件,以检查结果。


2

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


2

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

<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>

在节点中确认您的配置<security>,属性“ mode”值为“ None”。如果您的值为“ Transport”,则会发生错误。


这不会影响安全性吗?如果是这样,这可能不是大多数实际应用的解决方案
Veverke

0

您是否尝试使用clientVia,使用SOAP工具箱或类似工具查看发送的消息?这可以帮助查看错误是来自客户端本身还是其他地方。


您是否知道比过时的SOAP工具包更新的工具,这些工具可以使我更轻松地在WCF调用中记录此信息?
贾森·基利2009年

SOAP Toolkitdeprecated
Kiquenet

0

您是否检查了WCF跟踪?WCF倾向于吞下异常,并且仅返回最后一个异常,这是您要获取的超时,因为端点没有返回任何有意义的东西。


我尝试了SvcTraceViewer,它报告的唯一异常是超时(在客户端上)。服务器上没有任何报告。
贾森·基利2009年

打开跟踪上的所有选项,您可能没有打开所有跟踪选项。此外,请同时检查事件跟踪和消息跟踪文件。
Miki Watts,2009年

0

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


0

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

      <security mode="None">
        <transport clientCredentialType="Windows" proxyCredentialType="None"
          realm="" />
        <message clientCredentialType="UserName" algorithmSuite="Default" />
      </security>

0

我不是WCF专家,但我想知道您是否没有在IIS上遇到DDOS保护。从经验中我知道,如果您在某个时刻运行一堆从单个客户端到服务器的同时连接,则服务器会停止响应呼叫,因为它怀疑是DDOS攻击。它还将使连接保持打开状态,直到连接超时为止,以减慢客户端的攻击速度。

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

此MSDN帖子中有更多信息:

http://msdn.microsoft.com/en-us/library/bb463275.aspx

签出MaxConcurrentSession属性。


从我所看到的一切中,我觉得这是正在发生的事情,但是我(在服务器上)有:<serviceThrottling maxConcurrentCalls =“ 150” maxConcurrentInstances =“ 150” maxConcurrentSessions =“ 150” /> <serviceDebug includeExceptionDetailInFaults =“ true” />是否可以监视任何性能监视器或IIS日志以查看是否正在发生这种情况?
贾森·基利2009年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.