问题描述
我有一个 WPF
客户端通过主持
IIS 7中的
WCF
服务请求数据/ code>。 service方法使用 EF
调用存储过程( SQL 2012
)来检索一些数据。
I have a WPF
client requesting data via WCF
service hosted in IIS 7
. The service method makes a call to a stored procedure (SQL 2012
) using EF
to retrieve some data.
需要加载大量数据,因此客户端会多次调用服务方法,以分解数据加载并避免大量有效负载和超时。
There's a lot of data to load so the client makes several calls to the service method in an effort to "break up" the data loading and avoid large payloads and timeouts.
我们使用从 System.ServiceModel.ClientBase< T>扩展而来的生成的服务代理。
我们还使用带二进制编码的自定义http绑定(来自) - 此处显示的实际实现:
We're also using a custom http binding with binary encoding (from here) - actual implementation shown here:
<customBinding>
<binding name="CustomBinding_IPointDataAccess" closeTimeout="00:01:00"
openTimeout="00:01:00" receiveTimeout="00:10:00" sendTimeout="00:01:00">
<binaryMessageEncoding maxReadPoolSize="64" maxWritePoolSize="16" maxSessionSize="2048">
<readerQuotas maxDepth="2147483647" maxStringContentLength="2147483647" maxArrayLength="2147483647" maxBytesPerRead="2147483647" maxNameTableCharCount="16384" />
</binaryMessageEncoding>
<httpTransport manualAddressing="false" maxBufferPoolSize="524288"
maxReceivedMessageSize="2147483647" allowCookies="false" authenticationScheme="Anonymous" bypassProxyOnLocal="false" decompressionEnabled="true" hostNameComparisonMode="StrongWildcard" keepAliveEnabled="true" maxBufferSize="2147483647" proxyAuthenticationScheme="Anonymous" realm="" transferMode="Buffered" unsafeConnectionNtlmAuthentication="false" useDefaultWebProxy="true" />
</binding>
此外,动态压缩已转为在IIS中。我可以在Fiddler中查看请求,并且消息正文的大小很好(~50KB),并且 99%的请求在一两秒内返回。完善!
Also, dynamic compression is turned on in IIS. I can view the requests in Fiddler, and the size of the message's body is fine (~50KB) and 99% of the requests return in a second or two. Perfect!
然而,几乎每次迭代都有一个电话需要几分钟才能完成,我不知道为什么......我的 sendTimeOut
在客户端是1分钟,自然一个呼叫将失败。我把它延长到10分钟,电话似乎在2分多钟内完成 - 虽然有时需要更长时间。这个问题看起来非常随机 - 可能是第一次通话,可能是第30次通话。但它是非常可重复的。
However, with almost every iteration, there is one call in the bunch that takes minutes to complete, and I don't know why... My sendTimeOut
on the client was at 1 minute and naturally that one call would fail. I extended it to 10 minutes, and the call seems to complete in a little more than 2 minutes - although sometimes it would take even longer. The problem appears very random - it could be the first call, it could be the 30th call. But it's very reproducible.
我在WCF服务方法中对存储过程调用进行了一些日志记录,并在一秒钟内执行并获取数据。所以,我不认为这是一个数据库问题。
I placed some logging around the the stored procedure call in the WCF service method and it executes and gets data back in under a second. So, I don't think it's a database issue.
使用Fiddler,有问题的调用生成类似于以下内容的输出:
Using Fiddler, the problematic call generates output similar to the following:
ACTUAL PERFORMANCE
--------------
ClientConnected: 14:02:42.959
ClientBeginRequest: 14:03:01.224
GotRequestHeaders: 14:03:01.224
ClientDoneRequest: 14:03:01.574
Determine Gateway: 0ms
DNS Lookup: 0ms
TCP/IP Connect: 46ms
HTTPS Handshake: 0ms
ServerConnected: 14:05:16.021
FiddlerBeginRequest: 14:05:16.021
ServerGotRequest: 14:05:16.021
ServerBeginResponse: 14:03:04.784
GotResponseHeaders: 14:05:16.561
ServerDoneResponse: 14:05:16.611
ClientBeginResponse: 14:05:16.611
ClientDoneResponse: 14:05:16.611
请注意 ServerBeginResponse
和 GotResponseHeaders 。这看起来与的问题非常相似。
Notice the significant time between ServerBeginResponse
and GotResponseHeaders
. This seems strikingly similar to the issue seen here.
我启用了WCF服务跟踪,并且快速浏览一下,没有任何错误或警告,但除了基本功能外,我无法理解我正在看的内容。
I enabled WCF Service Tracing, and at a quick glance, there are no errors or warnings, but I can't really make much sense out of what I'm looking at beyond the basics.
如何确定问题的所在和位置?是序列化吗?这是网络问题吗?服务器是否可以跟不上发送这么多请求的客户端?
我已经尝试通过添加相应的 serviceBehaviors ,但这没什么区别。
I've tried adjusting the WCF Throttling in the config file by adding the appropriate serviceBehaviors
, but this did not make a difference.
我应该提一下,我是通过VPN连接这样做的,但其他的东西,如文件传输,远程桌面连接工作得很好。它看起来非常可靠。
I should mention that I am doing this over a VPN connection, but other things like file transfers, remote desktop connections work just fine. It seems pretty reliable.
如有必要,我可以提供更多详细信息。
I can provide more details if necessary.
编辑(6.10。 2013):不确定这是否相关或只是侥幸,但有几次,我注意到在有问题的电话中,身体尺寸明显小于其他人。每次都不是这种情况,但它可能提供一些线索。这是来自Fiddler的屏幕截图,向您展示每次调用时Body尺寸的一致性。所选条目(#21)的尺寸远小于其他条目,但需要2分钟才能完成。
Edit (6.10.2013): Not sure if this is related or just a fluke, but a couple times, I've noticed that on the problematic call, the Body size is significantly less than the others. This is not the case each time, but it may provide some clues. Here is a screen capture from Fiddler to show you how consistent the Body size should be with each call. The selected entry (#21) is much smaller than the others in size, but takes over 2 minutes to complete.
奇怪的是,这次我收到了一个例外。每次都不会发生异常。
Oddly enough, this time I received an exception. The exception does not happen every time.
System.ServiceModel.CommunicationException: The server did not provide a meaningful reply; this might be caused by a contract mismatch, a premature session shutdown or an internal server error.
Server stack trace:
at System.ServiceModel.Channels.ServiceChannel.Call(String action, Boolean oneway, ProxyOperationRuntime operation, Object[] ins, Object[] outs, TimeSpan timeout)
at System.ServiceModel.Channels.ServiceChannel.Call(String action, Boolean oneway, ProxyOperationRuntime operation, Object[] ins, Object[] outs)
at System.ServiceModel.Channels.ServiceChannelProxy.InvokeService(IMethodCallMessage methodCall, ProxyOperationRuntime operation)
at System.ServiceModel.Channels.ServiceChannelProxy.Invoke(IMessage message)
Exception rethrown at [0]:
at System.Runtime.Remoting.Proxies.RealProxy.HandleReturnMessage(IMessage reqMsg, IMessage retMsg)
at System.Runtime.Remoting.Proxies.RealProxy.PrivateInvoke(MessageData& msgData, Int32 type)
推荐答案
正如我在评论中所建议的那样,请尝试将transfermode设置为流式传输以排除可能性这是一个与内存压力相关的问题(因为流模式应该导致wcf使用更少的内存)。
As I suggested in the comments, please try setting transfermode to streamed to rule out the possibility that this is an issue related to memory pressure (since stream mode should cause wcf to utilize less memory).
当我看到这个问题时,怀疑这可能是问题,因为在快速连续进行多次服务呼叫时,似乎只会发生这种情况。根据我的经验,这通常是两个问题之一:代理没有从客户端正确关闭,或者服务器由于内存压力而运行GC。
When I saw this issue suspected this might be the problem because it only seems to happen to you when making many service calls in rapid succession. In my experience this is often one of two problems: either the proxies aren't being properly closed from the client, or the server is running GC's due to memory pressure.
当缓冲传输模式时,WCF会将消息响应的整个数据集加载到内存中,然后再将其发送回客户端。流式传输只是将数据发回而不进行缓冲。它对于大型数据集来说往往要快得多,对于小型数据集来说要慢一些,并且总是使用更少的内存(在服务器和客户端上)。
When the transfermode is buffered, WCF loads the entire dataset for the message response into memory before sending it back to the client. Streamed simply sends the data back without buffering. It tends to be much faster for large data sets, slightly slower for small data sets, and always utilizes less memory(on both the server and client).
这篇关于WCF - 进行多次调用时随机客户端超时的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!