我们有一个应用程序,在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,我看到当出现错误时,有五个 TCP 重传,随后是一个 TCP 重置。我猜 RST 是来自 WCF 断开连接。我收到的异常报告是由于 Step3 超时导致的。通过查看 tcp 流"tcp.stream eq 192",我发现了这个问题。然后,我将过滤器扩展到“tcp.stream eq 192 and http and http.request.method eq POST”,并在此流中看到了6个 POST。这似乎很奇怪,所以我检查了另一个流,如 tcp.stream eq 100。我有三个 POSTs,这似乎更正常,因为我正在进行三个调用。但是,我在每次 WCF 调用之后关闭连接,所以我期望每个流只有一个调用(但我不知道 TCP 太多)。
再进一步调查,我将 HTTP 数据包转储到磁盘上,以查看这六个调用的内容。
1) Step3
2) Step1
3) Step2
4) Step3 - corrupted
5) Step1
6) Step2
我猜测可能有两个并发客户端在使用同一连接,这就是为什么我看到了重复的东西。但是,我仍然有一些问题无法理解:
a)为什么数据包会损坏?可能是随机网络故障吗?负载是使用此示例代码进行压缩的:http://msdn.microsoft.com/en-us/library/ms751458.aspx - 并发使用该代码时是否会出现错误?我应该在没有gzip库的情况下进行测试。
b)为什么在操作超时后我还能看到步骤1和步骤2在运行?我认为这些操作不应该发生。也许我没有查看正确的流,因为我对TCP的理解有误。我有其他同时发生的流。我应该调查其他流——快速浏览流190-194表明Step3 POST具有正确的有效负载数据(不是损坏的)。这推动我再次关注gzip库。