我们有一个应用程序,它具有在 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 和 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 库。