WCF可靠的會話故障時重CPU負荷或在服務器線程池忙
有似乎是在WCF可靠的會話一個設計缺陷,防止問題或者當服務器處於CPU負載過高(80-100%範圍)或者沒有可用於處理消息的直接IO線程池線程時接受基礎架構保持活動消息。由於可靠的會話不活動超時,症狀表現爲明顯的隨機通道中止。然而,中止邏輯似乎以更高的優先級或通過不同的機制運行,因爲即使保持活動定時器不能運行,中止計時器似乎也會啓動。WCF可靠的會話故障時重CPU負荷或在服務器線程池忙
挖掘到參考源,看來該ChannelReliableSession使用一個InterruptableTimer類來處理靜止定時器。作爲響應,它觸發由ReliableOutputSessionChannel設置的PollingCallback,它創建一個ACKRequestedMessage並將其發送到遠程端點。 InactivityTimer使用WCF內部的IOThreadTimer/IOThreadScheduler來調度自己。這取決於可用(非繁忙)的IO ThreadPool線程來爲定時器提供服務。 如果CPU負載很高,看起來線程池不會產生新的線程。因此,如果有多個線程正在執行(在我的4核機器上顯示爲8個線程; 15秒鐘不活動TimeTimeout 7將中止並失敗),則沒有線程可用於發送保持活動狀態。但是,如果將客戶端上的可靠會話不活動超時修改爲比服務器更長,即使在這些情況下,服務器仍會單方面中止通道,因爲它期望在較短時間內發送消息。所以看起來中止邏輯運行在更高的優先級或者拋出一個異常進入一個正在執行的線程(不確定哪個);我預計服務器上的中止會由於高CPU而延遲,並且客戶端的更長暫停時間最終會被觸發,但事實並非如此。 如果CPU負載較低,那麼即使併發呼叫需要30-90秒才能返回,完全相同的情況也可以很好地工作。
您的InstanceMode是什麼,最大併發連接數,會話數或實例數是什麼,其他超時值是什麼(除了recieveTimeout必須大於inactivityTimeout)是無關緊要的。這完全是WCF實施的一個設計缺陷。它應該使用隔離的高優先級或實時線程來處理保持活動的消息,以避免虛假的異常終止。
簡短版本是:我可以發出1000個併發請求,需要60秒才能完成15秒可靠會話不活動超時沒有問題,只要CPU負載保持低。一旦CPU負載得到重呼,呼叫將隨機開始中止,包括未佔用任何CPU時間的呼叫或閒置等待使用的雙工會話。如果傳入的呼叫也增加CPU負載,則服務將進入死亡螺旋狀,因爲執行時間浪費在保證中止的請求上,而其他請求位於入站隊列中。直到所有請求都停止,所有正在運行的線程完成並且CPU負載下降,服務才能恢復到健康狀態。 這種行爲看似矛盾地使可靠會話成爲最不可靠的通信機制之一。
此相同的行爲適用於客戶;在這種情況下,WCF客戶端可能受到盒子上其他進程的控制,但是在CPU負載過高的情況下,它會隨機放棄可靠會話,除非所有操作的時間少於不活動時間的完成時間,但如果您不發出新呼叫快速WCF可能仍然無法發送保持活動狀態,並且通道可能會出錯。