台灣最大程式設計社群網站
線上人數
394
 
會員總數:245463
討論主題:189220
歡迎您免費加入會員
討論區列表 >> 專欄文章 >> 分散式 Web 應用程式的偵錯
[]  
[我要回覆]
回應主題 加入我的關注話題 檢舉此篇討論 將提問者加入個人黑名單
分散式 Web 應用程式的偵錯
價值 : 0 QP  點閱數:2428 回應數:0

樓主

站務人員 站長
門外漢
0 1580
542 9
發送站內信

捐贈 VP 給 站務人員
Anand Rajagopalan

程式發展專員

電子商務主要支援團隊

Microsoft Corporation 2000 年 8 月


摘要: 提供使用於分散式 Web 應用程式 (Distributed Web Application) 偵錯工具的知識。
在使用 Internet Information Services (IIS) 主動伺服網頁 (Active Server Pages, ASP) 的 Web 基礎發展環境中,針對中階層的 (Component Object Model, COM) 元件進行偵錯。

---------------------------------------------------------------

序言

本文的焦點

本文提供使用於分散式 Web 應用程式偵錯工具的知識。在使用Microsoft® Internet Information Services (IIS) 主動伺服網頁 (ASP) 的 Web 基礎發展環境中,針對中階層的 COM 元件進行偵錯。讀完本文後,使用者應能夠:

了解 IIS 的架構。

了解術語同處理序 (in-process)、跨處理序 (out-of-process) 和共用應用程式 (pooled application),並描述它們的優缺點。

了解如何使用例外監視器 (Exception Monitor) 去監視 IIS 應用程式和 COM 元件。

了解如何使用使用者轉儲 (User Dump) 將程序的記憶體資料轉移到磁碟上並做檢查。

了解如何使用 WinDBG 偵錯線上的程序。

了解如何使用性能監視器 (Performance Monitor) 排除 CPU 的問題。

了解使用控制台偵錯工具 (Console-Based Debugger, CDB) 和微軟 Windows NT 符號/系統偵錯工具 (Symbolic/Systems Debugger, NTSD)。

目標使用者

閱讀本文將使程式開發者、專業支援人員和包含發展與維持 Web 站台的 Web 管理員等,獲得對 IIS 架構及偵錯程序更多的了解。

簡介

Internet Information Server 架構

為了了解元件的偵錯程序,首要的就是透徹了解 IIS 的架構。
以下的圖將讓您深入了解 IIS、ASP、網際網路伺服器應用程式介面 (Internet Server Application Programming Interface, ISAPI),和元件之間的關係。

[圖 1] Internet Information Server 架構

網際網路服務

Inetinfo.exe 程式包含許多由 IIS 提供的網際網路服務 (HTTP、FTP、SMTP、NNTP)。Inetinfo.exe 接收從 TCP/IP 次系統傳來的要求,並將它們導向各自對應的服務,且依序地解釋這些要求,執行它們,並將結果傳回客戶端。由於所有的服務都是在相同的程式 (inetinfo.exe) 內執行,所以它們可共享快取區資料,如檔案控制代碼 (file handle),帳戶資訊 (account information) 和記錄檔資料 (log file data)。

ISAPI

有兩種不同形式的 ISAPI DLL:ISAPI 篩選常式 (filter) 和 ISAPI 擴充部分。

ISAPI 篩選常式 (filter) 是一個動態連結程式庫 (DLL),在 inetinfo.exe 程式內執行,用以過濾進出伺服器的資料。這個過濾器登錄為事件告知型態。當選擇的事件發生時,控制權將轉移到過濾器並且您可監視和修改資料 (從伺服器到客戶端或反向亦可)。ISAPI 篩選常式 (filter) 可以增強 HTTP 要求的日誌功能 (例如,追蹤誰登入您的伺服器),自訂加密或附加驗證方法。一旦啟用 ISAPI 篩選常式 (filter),所有的要求和回應都必須通過它們,這樣可能會對站台的性能有很大的影響。



ISAPI 伺服程式擴充部分 是一 DLL,HTTP 伺服程式可載入和呼叫它。網際網路伺服程式擴充部分,亦稱為「網際網路伺服應用程式 (ISA)」,可以增強 ISAPI 相容伺服程式的能力。ISA 可以由瀏覽程式呼叫觸發,並提供普通閘道介面 (CGI) 應用程式相似的機能,但比 CGI 有較佳的性能。



主動伺服網頁 (Active Server Page, ASP)

ASP 有如 ISAPI 的擴充 DLL。IIS 與 ASP 有分開的執行緒共用區 (pool)。IIS 使用一個稱為非同步執行緒佇列 (Asynchronous Thread Queue, ATQ) 的內部執行緒共用區 (pool),也稱為共用執行緒 (pool threads)。IIS 使用 ATQ 接受通訊端的連接,並送給客戶端靜態內容。一旦要求被辨識為 ASP 網頁,IIS 就會將網頁要求 (page request) 傳送到 ASP/MTS 執行緒共用區處理。



所有 ISAPI 管理和 ASP 程式碼均移動至一個稱為 Web 應用程式管理員 (WAM) 的元件。所有的資訊均經由 WAM 進入和離開應用程式服務層。



非同步執行緒佇列 (Asynchronous Thread Queue, ATQ)

ATQ 提供可重複使用的執行緒的共用區 (pool),以處理客戶端的要求。整個作業排程是以作業系統的 Completion Port Logic 完成。



Web 應用程式管理員 (WAM)

WAM 是於 Web 服務上的 COM 元件層。Web 服務上有元件提供給 ISAPI DLL 同時提供多種服務,例如多 ISAPI DLL 的支援、損毀修復和程式隔離。WAM 登錄為 MTS/COM+ 套件/應用程式。



IIS 同處理序應用程式

如果 IIS 應用程式被組態為同處理序的執行方式 (在 IIS 5.0 有較低的應用程式保護),則它將在 Web 伺服器的 (inetinfo) 處理序空間中執行。由於如此可以避免代價高昂的交互程式調度,所以有極大的性能優勢。但缺點是如果其中有一個應用程式發生故障,也有可能使得整個 Web 伺服器無法運作。這會嚴重降低 Web 伺服器的穩定性和可用性。所有應用程式在 IIS 4.0 中均預設以同處理序執行,但在 IIS 5.0 則預設以共用跨處理序 (pooled out-of-process) 的方式執行 (中等應用程式保護)。



IIS 跨處理序應用程式

應用程式以跨處理序的方式執行,可避免單一應用程式發生錯誤時,使整個 inetinfo 處理序癱瘓。管理複雜的 Web 站台和裝載多個應用程式時,這種伺服器的保護是非常重要的。如果一個應用程式產生錯誤,它的處理序將自動結束,而不會影響到 inetinfo 處理序。



應用程式以跨處理序執行的另一個優點是您可以隨意載出應用程式,無需重新啟動 IIS。



應用程式以跨處理序執行時,可獲得個別的 ASP 背景工作執行緒 (Worker Thread)。這是很大的優點,因為每次在機器 (box) 中加入一顆處理器 (processor),跨處理序應用程式就可獲得額外的 10 個 ASP 背景工作執行緒。這是預設值;但藉由改變 ProcessorThreadMax 和 ASPProcessorThreadMax,可以影響此數值。我們將在後續的文章中詳細討論這個計數器。



跨處理序應用程式的主要缺點,是它們必須擁有自己的處理序空間,如此會影響整體效能。



並且,如果其中有應用程式被組態為以跨處理序的方式,在同一部伺服器上執行,就會使資源相當吃緊,並影響到伺服器的效能。



IIS 共用跨處理序 (Pooled Out-of-Process) 應用程式 (僅適用於 IIS 5.0)

IIS 5.0 有介於跨處理序和同處理序的新選項。所有 IIS 應用程式組態為共用跨處理序時,將在同一伺服器套件/應用程式下執行 (由 MTS/COM+ 建立)。



這個選項享有跨處理器的優點,因為共用應用程式有它們自己的處理序空間,其中一個的失敗不會影響到 Web 伺服器的可用性。除此之外,因為所有共用應用程式共享相同的處理序空間,它佔用的資源沒有跨處理程序選項多。



其缺點是因為所有的共用應用程式分享相同的處理序空間,如果其中有一個程式發生錯誤,就會影響到同一共用區的所有其他應用程式。



在 IIS 5.0 中,應用程式均預設以共用跨處理序執行。



[圖 2] 處理序隔離:性能 vs. 堅固性



為何偵錯是很重要的

偵錯是由軟體開發者用來找尋和修復程式中的錯誤的方法。即使在單元和整合測試中,已經盡力搜尋並修復各項錯誤,但仍有一些錯誤會存在產品中。即使有嚴格品管、包含各項單元和整合測試的製作流程,其產品仍有可能發生錯誤。

偵錯是 Web 應用程式開發者最頭疼的工作。不同於桌上型電腦的獨立應用程式,Web 應用程式可分佈在數種系統和經常結合數種不同的程式語言和技術。雖然經由小心的計劃可避免一些應用程式的錯誤,仍有一些錯誤是由複雜的元件互動所產生的副作用。追蹤這些問題通常需要使用各種偵錯和發展工具。


偵錯時,最重要的事是要記得您是在針對資料偵錯,而非程式碼。一個成功的偵錯程序,需要藉由詢問正確的問題,來獲得正確的資料。資料可為全域性或區域性。在偵錯時,人們最容易犯的錯誤是假設他們所看到的症狀是真正問題的原因

在進入偵錯的真正程序前,請先熟悉本文件中經常使用到、關於偵錯的用詞。

Attaching : Attaching 的意思是監視線上的處理序,以便於對它偵錯。

Checked/Debug Build : Checked/Debug Build 的意思是在處理序中包括有偵錯資訊的製成 (build)。

Free Build : Free Build 忽略所有偵錯資訊,使得處理序可以輕量化和更有效率。

Dumping : 當處理序產生例外狀況時,程式可將它從記憶體寫入硬碟成為一個檔案。Dumping 是處理序位址空間的一個快照 (snapshot)。它的大小約等於處理序所用的記憶體空間。偵錯人員可使用偵錯工具分析轉儲 (dump) 檔案,以決定處理序被轉儲 (dump) 時正在執行什麼作業。


設定偵錯環境

偵錯符號 (符號偵錯資訊)

符號提供一個方法,解決載入執行檔案的全域變數和函數名稱。符號是函數\API 名稱和全域變數對應到從 DLL的基底載入位址的位移。在元件的編輯程序過程中,連結器 (linker) 產生符號。元件內部有符號資訊 (內部符號) 比較不會把符號弄錯,使得工作非常容易。一般而言,為降低元件的大小,在生產期間載入元件時會去掉元件的符號,以降低記憶體的消耗,使得元件更具效率。

一個 DBG 檔案是以 SPLISTM 或 REBASE 從一個程式的影像分離出來的。DBG 檔案通常不包含程式碼檢視樣式的符號 (Code View-Style symbols);它不能用來做原始碼層級 (source-level) 的偵錯。

目前微軟 Visual C++ 和微軟 Visual Basic 能夠產生稱為程式資料庫 (Program Database :PDB) 的符號格式。偵錯程式可直接使用 PDB 檔案。

除了安裝自訂元件的符號之外,擁有微軟產品的符號遲早會有用的。

符號位置

下列站台指出符號的位置

Windows NT 4 Service Pack 6 符號

http://www.microsoft.com/ntserver/nts/downloads/recommended/sp6/debug/default.asp

Windows NT 4 Service Pack 5 符號

http://www.microsoft.com/ntserver/nts/downloads/recommended/sp5/debug/default.asp

Windows NT 4 Service Pack 3 符號:

ftp://ftp.microsoft.com/bussys/winnt/winnt-public/fixes/usa/nt40/ussp3/i386/nt4sym3i.exe

http://support.microsoft.com/download/support/mslfiles/Nt4sym3i.exe

Windows NT Option Pack 符號:

ftp://ftp.microsoft.com/bussys/IIS/iis-public/iis40/symbols/x86/symbols.cab

ftp://ftp.microsoft.com/bussys/IIS/iis-public/iis40/symbols/x86/install.inf

ftp://ftp.microsoft.com/bussys/IIS/iis-public/iis40/symbols/x86/install.exe

Windows NT Option QFE 更新符號:

ftp://ftp.microsoft.com/bussys/IIS/iis-public/fixes/usa/IISUPD/SYMBOLS/x86/IISUpdis.exe

Site Server 3.0 Service Pack 1 符號:

ftp://ftp.microsoft.com/bussys/sitesrv/sitesrv-public/fixes/usa/siteserver3/sp1/x86/symbols/ss3sp1db.exe

Site Server 3.0 Service Pack 2 符號:

ftp://ftp.microsoft.com/bussys/sitesrv/sitesrv-public/fixes/usa/siteserver3/sp2/x86/Symbols/ss3sp2debug.exe


微軟 Windows 2000® 伺服器符號:

http://www.microsoft.com/WINDOWS2000/downloads/otherdownloads/symbols/default.asp

這些也在 Windows 2000 客戶支援和診斷服務工具箱 CD。

一般使用的偵錯工具的概觀

CDB

CDB 是一運用控制台的偵錯工具,它在一已開啟的視窗內執行。因所需的記憶體非常少,所以非常有效率。它可用在 Windows NT 上偵錯 Win32 應用程式。


NTSD

NTSD 相似於 CDB,除了 NTSD 將另開啟一新的視窗並在其內執行,而非 CDB 在一已開啟視窗上執行。


WinDBG

WinDBG 是一輕薄短小受歡迎的 GUI 偵錯工具。它可使用在 Windows NT、Windows 95 和 Windows 98 上偵錯 WIN32 應用程式。目前在 Windows 2000 客戶服務診斷和支援工具箱 CD內有此程式。它可完成原始檔層級的偵錯,可讀 dump 檔案和具有傑出的支援符號的功能。但由於它是一個 GUI 偵錯工具,所以它的速度較 CDB 和 NTSD 慢。

IIS Exception Monitor 6.1

IIS Exception Monitor 是一輕薄短小和相當簡單使用的偵錯工具。使用這個偵錯工具可將發生問題的 DLL 隔離出來。它提供記憶體內程式的影像的對應文字檔案。它使用 CDB 去獲得資訊。有時候獲得的資訊量不夠。IIS Exception Monitor 會要求 Windows Scripting Host 執行。你可以從下列網址下載這個工具 使用 IIS 例外監視器 (Exception Monitor) 進行疑難排解 (英文)。

Exception Monitor 7.x

最新版 IIS Exception Monitor 是 DBGPLUS 套裝程式的一部份,DBGPLUS 包含所有在本文討論過的工具。「IIS」這幾個字已從名稱上移除,因為 Exception Monitor 不僅是針對 IIS 的問題偵錯,同時它也可偵錯其他程式。它使用 WinDBG 獲得與它連接的程式的資訊。雖然它的功能非常像前置處理器,但使用者介面已完全的改造並加入新的特色。Windows 2000 客戶診斷服務和支援工具箱 CD 也有這個程式。您也可以從下列網址下載這個工具 Windows 2000 客戶支援診斷器 (英文)。


注意: 在本文所舉的範例是基於 IIS Exception Monitor 6.1。然而,只需更動一小部份,它們一樣可適用於 Exception Monitor 7.x。

Developer Studio

Developer Studio 是一整合發展環境,它包含功能強大的偵錯工具。在發展程式的過程中是非常有用的。在原始程式階層偵錯使用它是非常棒的。它使用非常大的記憶體。在電腦上安裝 Developer Studio 改變許多系統檔案;因而,在一般使用的環境中不常使用它。程式開發者可依據他們的需求改變增益功能去自訂偵錯工具功能。


偵錯程序

驗證符號

偵錯程序中首先要驗證符號是否已正確安裝。CHECKSYM 工具可完成此項工作。例如,為了要驗證一個程式內所有的 DLL 執行時所安裝的符號是否可用,您可使用以下的命令:

checksym -p processname.exe -r -v -y c:\symbols

使用萬用字元 (*.*) 可代表一個目錄下的所有檔案。-v 參數 (switch) 指示工具去驗證這個元件的符號,而 -y 參數則指定符號檔案的路徑。

如需要關於 CHECKSYM 可以使用的參數和選項的資訊,請鍵入以下命令:

checksym -??

選擇偵錯工具

因為各種偵錯工具的功能變化很大,所以在選擇偵錯工具前,透徹了解工作的需要是非常重要的。偵錯的方案大體來說可分為三個標題:區域偵錯、遠端偵錯和使用者轉儲檔偵錯。

區域偵錯

當您在本機能夠複製一個問題時,選用區域偵錯是一好的主意;由於區域偵錯提供環境的完全控制,您可以快速的解決問題。在此方案中,選擇偵錯工具和進行設定是相當容易的。區域偵錯的缺點在於有時問題很難在區域中正確複製或重新產生 (即支援專家所說的「repro」)。

遠端偵錯

當偵錯工具和被偵錯程式並不是在同一台電腦上時,稱為「遠端偵錯」。
遠端偵錯可以透過偵錯工具代理程式 (agent) 連接到一遠端程式,或者是在遠端的機器上執行偵錯工具並在本機機器上以指令 (分享命令列方式) 遙控。就此範例而言,遠端系統執行代理程式,而偵錯工具在本機系統上執行;代理程式連接上被偵錯程式,讀取程式的記憶體,並將它們傳給本機電腦。用代理程式遠端偵錯的優點是設定簡單與快速。缺點是容易導致網路上的問題,此種問題有時會使遠端機器上的代理程式毀損。因為符號僅在本機電腦安裝,它們可能與遠端機器上的不一樣。結果是,遠端偵錯可能非常慢。


用共享命令列方式的遠端偵錯是使用 remote.exe 工具達到的,Windows 2000 客戶診斷服務和支援工具箱 CD上有這個程式。 Remote.exe 工具可當伺服程式和客戶端應用程式執行。以具名管道連接伺服端和客戶端。WSRemote.exe 是 remote.exe 工具的一個通訊端版本/類似版本。Remote.exe 允許 STDIN (標準輸入) 和 STDOUT (標準輸出) 的分享。在遠端機器上執行下列命令即可執行遠端伺服執行個體:

remote /s application pipename

您可以在本機機器上執行下列命令,即可以客戶端的模式執行 remote.exe:

remote /c machinename pipename

這樣的設定很可靠,不容易受到網路問題的影響。

對使用者轉儲檔的偵錯

當一例外狀況發生時,產生一個與程式的記憶體完全對映的檔案並轉儲到硬碟上。當系統產生例外狀況時,Windows NT 的 DrWatson 工具可產生使用者轉儲檔。另外有一稱為 User Mode Process Dump 的工具。您可以組態使用者轉儲工具,設定成監視特定程式的例外狀況。產生的使用者轉儲檔可在稍後以如 WinDbg 的偵錯工具觀看,並在有空時分析,而不一定要對執行中的程式偵錯。

使用偵錯工具

使用 NTSD

啟動 NTSD 偵錯工具時,使用者需要指定要連結的程式。使用 TLIST 或 PVIEWER,您可以取得已存在程式的 ID,然後鍵入「NTSD -p pid」,即可對此程式偵錯。NTSD 命令列使用下列的語法

NTSD [options] imagefile

imagefile 是被偵錯的影像的檔案名稱,而 options 是以下其中之一:

[表 1] NTSD 影像檔選項

選項

Description (描述)

-2

開啟應用於對字元模式應用程式偵錯的視窗。

-d

將輸出導向至偵錯端。

-g

自動地通過第一個中斷點。

-G

當子控制項結束時,使 NTSD 立即結束

-o

使能夠針對多個處理序同時進行偵錯。預設值僅對一個處理序,由偵錯工具直接繁衍。

-p

指定要進行偵錯的處理序的 IDFONT>


-v

產生冗長的輸出。

NTSD p 104

NTSD 也可以用來偵錯新啟動的程式。例如,NTSD notepad.exe 將啟動並連接到新的 notepad.exe 程式。
一旦連接到新的程式,您可以使用各種命令觀看堆疊 (stack),設定中斷點,轉儲記憶體 (dump memory)等等。

[表 2] 經常使用到的命令
命令意義~顯示執行緒的清單

KB

顯示對目前執行緒的堆疊追蹤狀況

~*KB

顯示所有執行緒的堆疊追蹤狀況

R

顯示目前框架的登錄輸出

U

反組譯程式碼,並顯示程序的名稱和位移 (offset)

D[type][<range>]

轉儲記憶體

BP[#] <address>

設定中斷點

BC[<bp>]

取消中斷點設定

BD[<bp>]

暫停中斷點功能

BE[<bp>]

恢復中斷點功能


BL[<bp>]

列出中斷點清單

使用 WinDBG

啟動 WinDBG。

在 [偵錯] 功能表中,按一下 [連結至處理序],選擇您要偵錯的程式,然後按一下 [選取]。

WinDBG 在命令視窗上列出有關於 inetinfo 程式的 DLL,並且也顯示 DLL 是否有載入符號。在這時候 inetinfo.exe 應用程式 (IIS) 偵錯程序已終止。想重新啟動,在命令視窗上鍵入 g。

在命令視窗中鍵入 ~*kb。

這樣將顯示程式的所有執行緒的堆疊。

想改變符號的路徑,在 [檢視] 功能表中,按一下 [選項]。 在 [Windows 偵錯工具選項] 對話方塊中,按一下 [符號] 頁籤,在 [偵錯符號搜尋路徑] 文字方塊中指定符號檔案的路徑,然後按一下 [確定]。

在命令視窗,鍵入 kb。

這將列出目前執行緒的堆疊。

另一個檢視目前執行緒的方法是在 [檢視] 功能表中按一下 [呼叫堆疊],檢視 [呼叫堆疊] 視窗。

在命令列的視窗,鍵入 lm。

這將列出在程式內的所有模組 (DLLs) 的名稱和它們的基底載入位址 (base loading addresses)。

終止時,在命令視窗鍵入 q。

使用 IIS Exception Monitor

在下列範例中,IIS Exception Monitor 是使用來連結摒偵錯 inetinfo (IIS) 程式。

按一下 [開始],指到 [程式集],指到 IIS Exception Monitor,然後按一下 IIS Exception Monitor。

在 Welcome 對話方塊裡面,按一下 Next。

如果您在 Check Symbols 對話方塊裡按一下 yes,精靈會尋找 IIS 所用到的檔案並比對 \%SYSTEMROOT%\Symbols\dll 目錄底下的檔案是否有相同者。您也可以按一下 Use Alternate Symbol Path for Exception Monitoring 來指定不同的符號路徑。

選擇 Yes。驗證已安裝的 IIS 符號。然後按一下 Next。

在 Verify Symbols 對話方塊裡,檢查系統中有哪些不相符的 DLL。您也可以選擇 Determine which symbol packages can be installed from Microsoft's Internet site 核取方塊,從 Microsoft 網站下載符號。後者會帶領您到下載網頁。在我們的範例裡,是假設已經安裝好了符號。然後按一下 Next。

注意: [驗證符號] 對話方塊利用 CHECKSYM.EXE 來得到符號的資訊。CHECKSYM.EXE 的位置在 C:\ixcptmon\bin 目錄底下。

在 Process Options 對話方塊裡有三個選項,其中 In-Process 選項意指在 inetinfo 處理序之中執行的 IIS 應用程式 (IIS 5.0 的選項「低」)。 Out-Of-Process 選項意指被設定在自己的/共用處理序空間之中執行的 IIS 應用程式 (IIS 5.0 的選項「高」與「中」),以及在 MTS/COM+ 底下當作伺服器套件執行的元件。 Other Process 選項意指其他在系統中執行的處理序。如果元件在 MTS 註冊為「 伺服器應用程式 / 套件」,它會在 dllhost.exe 處理序底下執行 (Windows NT 4.0 的 mtx.exe)。每個應用程式會有若干 dllhost.exe 執行個體。如果對元件進行偵錯,首先必須找到它是在 dllhost.exe 的哪一個執行個體底下執行,然後接上那個執行個體。 Other Process 選項有一個好用的功能,就是它會列出所有在 MTS/COM+ 註冊的元件,依照應用程式 / 套件排列,讓您很方便地找到正確的執行個體。

在我們的範例裡,選擇 In-Process 選項,然後按一下 Next。

接下來是 Session Options 對話方塊。如果選擇 Automatic,只要有例外狀況發生就會建立一個記錄檔。如果選擇 Manual,則會被要求提供通訊埠、使用者名稱與密碼,好讓支援工程師能以交談的方式為您偵錯。此選項主要是用於可獲得技術支援的狀況。如果選擇 Manual,一旦有例外狀況發生時,Web 服務會被暫停而不接受任何 Web 要求,直到它重新啟動或是監視工作階段取消為止。如果希望 IIS Exception Monitor 繼續監視,即使它已經產生了記錄檔而且重新啟動了處理序,選擇 Enable Recursive Mode 核取方塊。如果您希望當 [IIS Exception Monitor 發現例外狀況時給您一個 popup 訊息,或是您有 CDO 而且安裝了 SMTP 服務,請選擇 Notify Admin 核取方塊。您要給一個合法的 e-mail 位址,當例外狀況被偵測到的時候,您才能收到帶有附件檔案副檔名為 .dbl 的 e-mail。選擇 Schedule this session 核取方塊,您可以設定 Exception Monitor 在指定的時間或是在系統啟動時開始作動。不過這需要安裝 [Task Scheduler],若未安裝則此選項不能使用。

在我們的範例裡,選擇 Automatic 選項,然後按一下 Next。

按一下 Start Monitoring 對話方塊裡的 Run This Monitoring Session,然後按一下 Next。

Session Status 對話方塊會列出所有曾經被監視或現在監視中的處理序。最後,按一下 Finish。

您會看到一個標題列寫著「IIS_<Process ID>」的指令提示視窗。它是在監視 inetinfo.exe 處裡序。每當例外狀況發生, IIS Exception Monitor 就會產生記錄檔 (副檔名為 .dbl),重新啟動 IIS 服務,然後關閉指令提示視窗。

您可以在 \IXCPTMON\Logs 目錄底下找到記錄檔。

利用記錄檔鑑定問題

記錄瀏覽程式 Readlogs.exe 是在安裝 [IIS Exception Monitor] 的時候一起安裝的。您可以利用 Readlogs 來打開 .dbl 記錄檔。

[圖 3] Readlog 對話方塊

Readlogs 開啟記錄檔之後,它會顯示出導致例外狀況的執行緒的堆疊。如果已經安裝了正確的符號,Readlogs 會解析出函式名稱然後顯示在 Function 欄位,就像上圖所顯示的。函式名稱與 DLL 名稱有「!」隔開,例如,上圖函式 OutputDebugStringA 是屬於 KERNEL32 DLL。

您只要按一下分析器裡的 Fault Stack 按鈕就可以檢視錯誤執行緒堆疊。利用 << 與 >> 按鈕,您可以捲動堆疊清單。您也可以在 Choose a Command 下拉式清單中選擇一個指令執行。如果您不想看到 Microsoft 檔案,有一個選項可以 隱藏它們,這樣能快速地辨識出協力廠商的 DLL。除了列出堆疊,記錄檔也包含有關已載入的 DLL 或模組、鎖定 (lock) 及擁有它的執行緒 ID、與偵測到的錯務的資訊。

按一下 DLLs 按鈕,會列出在處理序中所有已載入的 DLL。

Errors 按鈕會列出處理序執行過程中所有發生的錯誤與警告。您也可以自己設定 IIS Exception Monitor 去捕捉某些錯務。

按一下 Locks 按鈕會列出鎖定及擁有它們的執行緒的 ID 的清單。每當執行緒要獨占地存取資源時,它會要求鎖定該資源。若有多於一個執行緒鎖定某資源,並等待其他鎖定被解除,此現象稱為「死結」(Deadlock)。您可以檢查鎖定及擁有它們的執行緒的清單,以便找出可能會造成死結的潛在來源。

按一下 P.T.C. (Prior to Crash) 按鈕會列出記錄檔內處理序中斷之前的最後 20 行。

您也可以利用 Report 按鈕將所有資訊以報表格式複製一份放入剪貼簿。

Sys Info 按鈕會顯示一些系統相關的資訊,偵錯時用的到。

Config 按鈕可讓您依需求自訂記錄檔。

使用「使用者模式處理序轉儲工具」

「使用者模式處理序轉儲」工具的功用是,當例外狀況發生時,用它來接上特定的處理序,然候把處理序記憶體空間轉儲到硬碟。首先,必須執行位於 C:\Program Files\Debuggers\bin\userdump\ 的 setup.exe,以便設定「使用者模式處理序轉儲」服務。「使用者模式處理序轉儲」 設定程式是 DBGPLUS 套件的一部分。

在 Welcome 對話方塊裡面,按一下 Next。

在 Confirmation 對話方塊裡面,按一下 Finish。

安裝程式會安裝一個控制台圖示名為 Process Dump,可用來設定「使用者轉儲」服務。

快按兩次 Process Dump 圖示會帶出 User Mode Process Dump Configuration 對話方塊。

按一下 New,然候輸入希望被使用者轉儲工具監視的應用程式名稱。

您可以建立一些規則用來捕捉特定的例外狀況。請按一下 Rules。

被監視中的處理序如果發生了例外狀況,它會把處理序記憶體空間轉儲到硬碟。使用者模式處理序轉儲工具 與 IIS 例外狀況監視器 不同,前者在轉儲結束之後不會重新啟動 IIS 伺服器。

WinDBG 偵錯工具可用來開啟前述所產生的使用者轉儲,並加以分析以便找出處理序毀損的原因:

啟動 WinDBG。在 File 功能表中按一下 Open Crash Dump,然後選擇毀損轉儲檔案。

在指令視窗中鍵入 g (go),開始偵錯程序。

如果要檢視錯誤堆疊,鍵入 kv 。

對哪一個處理序進行偵錯?

辨識出哪一個處理序要進行偵錯並不容易。如先前「網際網路資訊服務架構」所述,元件與 IIS 應用程式的搭配各異其趣,底下的表格說明了,依據元件型別與 IIS 組態選擇不同的處理序。

[表 3] 元件型別與 IIS 組態

元件型別

同處理序 IIS 應用程式

跨處理序 IIS 應用程式

暫存跨處理序 IIS 應用程式

(IIS 5.0 才有)

屬於程式庫套件 / 應用程式的元件或是不屬於 MTS/COM+ 的元件

接上 inetinfo 處理序

接上 IIS 應用程式所屬伺服器套件 / 應用程式的 MTX/DLLHOST 執行個體


伺服器套件 / 應用程式的元件

接上元件所屬伺服器套件 / 應用程式的 MTX/DLLHOST 執行個體


若偵錯的對象是,屬於 MTS/COMD+ 的元件或 IIS 應用程式,且安裝成為伺服器套件 / 應用程式,事情就變得棘手。因為一個系統可能會有好幾個套件 / 應用程式同時執行,所以它們會有各自的 MTX.exe 或 DLLHost.exe。哪一個才是您的呢?第一件事就是那個載入偵錯對象元件的處理序的 PID (process identifier)。您可以利用 IIS 例外狀況監視器獲得資訊,請選擇 [Process Options] 頁中的 [Out-Of-Process] 選項。

您會看到 [Select Out-Of-Process Application] 頁面,在那裡有一份應用程式 / 套件名稱的清單,這樣就比較容易找到您要的 PID。

一般問題之偵錯

對於分散式 Web 應用程式最常發生的問題有:

ASP 0115—違規存取 (ASP 0115—access violation)

ASP 伺服器太忙錯誤 (ASP server too busy error)

100% CPU 問題 (100 percent CPU problem)

在本節中,我們會分析問題可能的起因,並討論如何偵錯與找到造成錯誤的程式碼。


ASP 0115—違規存取 (ASP 0115—Access Violation)

違規存取的主因是堆積 (heap) 與堆疊 (stack) 破壞。

存取不屬於自己的記憶體空間,就是違規存取。

例如:

char* pszTemp = (char*) malloc(strlen("BOMB THIS"));

strcpy(pszTemp,"BOMB THIS");

此例中,使用者取得 9 位元組記憶體空間,但未加上 NULL 終端子 ("\0")。當複製字串到此記憶體位址時就會造成錯誤,因為函式 strcpy 會存取超過配置的記憶體空間。


另一個案例是企圖存取無效的記憶體位置。

例如:
FunctionA()

{

m_pAV = NULL;

FunctionB(m_pAV);

}

FunctionB(CAccessViolate* pAV)

{

pAV->BombThis();

}

這個範例裡,函式 B 使用 pAV 指標之前未檢查其是否有效,造成了違規存取。

大部分的違規存取錯誤發生的時機是,當 ASP 網頁企圖存取 會做錯事的元件。簡單地說,假設您有一個程式庫套件的元件,您要存取的 ASP 網頁用到這個元件,此 ASP 網頁可能傳回以下的訊息:

error 'ASP 0115'

Unexpected error

/<Web Server Name>/<ASP file name>.asp

A trappable error occurred in an external object. The script cannot continue running.

此錯誤訊息說,在 ASP 網頁中有一個錯誤,它是由一個發生在外部物件的例外狀況所引起。這意謂著 ASP 網頁內某個元件出錯了。您可以用隔離法找出禍源,先移除 ASP 網頁內所有元件參考,然後一次一個加回去。

如果隔離法變得冗長乏味,或錯誤訊息不夠清楚而無法得知 ASP 網頁名稱,您可以利用 WinDBG、使用者模式處理序轉儲、或是 IIS 例外狀況監視器,接上 inetinfo 然後對它進行偵錯。

找出造成違規存取的程式碼

假設您使用「使用者模式處理序轉儲」工具來接上 inetinfo 處理序,並且建立了轉儲檔案。讓我們用 WinDBG 來檢視轉儲檔案,看看是發生了甚麼事?

在 WinDBG 中開啟毀損轉儲,按一下 View 功能表中的 Call Stack.

[圖 4] 顯示著堆疊的 [Windows Debugger] 對話方塊

即使上圖堆疊中最上面的函式是屬於 KERNEL32 DLL,並不代表出錯的程式碼必定在該內函式。而大部分的狀況也不是如此。下一步是找出標準的 Windows 系統元件以外的元件,並了解毀損中斷時它們在做甚麼?上圖的堆疊由下向上第 8 行與第 7 行表示 ASP 使用 Microsoft VBScript 引擎來啟動元件,第 6 行與第 5 行表示 VBScript 引擎利用 IDispatch 介面方法來叫用元件內部的方法 (CRASHATLAPP。由於用到 IDispatch 介面,自然 OLEAUT32.dll 便出現在畫面中,第 4 行與第 3 行說明了這件事。第 2 行顯示 BlowOff 方法被叫用,接著它叫用了 KERNEL32 dll 內的 OutputDebugString API。我們可以安心地假設標準 Windows 元件 KERNEL32 dll、OLEAUT32.dll、與 VBScript 引擎無關 (以問題隔離法判斷而言)。所以剩下的唯一的,非 Windows 元件嫌疑犯就是 CRASHATLAPP。

CRASHATLAPP 的 BlowOff 方法叫用了 OutputDebugString API。我們可以在指令視窗中輸入 kb,檢查 BlowOff 傳遞給 OutputDebugString 的參數。


BlowOff 方法傳遞了值為 NULL 的參數給 KERNEL32 DLL 的 OutputDebugString 方法。最好是看看為什麼 BlowOff 方法會傳遞 NULL 值。如果您有 CRASHATLAPP 元件的原始程式碼,您可以在堆疊的第 2 行快速按兩下。


[圖 5] 顯示著堆疊的 [Windows 偵錯工具] 對話方塊

方法 BlowOff 的程式碼出現了!

[圖 6] 顯示著 BlowOff 程式碼的 [Windows 偵錯工具] 對話方塊

此程式碼明白地說明了,值為 NULL 的參數傳進了 OutputDebugString。


這種錯誤應該不會出現在程式碼,此例的目的是提供一個概念,關於違規存取錯誤的偵錯過程。

「ASP 伺服器太忙」錯誤

[ASP 伺服器太忙] 錯誤一般是來自 ASP 請求佇列滿載。當 IIS Web 伺服器負載過高或是正在等待阻塞的執行緒,就會產生大量的佇列。此情況通常發生在,IIS Web 伺服器在等待元件,而該元件被叫用的頻率超過本身的能力。所有湧進的請求被放置在 ASP 請求佇列,然後依照先到先做順序處理。如果阻塞只有很短時間,佇列機制終能解決問題,服務得以及時開始。但是,如果阻塞延續很久,佇列中的請求一直累積,最高限制是由 ASPRequestQueueMax 中繼資料 (Metadata) 所設定,預設是 3000。如果佇列中的請求量低於 3000,發出第 2999 個請求的使用者會看到一個沙漏,表示該請求是在佇列中等待。即使是在此刻,如果佇列能儘快清空,所請求的服務仍能被處理。相反地,如果佇列請求量達到了 ASPRequestQueueMax 而且接著又有新的請求到來,IIS 伺服器就會傳回 [ASP 伺服器太忙碌] 錯誤。
ASPProcessorThreadMax 與 ASPRequestQueueMax 設定

ASPProcessorThreadMax 與 ASPRequestQueueMax 中繼資料的 設定值對於網站的效能影響甚鉅。ASPProcessorThreadMax 指定一個處理器所能服務的執行緒數量的最大值。ASPRequestQueueMax 指定佇列請求量的最大值。這兩個參數可利用下列指令改變之:

adsutil.vbs set w3svc/AspProcessorThreadMax NewValue

adsutil.vbs set w3svc/AspRequestQueueMax 新值

就好的 script 而言,ASPProcessorThreadMax 的值應該要小。調整 ASPProcessorThreadMax 的目標是使得,在尖峰負載時處理器的使用率高於百分之 50。

由於各網站的硬體配置差異很大,所以要預測這些參數的最佳值並不容易。您應該利用性能監視器來監視關鍵的統計數字,以便決定這些參數值。這些統計數字應該包括:

處理器時間:處理器時間百分比

ASP:每秒請求數量,遭拒請求數量,佇列請求數量

您可以監視網站尖峰負載時刻的這些數值。對於典型的 high-volume 網站,您可以觀察到佇列請求量會呈現上上下下變化。如果處理器使用率低,而佇列請求量不會變大,這表示網站的能力高於實際所需。如果佇列請求量高高低低,而處理器使用率低於百分之50 percent,這表示有一些請求阻塞了,此時若調高執行序數值會有所幫助。如果調高執行序數值之後,佇列請求量反而變高,而處理器使用率也變低,這表示有嚴重的阻塞問題。典型的阻塞問題,可能是由於資料庫的 SQL 請求耗時太久所導致。因為,增加執行序數量會讓更多的請求進來,結果給了資料庫更多壓力,造成請求反映時間加長。 欲求得較佳的 ASPRequestQueueMax 數值,可以先設定可接受的最大反映時間,計算在這段時間內的佇列請求量,然後設定 ASPRequestQueueMax 為比這個佇列請求量低一點的數值。

一個偵錯範例

已詳細處理 ASPProcessorThreadMax and ASPRequestQueueMax 參數,試著模擬ASP Server Too Busy 錯誤和嘗試偵錯執行緒被凍結 (blocking) 的元件並找出原因。假定您有一 個ASP 網頁,它呼叫一被凍結的元件。

為了模擬問題,設定 ASPRequestQueueMax 參數為 20 藉著下列的命令 :

cscript c:\inetpub\AdminScripts\adsutil.vbs SET w3svc/ASPRequestQueueMax 20

啟動性能監視器:

按一下 [開始],指到 [程式集],指到 Administrative Tools,然後按一下 Performance Monitor。在圖表上按一下右鍵,然後按一下 Add Counters。

在 Add Counters 對話方塊中,從 Performance Object 清單中選擇 Active Server Pages。

從 Select counters from list,選擇 Requests Executing 和 Requests Queued。按一下 Add,然後按一下 Close。

假定您在已被凍結的 ASP 程式碼上呼叫元件。

加入這些計數器,注視計數器的值。您可以觀察到當要求佇列計數器達到ASPRequestQueueMax數值 (20) 伺服器回應ASP Server Too Busy error。

[圖 7] 性能監視器顯示要求回應計數器數值

偵錯 inetinfo 程式以決定哪一個執行緒凍結和發生原因,啟動 WinDBG 並連結到 inetinfo 程式。執行緒凍結的最常發生原因是死結 (deadlock)。您可試著去確認鎖定計數大於零的關鍵區段和它本身擁有的執行緒 ID。這個執行緒是罪魁禍首。一旦您有了執行緒 ID,您可以偵錯這個執行緒堆疊以找出哪一個特別的方法被凍結住。為完成這個動作您可在命令視窗上鍵入下列命令:

!locks



這將列出鎖定計數大於零的執行緒。輸出會像這樣:



CritSec ?g_cs@@3U_RTL_CRITICAL_SECTION@@A+0 at 100355A0

LockCount 24

RecursionCount 1

OwningThread 6e8

EntryCount 18

ContentionCount 18

*** Locked





尋找鎖定計數大於零的關鍵區段並注意它擁有的執行緒 ID。



通常因為用於 ntdll.dll 的符號沒有正確的排好,有時候 !locks 命令並不能提供需求的資訊。在這個範例中,您可使用下列簡陋但有效的方法。



在命令視窗,鍵入 ~*kb,顯示所有執行緒的堆疊。找出包含 NTDLL!RtlEnterCriticalSection 的執行緒堆疊。一旦您確認出有此項目的執行緒,注意在線上的 param1 的值包含 NTDLL!RtlEnterCriticalSection。此值是關鍵區段物件傳遞到 EnterCriticalSection API。使用此值,在命令視窗鍵入下列命令:



!Critsec 100355A0



使用上述兩個方法之一,您將可確認鎖定計數大於零的執行緒 ID。將十六進位的執行緒 ID 轉換成十進位。



檢查執行緒和確認凍結執行緒的方法。在 Debug 功能表中按一下 Threads。



在 Threads 對話方塊中,按一下在先前步驟您已確認的執行緒 ID,並按一下 Select。



在 View 功能表中,按一下 Call Stack。這將顯示執行緒的堆疊。如我們在先前的範例所做的 (Access Violation),開始對堆疊偵錯。



100% CPU 問題

100% CPU 問題發生在當一個執行緒消耗所有的 CPU 處理時間。一個可能的原因是程式迴圈獨占 CPU 資源。程式監視器是檢修 100% CPU 問題的完美工具。首先我們必須產生一性能監視器記錄檔。



準備記錄檔



啟動性能監視器:



按一下 [開始],指到 [程式集],指到 Administrative Tools,然後按一下 Performance Monitor。



在 Counter Logs上按一下右鍵,然後按一下 New Log Settings。為記錄檔命名並按一下 [確定]。



在 [General] 頁籤上,按一下 Add 將計數器加入記錄檔。

加入下列計數器:



ASP:所有的計數器



Memory:所有的計數器



Process:所有計數器和所有執行個體



Processor:所有計數器和所有執行個體



Thread:所有計數器和所有執行個體



Web service:所有計數器和所有執行個體



加入所有計數計之後,將 Sampling Interval 更改為 every 1 second,然後按一下 [確定]。



現在您就可以開始輸入資料。在記錄檔名稱上按一下右鍵,然後按一下 [開始]。確保在處理器使用迅速上升至 100%的時間內,記錄檔抓住所有的資料。啟動 WinDBG 並連結到 inetinfo 程式。一旦處理器的使用值回復到一般水準,您可以停止記錄並藉著右鍵按一下 log name 並按一下 Stop。



檢查記錄檔

現在我們已產生記錄檔,我們可開始嚴密的檢查它以查出使用大部分 CPU 時間的程式,程式內吃掉大部分 CPU 時間的執行緒和為何它會這樣做。



第一個步驟是確認哪一個程式使用大部分 CPU 時間。開啟一記錄檔案,按一下 System Monitor 在控制台的根目錄下的檔案夾。在細節窗格 (detail pane) 中,在圖表上按一下右鍵,然後按一下 Properties。在 System Monitor Properties 中,按一下 Source 頁籤。選擇 Log file 並瀏覽 去選擇您剛產生的記錄檔。



在圖表上按一下右鍵,然後按一下 Add Counters在 Add Counters 對話方塊中,從 Performance object 清單中選擇 Process。選擇 Select counters from list,並從清單中選擇 %Processor Time。選擇 All instances。選擇 Add,然後按一下 Close。



這給予我們一張列出所有的程式和它們的 CPU使用時間的清單。現在您必須找出哪一個程式造成 100% CPU 問題。



請確定 Highlight 工具鈕 (球狀的圖示) 已按下。現在您可從頭到尾捲動計數器,除了最接近 100% 那一項外刪除所有其它項。確定您選擇的計數器是洽當的;例如,如果您對此 100% CPU 使用程式偵錯,您將可能看起來像在 inetinfo 或其他跨處理序 COM 應用程式/封裝 (MTX.EXE/DLLHOST.EXE) or IIS 應用程式。



一旦您已在程式層級隔離問題,您可集中心力在解決造成 100% 問題時間內,在程式內部活動的執行緒並嘗試隔離造成問題的執行緒。為了這個目的,加入更多的顯示程式內執行緒使用 CPU 時間的計數器。舉例而言,對 inetinfo 程式下所有執行緒加入計數器。在圖表上按一下右鍵,然後按一下 Add Counters。在 Add Counters 對話方塊中,從 Performance object 清單中選擇 Thread。選擇 Select counters from list,並從清單中選擇 %Processor Time。選擇 Select instances from list,並選擇以 inetinfo/* 開頭的所有執行個體。按一下 Add,然後按一下 Close。



這將在圖上顯示 inetinfo 程式內的所有執行緒的 CPU 使用時間。



現在您可從頭到尾捲動計數器,除了最接近 100% 那一項外刪除所有其它項。這將帶我們到最接近造成問題的執行緒。



[圖 8] 性能監視器顯示 CPU 使用時間計數器



我們留下執行個體 ID 34的唯一的執行緒,它使用最多 CPU 時間。現在我們必須找出此執行緒的執行緒 ID,在 WinDBG 內查詢它並對它偵錯。



為了要尋找執行緒 ID,在圖表上按一下右鍵,然後按一下 Add Counters。在 Add Counters 對話方塊中,從 Performance object 清單中選擇 Thread 。選擇 Select counters from list,並從清單中選擇 ID Thread。選擇 Select instances from list],並選擇執行個體 inetinfo/34。按一下 Add,然後按一下 Close。



這將給我們造成問題的執行緒的執行緒 ID。選擇 ID Thread 計數器。注意計數器的最後值 (Last)、最大值、最小值和平均值。一般而言,這四個值是相等的。注意此值 (本例中為 746) 和轉換到 WinDBG 應用程式。



[圖 9] 性能對話方塊顯示 ID 執行緒計數器



在 WinDBG 的 View 功能表中,按一下 Threads。這將顯示當遭遇 100% CPU 問題時,在 inetinfo 程式內正在執行的執行緒的清單。找出您已從性能監視器上注意到的執行緒 ID 數值。如果您在清單上找出它,按一下它,然後按一下 Select。按一下 [確定]。



在 View 功能表中,按一下 Call Stack。 這將顯示造成問題的執行緒的堆疊。這些堆疊隔離問題方法。一旦我們找出方法,我們可回到原始碼並找出哪一行程式造成問題。



結論

您可使用 IIS Exception Monitor,WinDBG,使用者模式程式轉儲工具和性能監視器去有效的解決在分散式 Web 應用程式所遭遇的大部分一般性問題。這些工具程式對一問題不必然有所有解答和解決方案,但它們可引導您一個最終可解決問題的方向。



© 2000 Microsoft Corporation. All rights reserved.
本篇文章發表於2001-01-15 00:00
別忘捐VP感謝幫助你的人 新手會員瞧一瞧
目前尚無任何回覆
   

回覆
如要回應,請先登入.