使用 WSHttpBinding 时 WCF 并发请求在服务器上堆积
-
08-07-2019 - |
题
我有一个 WCF 客户端/服务器应用程序,它使用 WSHttpBinding 通过 HTTP 进行通信。
服务器设置: :自托管,使用标准 WCF ServiceHost
。我的实际服务等级归因于:
[ServiceBehavior(ConcurrencyMode = ConcurrencyMode.Multiple,
InstanceContextMode = InstanceContextMode.PerSession,
UseSynchronizationContext = false)]
客户端设置: :使用 Visual-Studio 生成的客户端代理 同步 服务电话(proxy.call_server_method
阻塞直到服务器完全响应为止。)
设想:我有一个特定的方法调用,需要 20 秒才能在服务器上执行。客户端在单独的线程中调用此方法,因此它不会被阻塞,并且 ConcurrencyMode.Multiple
意味着 WCF 也应该在服务器上的单独线程中执行它。
这个理论得到了以下事实的支持:当我将我的应用程序配置为使用 NetTcpBinding
, ,一切正常。
问题:
如果我将应用程序配置为使用 WSHttpBinding
, ,那么这个长方法调用会导致 http 请求“备份”。我通过检查日志和使用 fiddler 调试 HTTP 请求来验证此行为。
例子:
- 客户端在后台线程发起 20 秒长的请求
- 客户端在前台线程发起请求B和C
- 请求 B 和 C 被发送到服务器,服务器在完成 20 秒长的请求之前不会处理它们
但是有时:
- 请求 B 和 C 不被发送 (它们甚至不会出现在 fiddler 中)直到 20 秒的请求返回(这种情况很少见)。
- 笔记:环境
<add address="*" maxconnection="100"/>
在客户端的 app.config 中使这种情况(似乎)停止发生。
- 笔记:环境
- 请求 B 立即发送并收到响应,而请求 C 则被推迟到 20 秒完成(这种情况很少见)
这是 fiddler 演示该问题的时间表:(点击查看大图)
正如您所看到的,请求都在服务器上备份。一旦 20 秒的请求完成,响应就会蜂拥而至,但请注意,有一些请求 不是 被拦住……
所以, 问题:
- 这到底是怎么回事?为什么使用它可以正常工作
NetTcpBinding
并且不能使用WSHttpBinding
? - 为什么行为不一致?
- 我能做什么来修复它?
笔记:
- 它没有锁定服务器。我已经设置了断点并使用了
!syncblk
并且它始终报告没有锁定。 - 这不是我的线程(否则 NetTcpBinding 不应该工作)
- 我有
<serviceThrottling maxConcurrentCalls="1000" maxConcurrentInstances="1000" maxConcurrentSessions="1000" />
在服务器的app.config中设置 - 20 秒的调用只是在等待计时器,它不会对 CPU、磁盘或网络造成影响
- 我更喜欢一个不涉及重新架构应用程序以使用异步调用的解决方案......这是一大堆遗留代码,我真的不想弄乱我不理解的东西。
解决方案 3
[自我回答,向其他用户展示我们的最终解决方案是什么]
最终我还是没能解决这个问题。
我们的最终解决方案是将我们的应用程序从 WSHttpBinding
并到 NetTcpBinding
在生产中 - 出于性能原因,我们一直计划最终这样做。
但这是相当不幸的,因为它留下了一个黑色印记 WSHttpBinding
这可能有也可能没有。如果有人确实想出了一个不涉及放弃的解决方案 WSHttpBinding
,我很想知道
其他提示
WCF(.Net 或 Windows 的东西)之外有一些限制,默认只允许最多两个同时出站 HTTP 连接。不幸的是,我一辈子都不记得这个东西的名字(以及你在 app.config 或你的应用程序中放置的内容来覆盖它)。鉴于您没有看到请求离开客户端,并且它只是 HTTP,我认为您遇到了“那个问题”。我会继续寻找它的名字。
更新:找到它 - 在客户端上尝试这个(但将“2”更改为更大的数字):
<configuration>
<system.net>
<connectionManagement>
<add address = "*" maxconnection = "2" />
</connectionManagement>
</system.net>
</configuration>
我们在 IIS/ASP.NET 中托管的 JSON 服务中看到了完全相同的症状。
根本原因最终是 ASP.NET 同步请求,而不是 WCF。我们必须禁用会话状态(在应用程序级别)才能获取并发 WCF 方法。
网页配置:<system.web> <sessionState mode="Off" /> </system.web>
请注意,我们的服务使用 webHttpBinding,而不是 wsHttpBinding。所以,我不确定这是否也解决了猎户座的问题。
我认为您达到了协议限制,要解决它,您需要修改客户端计算机上的标准设置:
http://support.microsoft.com/kb/183110
http://support.microsoft.com/kb/282402
我猜想 WSHttpBinding 在发出请求时使用 WinINET 设置。
如果换成BasicHttpBinding,还能用吗?
是这样吗,听起来像 这是你的问题, ,会话限制,这让我很恼火。
考虑使用ContrencyMode.Multiple在每个通话服务上以允许并发呼叫。
我忘了——可以订购吗?我认为也许 RM 通过 http 保留顺序,但也许 Tcp 会话不保留顺序(除非您明确请求它)?服务合同上是否有一个属性描述了有序/无序会话(我忘记了)。
不确定,但有时 silverlight 应用程序并发调用的问题与浏览器连接管理有关。对我来说,解决方案是将其放入我们的 App.xaml.cs 中,Application_Startup 方法如下所述: http://weblogs.asp.net/olakarlsson/simultaneously-calling-multiple-methods-on-a-wcf-service-from-silverlight
WebRequest.RegisterPrefix("http://", WebRequestCreator.ClientHttp);