故障診斷學習工具

CloudSpace發表於2010-08-30
隋 鵬飛 (suipf@cn.ibm.com), 軟體工程師, IBM
李 昊 (nicohaoli@cn.ibm.com), 軟體工程師, IBM
張 濤 (jordanzt@hotmail.com), 軟體工程師, IBM

簡介: 本文介紹了 Problem Diagnostics Lab Toolkit 的使用方法和技巧。

引言

WebSphere 應用服務的故障診斷一直是客戶最為關心的問題之一。為了對 WebSphere 應用伺服器進行快速的問題診斷, IBM 提供了廣泛的支援,包括幫助客戶進行快速的資料採集,指導客戶進行資料分析以及提供大量的參考手冊和技術文件等,這些努力大大減輕了問題診斷的工作量。然而,問題的解決最終還是要依賴於使用者對具體問題的分析。這就像是醫生給病人看病,任何先進的醫療器械和理論知識都代替不了醫生的診斷,為了給病人治病,醫生不僅要有紮實的理論基礎,還要有豐富的實踐經驗,對 WebSphere 應用伺服器進行問題診斷也是一樣。那麼怎樣才能獲得故障診斷相關的經驗呢? 在實踐中學習當然是我們獲得經驗的最佳途徑,但僅僅依靠在工作中解決實際問題來獲得經驗將是一個漫長的過程,並且通常都需要付出一定的代價。與之相比,另一種主動的方式 – 實驗 – 要划算的多,通過實驗的方式獲得經驗不僅可以幫助我們在問題發生時進行快速的診斷,而且還有可能因為這些已有的經驗避免一些問題的發生。本文將介紹一種進行問題診斷的實驗工具 – Problem Diagnostics Lab Toolkit(http://www.alphaworks.ibm.com/tech/pdtk), 它可以幫我們快速重現問題,並且為問題的定位和診斷提供指導。

Problem Diagnostics Lab Toolkit (PDLT) 是一個安裝在 WebSphere Application Server 上的企業應用程式,與普通的應用程式相比,它的特點是可以動態的修改需要執行 Java 程式碼,這些 Java 程式碼是通過應用程式寫到 jsp 中的,所以當使用者在瀏覽器中修改相應的程式碼以後,不需要重起應用程式,就能立即執行新的程式碼。包含 Java 程式碼的 jsp 可以通過 "動作皮膚" 中的按鈕來呼叫的 , 這樣無論是修改還是執行 Java 程式碼都非常的方便。監控模組可以幫助我們察看系統當前的狀態,包括執行緒狀態、記憶體和 CPU 使用情況,以及不同請求的響應時間等。 PDLT 還包含一個內建的壓力引擎,當我們需要重現一些在壓力條件下才能重現的問題時,可以設定模擬的客戶端的個數、每個客戶端的請求數以及兩次請求之間的時間間隔。下圖展示了 PDLT 的主要功能模組:


圖 1. PDLT 的功能模組
圖 1. PDLT 的功能模組

管理模組: 主要負責實驗案例的管理和維護。

程式碼編輯器: 動態修改 Java 程式碼,修改後的 Java 程式碼可以立即被執行,而不需要重新部署應用程式。

監視模組: 監視應用程式的執行狀態,比如記憶體、CPU、執行緒和平均響應時間等。

壓力引擎: 模擬多客戶端對 Java 程式碼(JSP) 進行訪問。

案例庫: 存放的案例。

Problem Diagnostics Lab Toolkit 的安裝

PDLT 是一個的企業應用程式,使用者需要將其部署在 WebSphere 的單 Server 環境中,部署過程中只需要接受預設的配置即可,不需要配置額外的資源和環境變數。

具體安裝步驟如下:

1) 從 http://www.alphaworks.ibm.com/tech/pdtk/download 下載 PDLT。

2) 啟動 WAS,並開啟 admin console 。

3) 選擇“應用程式”->“安裝新的應用程式”。

4) 選擇壓縮包中的 ear 檔案。

5) 全部使用預設選項安裝該 ear 。

安裝完成後,使用者可以通過瀏覽器訪問 http://hostname:port/LabToolkit,其介面如下圖所示


圖 2. PDLT 的介面
圖 2. PDLT 的介面

問題 (Problem): 是對實驗場景的分類,每一類問題可以通過多個場景來進行重現。

場景 (Scenario): 用於重現問題的實驗場景,每一個場景包含一個嚮導和一個動作皮膚。

嚮導(Wizard): 指導使用者完成場景中的步驟。

動作皮膚 (Action Pane): 包括一系列動作按鈕,每個動作按鈕對應後臺的一個 jsp 檔案,使用者可以執行或者修改這個 jsp 檔案中的程式碼。

監視器 (Monitor): 使用者監控系統的狀態。

訊息皮膚 (Message Console): 用於顯示執行過程中的日誌訊息。

瞭解試驗場景

每一個試驗場景代表一種可能發生問題的情況,使用者首先選擇一個問題類別,然後在該類別中選擇一個試驗場景,這裡我們以死鎖問題為例,選擇“ThreadHang" --&gt "DeadLock",

這時我們可以看到這個實驗場景的嚮導(圖 3)和動作皮膚(右側),嚮導主要分為四個步驟 :

簡介 (Instruction): 主要介紹該場景所要重現的問題。

問題重現 (Reproduction):介紹重現該場景的步驟和注意事項。

分析問題 (Investigation): 指導使用者進行問題診斷。

總結 (Summary): 問題總結。

通過滑鼠右鍵彈出的上下文選單,使用者可以增加或者刪除嚮導的步驟或者對嚮導中的內容進行修改。


圖 3. 嚮導部分
圖 3. 嚮導部分

圖 4. 動作皮膚
圖 4. 動作皮膚

檢視程式碼

"Dead Lock" 的動作皮膚中有兩個動作按鈕,"DeadLock Jsp" 按鈕和 "Correct Jsp"。

用滑鼠右鍵單擊 "DeadLock Jsp" 按鈕,在快捷選單中選擇 "Edit Action Button" ,在彈出的 Java 編輯器中我們可以檢視或者編輯這個按鈕所執行的 Java 程式碼,其程式碼如下:


清單 1.“DeadLock Jsp” 按鈕執行的 Java 程式碼

				 
 
 synchronized (lock1) { // lock1 is defined in the "Methods and Static Variables" tab 
      Thread.sleep(5000); 
      ThreadMonitor.registerThreadStatus("blocked"); 
      //It will be blocked here if the thread can not get the lock2 
      synchronized (lock2) { 
  ThreadMonitor.registerThreadStatus("running"); 
  //It will continue to run if the thread can get the lock2 
 } 
 } 
   synchronized (lock2) { // lock2 is defined in the "Methods and Static Variables" tab 
      Thread.sleep(5000); 
      ThreadMonitor.registerThreadStatus("blocked");
       //It will be blocked here if the thread can not get the lock1 
      synchronized (lock1) { 
   ThreadMonitor.registerThreadStatus("running"); 
   //It will continue to run if the thread can get the lock1 
 } 
 } 


圖 5. 程式碼編輯器
圖 5. 程式碼編輯器

這段程式碼主要完成如下操作:

  1. 獲取一個全域性鎖 locker1

    (Sleep(5000))

  2. 獲取一個全域性鎖 locker2
  3. 釋放全域性鎖 locker2
  4. 釋放全域性鎖 locker1
  5. 獲取一個全域性鎖 locker2

    (Sleep(5000))

  6. 獲取一個全域性鎖 locker1
  7. 釋放全域性鎖 locker1
  8. 釋放全域性鎖 locker2

這段程式碼在單執行緒執行時可以很順利的執行,但在多執行緒併發條件下卻很容易發生死鎖:當兩個不同的執行緒分別執行到第 2 步和第 6 步之前時 , 其中的一個執行緒已經佔用了 locker1, 它需要等待 locker2, 而另一個執行緒則剛好相反。 因此如果我們模擬多使用者併發執行這段程式碼,就能夠重現死鎖問題。

模擬多使用者併發

PDLT 內建了壓力引擎,可以方便的模擬多使用者併發呼叫的場景,如下圖所示,展開動作皮膚下方的 Advanced Settings"皮膚,可以設定模擬客戶端的個數,傳送請求總數以及請求之間的間隔時間。這裡我們將使用者數設定為 2。返回動作皮膚並單擊"DeadLock Jsp" 按鈕,壓力引擎會同時傳送 2 個請求來呼叫"DeadLock Jsp" 按鈕所對應 jsp,從而執行上面我們所編輯的程式碼。


圖 6. 設定壓力引擎
圖 6. 設定壓力引擎

監控執行緒執行情況

展開“Monitors”皮膚,可以看到 3 個 tab 頁, 分別用來監控執行緒資訊、記憶體和 cpu 使用情況以及請求的平均響應時間。 這裡我們主要關心執行緒的執行情況,從執行緒資訊頁我們可以看到剛剛執行的兩個新的執行緒都處於“block”狀態,並且這種狀態會一直持續下去。 這就是死鎖,它不但導致發生死鎖的兩個執行緒無法正常結束,這兩個執行緒所佔用的資源還會影響到更多的執行緒, 當執行緒總數超過 Web Container 執行緒池的最大執行緒數時,則所有的請求都會被拒絕。


圖 7. 監控執行情況
圖 7. 監控執行情況

察看正確程式碼

用滑鼠右鍵單擊 "Correct Jsp" 按鈕,在快捷選單中選擇 "Edit Action Button",在彈出的 Java 編輯器中我們可以檢視或者編輯這個按鈕所執行的 Java 程式碼,其程式碼如下:


清單 2.“Correct Jsp” 按鈕執行的 Java 程式碼

				 
 synchronized (lock1) { // lock1 is defined in the "Methods and Static Variables" tab 
      Thread.sleep(5000); 
      ThreadMonitor.registerThreadStatus("blocked"); 
      synchronized (lock2) { 
  ThreadMonitor.registerThreadStatus("running"); 
 } 
 } 
synchronized (lock1) { // lock2 is defined in the "Methods and Static Variables" tab 
      Thread.sleep(5000); 
      ThreadMonitor.registerThreadStatus("blocked"); 
      synchronized (lock2) { 
   ThreadMonitor.registerThreadStatus("running"); 
 } 
 } 

這段程式碼主要完成如下操作:

  1. 獲取一個全域性鎖 locker1

    (Sleep(5000))

  2. 獲取一個全域性鎖 locker2
  3. 釋放全域性鎖 locker2
  4. 釋放全域性鎖 locker1
  5. 獲取一個全域性鎖 locker1

    (Sleep(5000))

  6. 獲取一個全域性鎖 locker2
  7. 釋放全域性鎖 locker2
  8. 釋放全域性鎖 locker1

與 “DeadLock Jsp” 相比,我們在這段程式碼中僅僅調整了一下 locker1 和 locker2 的巢狀順序,但當我們用兩個(或者更多)客戶端同時發出請求時,所有執行緒都能夠正常結束。

因此,在多執行緒環境下,一定要保證鎖的巢狀順序是一致的,這樣才能避免死鎖的發生。

 

結束語

除了死鎖問題之外,PDLT 還包含很多其他常見的典型問題,比如 Java 記憶體溢位、本地記憶體溢位、CPU 使用率過高、連線洩漏等。 對於這些常見的錯誤,使用者最好在問題發生之前就對它進行了解,瞭解這些問題發生時系統的症狀,以及如何診斷和解決這類問題。這樣當真正的問題到來的時候才能迅速做出判斷,從而減少由於系統中斷而帶來的損失。

原文連結:http://www.ibm.com/developerworks/cn/websphere/library/techarticles/1007_suipf_wasdiagnosetool/1007_suipf_wasdiagnosetool.html

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/14789789/viewspace-672135/,如需轉載,請註明出處,否則將追究法律責任。

相關文章