【发布时间】:2013-06-07 19:16:08
【问题描述】:
我有一个WPF 客户端通过WCF 托管在IIS 7 中的服务请求数据。服务方法使用 EF 调用存储过程 (SQL 2012) 以检索一些数据。
要加载大量数据,因此客户端会多次调用服务方法,以努力“分解”数据加载并避免大负载和超时。
我们使用从System.ServiceModel.ClientBase<T>.扩展生成的服务代理
我们还使用带有二进制编码的自定义 http 绑定(来自 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% 的请求在一两秒内返回。完美的!
但是,几乎在每次迭代中,都有一个呼叫需要几分钟才能完成,我不知道为什么...我在客户端上的 sendTimeOut 是 1 分钟,自然一个呼叫会失败。我将它延长到 10 分钟,通话似乎在 2 分钟多一点内完成——尽管有时需要更长的时间。问题看起来非常随机 - 它可能是第一次调用,也可能是第 30 次调用。但它的重现性非常好。
我在 WCF 服务方法中的存储过程调用周围放置了一些日志记录,它会在一秒钟内执行并取回数据。所以,我认为这不是数据库问题。
使用 Fiddler,有问题的调用会生成类似于以下内容的输出:
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 之间的重要时间。这似乎与here 看到的问题惊人地相似。
我启用了 WCF 服务跟踪,快速浏览了一下,没有错误或警告,但我无法真正理解我所看到的超出基础知识的内容。
我怎样才能确定问题出在什么地方?是序列化吗?是网络问题吗?客户端发送这么多请求,服务器跟不上吗?
我尝试通过添加适当的serviceBehaviors 来调整配置文件中的 WCF 限制,但这并没有什么不同。
我应该提到我是通过 VPN 连接执行此操作的,但文件传输、远程桌面连接等其他事情也可以正常工作。看起来还挺靠谱的。
如有需要,我可以提供更多详细信息。
编辑 (6.10.2013): 不确定这是相关还是只是侥幸,但有几次,我注意到在有问题的调用中,Body size 明显小于其他。并非每次都是如此,但它可能会提供一些线索。这是 Fiddler 的屏幕截图,向您展示了 Body 大小与每次调用的一致性。所选条目 (#21) 的大小比其他条目小得多,但需要 2 多分钟才能完成。
奇怪的是,这次我收到了异常。异常并非每次都发生。
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)
【问题讨论】:
-
您是否在绑定中使用了可靠会话?
-
不,我没有打开可靠会话。
-
几个问题;这些请求是并行的还是顺序的?您是否尝试在 IIS 中为此 WCF 服务调整高级 AppPool 设置中的最大工作进程? (这将把它变成一个网络花园)。我发现当我的服务主机在同时请求中可以处理的内容超载时会发生通信错误。
-
(1) 这些请求是连续的。一个调用将在调用下一个调用之前完成。 (2) 我没有尝试在 Advanced AppPool 设置中调整 Maximum Worker Processes。如果调用是连续的,这仍然适用吗?目前,这设置为 1。
-
我建议您尝试将 transfermode 设置为 streamed 以排除这是与内存压力有关的问题的可能性(因为流模式应该导致 wcf 使用较少的内存)