我有一个 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 秒长的请求之前不会处理它们
但有时候:
- 在 20 秒的请求返回之前(这种情况很少见) ,请求 B 和 C不会被发送(它们甚至不会出现在 fiddler 中)。
- 注意:
<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、磁盘或网络
- 我更喜欢不涉及重新构建应用程序以使用异步调用的解决方案......这是一大堆遗留代码,我真的不想弄乱我不理解的东西。