【发布时间】:2013-05-31 14:15:28
【问题描述】:
我们有一个 C# (.Net 4.0) 控制台应用程序,它“自托管”两个 WCF 服务:一个使用 WSHttpBinding,另一个使用 BasicHttpBinding。
连接到这些服务后,我们有两个独立的客户端应用程序:一个使用 BasicHttpBinding 的基于 Silverlight 的服务,另一个使用 WSHttpBinding 的控制台应用程序。
WCF 服务应用程序通常有大约 30 个用户通过 Silverlight 客户端进行连接,另外还有几个来自控制台应用程序客户端的连接。无论如何,它都不是“平淡无奇”。每个客户端最多每 5 秒查询一次 WCF 服务。
问题是:服务应用程序间歇性地无响应。尽管服务器本身继续运行(它继续写入日志文件),但所有 WCF 活动(在 ServiceHosts 上)似乎都“占用”了。不处理新请求(尽管接受 TCP 连接)。此外,应用程序消耗的线程数开始急剧增加,大约每秒一个新线程。代码本身对Threads 或ThreadPools 没有任何作用,尽管它偶尔会在几百毫秒内发出Thread.Sleep。
令人沮丧的是问题的间歇性:代码经常运行数小时,甚至数天而没有任何问题。然后,在没有明显原因的情况下,它突然变得无响应并且线程数开始增加。
我尝试过模拟用户活动 - 连接和断开客户端,用请求“淹没”服务 - 但我无法重现故障。
以防万一问题是 WCF 限制,我添加了以下代码:
ServiceThrottlingBehavior throttlingBehavior = new System.ServiceModel.Description.ServiceThrottlingBehavior
{
MaxConcurrentCalls = 512,
MaxConcurrentInstances = 8192,
MaxConcurrentSessions = 8192
};
host.Description.Behaviors.Add(throttlingBehavior);
host2.Description.Behaviors.Add(throttlingBehavior);
.. 没有明显效果。
我已在代码中添加了大量日志记录,以尝试确定触发此行为的原因 - 记录对每个方法的每次调用 - 但结果未出现任何结果。我已经将所有内容包装在try...catch 块中,并将任何异常吐出到日志文件中,以查看是否有东西掉到某个地方,并以类似的方式困住了UnhandledExceptions ......但又一次,似乎没有任何问题。
上述行为是否对任何人来说都很熟悉,或者任何人都可以提出解决此问题的最佳方法吗?
编辑:按照下面 Wal 的建议,当应用程序开始出现异常行为时,我已经捕获了该应用程序的 .DMP,并查看了 VS2012 中的 Parallel Stacks 视图,我看到了:
... 和其他非常相似但线程数不同的。我不够聪明,无法准确解读这意味着什么.. 谁能建议下一步从哪里开始?
【问题讨论】:
-
当你在 .net4 中时,你可以使用任务管理器来转储你的进程并将该转储文件拖回 VS 并查看并行堆栈以查看发生了什么。 希望这很明显,否则你可能不得不走 windbg 路线。 (使用相同的转储文件)。希望问题本身很简单,例如您的客户发送的另类的东西无意中备份了您的处理队列
-
你在调用方法后关闭你的客户吗?可能相关johan.driessen.se/posts/…
-
我想您已经尝试过了,但是...您是否启用了(几乎)所有与您的流程相关的性能计数器的收集?发生这种情况时,您可以比较收集的数据(争用与线程一起上升?内存使用率比线程上升得更快?等等......)
-
除非您了解它们的工作原理,否则不应更改 WCF 限制的默认设置。我建议您不要覆盖它们,因为这很少有用。另外,您是否使用服务主机的默认 ConcurencyMode 和 InstanceMode 设置?欲了解更多信息,请阅读this excellent post
-
我的专业知识位,但这听起来像是主线程之外的某些静态资源的竞争条件。 WCF 服务肯定会继续接受连接,并继续产生新线程,这些线程永远不会返回,因为前两个线程将其锁定。除了日志文件,是否还有其他正在访问的文件?根据我的经验,即使是只读的“非独占”访问也会导致竞争条件。您是否将所有静态资源包装在
lock (lockobject) { }块中?