1. 程式人生 > >玩轉Windows服務系列——Windows服務啟動超時時間

玩轉Windows服務系列——Windows服務啟動超時時間

最近有客戶反映,機房出現斷電情況,伺服器的系統重新啟動後,資料庫服務自啟動失敗。第一次遇到這種情況,為了檢視是不是斷電情況導致資料庫檔案損壞,從客戶的伺服器拿到資料庫的日誌,進行分析。

資料庫工作機制

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

資料庫分為六大服務:

資料庫六大服務

資料庫的六大服務之間存在依賴關係,及啟動流程:

資料庫啟動流程

服務自動啟動失敗原因

從客戶那裡,拿到了兩份日誌,一份是開機自啟動的日誌資訊,此次資料庫啟動失敗。另外一份是開機後,手動啟動資料庫服務的日誌資訊,此次資料庫啟動成功。

首先看第一份日誌:

快照資料服務成功啟動

從日誌中看到,快照資料服務已經成功啟動,但是沒有後續的日誌資訊,說明問題可能出在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的一個記憶體管理機制,記憶體對映檔案在解除安裝的時候,並不會立即去釋放記憶體,釋放記憶體的時機是由作業系統來決定的。當程式在很短的時間內又重新載入此記憶體對映檔案時,作業系統發現此記憶體對映檔案還存放在記憶體中,那麼就不會再載入了。

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

系列連結