WCF可靠会话在CPU负载过重或线程池忙时服务器出现故障

时间:2013-04-05 17:51:06

标签: c# wcf reliablesession

WCF可靠会话在CPU负载过重或线程池忙时

时发生故障

WCF Reliable Sessions中似乎存在设计缺陷,可防止在服务器处于高CPU负载(80-100%范围)或没有立即IO时发出或接受基础架构保持活动消息线程池线程可用于处理消息。由于可靠的会话不活动超时,症状表现为明显随机的信道中止。然而,似乎中止逻辑以更高的优先级或通过不同的机制运行,因为即使保持活动计时器无法运行,中止计时器似乎也会启动。

进入参考源,似乎ChannelReliableSession使用InterruptableTimer类来处理inactivityTimer。作为响应,它会触发由ReliableOutputSessionChannel设置的PollingCallback,它创建一个ACKRequestedMessage并将其发送到远程端点。 InactivityTimer使用WCF内部IOThreadTimer / IOThreadScheduler来自行安排。这取决于可用(非忙)IO ThreadPool线程来为定时器提供服务。 如果CPU负载很高,则线程池似乎不会产生新线程。因此,如果多个线程正在执行(在我的4核计算机上看起来是8个线程; 15秒不活动时间7将中止并失败),则没有线程可用于发送保持活动状态。但是如果您修改客户端上的可靠会话不活动超时比服务器长,即使在这些条件下服务器仍然会单方面中止通道,因为它期望在更短的时间内发送消息。因此,中止逻辑似乎以更高的优先级运行,或者将异常抛入其中一个执行线程(不确定哪个);我预计服务器上的中止会由于高CPU而延迟,并且客户端的超时时间最终会达到,但事实并非如此。 如果CPU负载较低,那么即使并行调用需要30-90秒才能返回,这个完全相同的情况也能正常工作。

您的InstanceMode是什么,最大并发连接,会话或实例是什么,与其他任何超时值无关(除了recieveTimeout必须大于inactivityTimeout)。它完全是WCF实现的设计缺陷;它应该使用隔离的高优先级或实时线程来为保持活动的消息提供服务,这样就不会产生虚假的中止。

简短版本是:我可以发出1000个并发请求,需要60秒才能完成15秒可靠会话不活动超时没有问题,只要CPU负载保持低水平。一旦CPU加载变得沉重,呼叫将随机开始中止,包括不占用任何CPU时间的呼叫或等待使用的双工会话等待如果来电也会增加CPU负载,那么服务将进入死亡螺旋,因为执行时间被浪费在保证中止的请求上,而其他请求则位于入站队列中。在所有请求都停止,所有正在进行的线程完成并且CPU负载下降之前,该服务无法返回到正常状态。 这种行为似乎自相矛盾地使Reliable Sessions成为最不可靠的通信机制之一。

同样的行为适用于客户;在这种情况下,WCF客户端可能受到盒子上其他进程的支配,但在高CPU负载下,它将随机中止可靠会话,除非所有操作都需要少于inactivetivityTimeout来完成,但是如果你没有发出新的调用快速WCF可能仍然无法发送保持活动状态,并且通道可能会出错。

1 个答案:

答案 0 :(得分:4)

记录我的答案:

如果使用ThreadPool.SetMinThreads(X,Y),您可以稍微缓解此问题,其中Y的某个数字大于执行并发WCF请求的线程数。然后可能有一个线程可用++来维持keep-alive,并且可靠的会话可能不会超时,即使在持续的100%CPU负载下也是如此,但这也有其局限性。在我的测试中,我将IO线程从最小的2个减少到20个,然后发出了大量的并发(但是没有任何请求,只是睡了10秒)。之后我重新运行了我的客户端,但是在CPU浪费的情况下,我能够同时成功执行所有8个。由于线程池的延迟初始化,重新启动服务然后立即执行相同的客户端测试失败。把它搞砸了我最终开始在14个同时调用(10个调用中止)再次达到超时,这可能只是调度程序没有获得足够的CPU片来正确执行。我怀疑你是否可以抓住IO线程并提高它们的优先级,你可以解决这个问题。

++因为池使用延迟初始化,所以必须从客户端发出足够的并发调用,这些调用需要时间才能完成但不使用任何CPU(例如:Thread.Sleep(5000))来强制池创建最小线程数而不触发高CPU块新线程逻辑,否则将不会创建最小线程数,问题仍然存在。

另一个可能的解决方法是使inactivityTimeout成为一个非常大的值。这将有助于缓解此问题,但会引入新的拒绝服务漏洞,即使客户意外失败也无法关闭连接。

此时似乎没有针对此问题的修复程序;我个人建议不要使用Reliable Sessions,因为它会导致连接中止和中止的情况随机中止。