2010-04-23 75 views
2

我開發了中間件,它爲我們組織內多個平臺上的多個客戶端應用程序提供RPC功能。中間件用C#編寫,並作爲Windows NT服務運行。它處理文件訪問網絡共享,數據庫訪問等事情。中間件託管在運行Windows Server 2008的兩個高端系統上。Windows NT服務關機問題

當我們的服務器管理員之一去重新啓動計算機時,主要執行Windows更新,在我的NT服務方面,系統的行爲方式存在嚴重問題。我的服務旨在立即停止監聽新連接,立即開始拒絕現有連接上的新請求,並在SCM發出OnStop或OnShutdown請求的情況下儘快關閉。但是,爲保持系統完整性,目前正在進行的操作可以在合理的時間內繼續進行。通常,服務器在30秒內關閉(例如,在手動停止服務時)。但是,當指示系統重新啓動時,我的服務立即失去對網絡驅動器和UNC路徑的訪問權限,從而導致任何打開文件的數據完整性問題以及對這些位置的部分寫入。我的服務確實將Workstation(因此SMB重定向器)列爲依賴項,因此如果Windows遵守這些依賴關係,我認爲我的服務需要在Workstation/Redirector停止之前停止。

基本上,我的應用程序被迫崩潰並燒壞,失敗的遠程過程調用,並最終在超時時間過後(似乎大約20-30秒)被操作系統強制終止。

與Windows應用程序不同,我的Windows NT服務似乎沒有任何權限來阻止正在進行的系統關閉,延遲系統關閉,甚至只是有機會在存在之前保存任何掛起的網絡共享磁盤寫入強行斷開和關閉。在這種環境下,NT服務開發人員應該如何擁有任何類型的應用程序完整性?爲什麼Forms應用程序在關閉之前得到完成業務的所有機會,而服務似乎沒有這種好處?

我曾嘗試:通過P

調用SetProcessShutdownParameters /調用嘗試通知我關機更快的應用程序,以避免重定向器關閉我之前做。

使用小於或等於兩分鐘限制的值調用ServiceBase.RequestAdditionalTime。

扭捏WaitToKillServiceTimeout的

一切我能想到的,使我的服務關閉快。

但是最後,我仍然遇到了30秒的問題時間,其中我的服務似乎還沒有收到OnShutdown事件的通知,但由於重定向器不再爲我的網絡共享提供服務,請求失敗要求。

這個問題是如何解決的?我能做些什麼來延遲或停止關機,或者至少被允許在沒有重定向服務的情況下關閉我的活動任務?我可以理解微軟正在試圖做些什麼來防止服務拖垮他們並顯示關閉,但這似乎是Windows客戶端操作系統的一個偉大目標,而不是服務器。我不希望我的服務器快速關閉,我希望操作的完整性和優雅的關閉。

在此先感謝您提供的任何幫助。

更新:我已經做了確切的時間。在測試關機時,我在23:55:58得到了關機通知,並注意到23:56:02失去了網絡共享連接。所以在4秒鐘內,我失去了保存任何活動狀態的能力。

+1

真的不是您的問題的答案,但是所有其他失敗模式(如路由器崩潰或遠程文件服務器突然重新啓動)呢?你不需要處理所有這些嗎? – 2010-04-23 06:43:00

+0

除了Workstation之外,可能還會將Netman添加到您的依賴項中,值得一試。 – Filburt 2010-04-23 06:51:48

+0

在前端,我在多臺刀片服務器上運行該中間件服務的多個副本,並在它們前面安裝高度可用的冗餘F5負載平衡器對,並配置爲在緊時間進行重新選擇。我們的網絡旨在爲路由器(主要是第3層交換機接口)提供HSRP冗餘,交換機之間的中繼線採用LACP等。我關心的主要文件服務器運行在Microsoft故障轉移羣集中,後端是EMC光纖通道SAN。我們在硬件方面一直非常穩固。這就是這個「簡單」的軟件問題,它正在扼殺它。 – 2010-04-23 06:53:03

回答

1

這個問題:https://serverfault.com/questions/34427/windows-service-dependencies在ServerFault應該回答你自己的。它鏈接到這篇文章:http://blogs.technet.com/askperf/archive/2008/02/04/ws2008-service-shutdown-and-crash-handling.aspx,這應該有助於您獲得關機前通知和服務關機訂購。

+0

我已經在註冊表中爲我的服務配置了預關閉通知,但我無法弄清楚如何在C#.NET NT服務中註冊PRESHUTDOWN通知。我嘗試使用爲ACCEPT_PRESHUTDOWN設置的結構p/invoke SetServiceStatus,但它沒有任何影響,或者我無法通過OnCustomCommand獲取該事件。 – 2010-04-23 08:15:11

+0

問題是:你什麼時候調用SetServiceStatus?問題在於,當OnStart返回時(爲了告訴SCM服務狀態爲RUNNING),ServiceBase以它自己的接受命令的概念進行操作。所以,我想你需要從OnStart生成一個線程(我猜你已經這麼做了),並用自己的接受命令列表再次調用SetServiceStatus。 – Timores 2010-04-24 15:36:42