程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> .NET網頁編程 >> 關於.NET >> Windows服務啟動超時時間的問題

Windows服務啟動超時時間的問題

編輯:關於.NET

最近有客戶反映,機房出現斷電情況,服務器的系統重新啟動後,數據庫服務自啟動失敗。第一次遇到這種情況,為了查看是不是斷電情況導致數據庫文件損壞,從客戶的服務器拿到數據庫的日志,進行分析。

數據庫工作機制

要分析數據庫啟動失敗的原因,首先說明一下數據庫服務的工作機制。

數據庫分為六大服務:

數據庫的六大服務之間存在依賴關系,及啟動流程:

服務自動啟動失敗原因

從客戶那裡,拿到了兩份日志,一份是開機自啟動的日志信息,此次數據庫啟動失敗。另外一份是開機後,手動啟動數據庫服務的日志信息,此次數據庫啟動成功。

首先看第一份日志:

從日志中看到,快照數據服務已經成功啟動,但是沒有後續的日志信息,說明問題可能出在snapshot服務,或者下一個將要啟動的equation服務。而另外一份日志中看到所有的服務都成功啟動,並且正常運行,這就排除了服務器意外斷電導致文件損壞的可能。

數據庫可以通過手動的方式成功啟動,說明數據庫的文件信息都正確,但是第一啟動時卻只logger、historian、snapshot服務成功啟動,由於後續沒有日志輸出,很難分析問題的原因。

既然數據庫沒有相應的日志,那麼就要通過系統日志來分析,此處需要尋求系統的事件日志的幫助。

在計算機管理中找到事件查看器,選擇系統,如下圖:

默認情況下,服務出現啟動失敗等異常時,操作系統會記錄一些系統事件。

從中可以看到如下信息:

snapshot 服務啟動時掛起事件ID 7022

有事件ID與事件描述,谷歌之,但是沒有找到相應的解決方案,沒辦法,還是只能從數據庫日志來分析。

再次分析日志,看到這樣一種情況:

snapshot服務從開始啟動,到啟動結束,共耗時兩分半,這個時間對於Windows服務的啟動來說,時間是很長了。根據此情況,以及系統事件的描述,推測,有可能是服務啟動超時。

為了驗證此推測,在數據庫服務啟動時加入一個Sleep(60000),這個時間足夠超時了。從服務管理器中啟動服務,過了一段時間後,服務啟動失敗,從事件查看器中,看到”服務啟動時掛起的消息”,由此基本上可以斷定數據庫服務是由於超時而啟動失敗的。

服務啟動超時原因

知道服務啟動失敗原因是超時導致的,還需要分析一下為什麼開機自啟動的時候服務會啟動超時。

還是從日志開始,幸好日志中有詳細的輸出日志,從這些日志中,看到兩個耗時比較長的操作:

鎖定歷史數據緩存與鎖定歷史數據補寫緩存兩個操作,耗時分別在一分鐘左右,兩個操作一起占了啟動耗時的大部分時間,那麼啟動超時就是由這兩個操作導致的。

既然這兩個操作比較耗時,那麼他們在悄悄的做什麼呢。這兩個操作實際是在鎖定物理內存,使其盡量不要交換到磁盤上,那麼開機啟動後,所有的緩存數據還沒有加載到內存中,此時鎖定此內存,就會導致操作系統將此緩存數據從磁盤加載到內存中。看似復雜,實際就是操作系統在讀磁盤,而機械磁盤的讀取速度是有限並且非常慢的,當緩存文件很大時,純粹讀取磁盤的時間就要很長。而此案例中,兩個緩存文件都在15G左右,所以耗時也就比較長了。

由此分析下來,也就找到了服務啟動超時的原因了。

服務第二次啟動時順利啟動的原因分析

這還沒完,服務啟動超時的原因是知道了,但是為什麼第二次啟動時,就可以順利啟動呢。接著分析。

再來看第二次啟動時的日志:

此日志中看到,第一次啟動中,每個占用耗時達到60秒的鎖定內存操作,此次只有3秒,可以說非常迅速了。

上面說到,鎖定內存實際是在讀取磁盤,而磁盤速度特別慢,15G的緩存文件,在3秒內讀取完,是根本不可能的。那麼唯一的可能就是根本沒有讀取磁盤。

其實這是Windows的一個內存管理機制,內存映射文件在卸載的時候,並不會立即去釋放內存,釋放內存的時機是由操作系統來決定的。當snapshot服務在很短的時間內又重新加載此內存映射文件時,操作系統發現此內存映射文件還存放在內存中,那麼就不會再加載了,因為讀取磁盤的速度實在是太慢了。而在開機啟動的時候,由於是第一次加載內存映射文件,內存中還不存在,就會讀取一次磁盤。所以這個鎖定內存的時間也就由第一啟動時的60秒變為3秒了。

設置Windows服務啟動超時時間

Windows系統的服務超時時間默認是30s,當一個服務的啟動時間超過這個時間後,服務管理器會認為服務存在異常,並視為啟動失敗,然後記錄一些系統事件信息。但是有時候這個時間是比較短的,比如我們的snapshot服務,這就需要修改注冊表來解決這個問題。注冊表項為HKEY_LOCAL_MACHINE/SYSTEM/CurrentControlSet/Control/ServicesPipeTimeout,這個值有可能不存在,如果不存在需要添加。類型為DWORD,單位是毫秒。

當然,這個超時時間是對所有服務都有效的,修改這個值並不是最好的解決辦法。最好能在snapshot程序內部,對啟動時加載緩存流程進行優化,以縮短啟動時間,或者將耗時比較長的操作放到啟動後進行。

總結

可以通過修改注冊表來修改Windows的服務啟動超時時間。

Windows的一個內存管理機制,內存映射文件在卸載的時候,並不會立即去釋放內存,釋放內存的時機是由操作系統來決定的。當程序在很短的時間內又重新加載此內存映射文件時,操作系統發現此內存映射文件還存放在內存中,那麼就不會再加載了。

當然,還有最重要的一點,日志系統很重要,騷年,乖乖的給程序加日志去吧!

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved