WebObjects/Web 應用程式/部署/除錯凍結的已部署例項
本文由 Andrew Lindesay (http://www.lindesay.co.nz) 撰寫於 2005 年 2 月左右。它最初以 LaTeX PDF 格式出現,並已轉錄到此維基。您自行承擔使用本文件中包含的資訊的風險。如果您認為維基標記轉換過程中可能存在錯誤,請聯絡作者。
此處討論的材料已在 MacOS-X Server 上的 WebObjects 5 和 Java 1.4 中使用。它可能適用於或不適用於舊版或新版 WebObjects 或 Java。強烈建議您首先在非生產伺服器上對其進行測試。請注意,如果您的系統在網際網路上公開,此技術可能存在安全問題。
Java 提供了 WebObjects 5 應用程式執行的基礎。Java 有其優缺點。一個優點是輕鬆實現軟體系統的多執行緒操作。這通常可以用來充分利用您的硬體資產,但也意味著您需要確保對事物進行鎖定,以防止兩個執行緒同時訪問同一事物。鎖定失敗會導致資料損壞,或者當一個執行緒由於某種原因無法釋放鎖定時,其他執行緒可能會無限期地等待。
當多執行緒系統中“出現問題”時,獲得可靠的診斷可能很困難。問題通常很難重現,可能非常零星,並且通常很少見。可能需要一系列非常具體的事件,並且需要非常精確的時間才能重現問題,並且這些問題通常難以在“實驗室”中重現。在生產環境中,此類錯誤可能會導致應用程式例項“凍結”,並最終使即時系統無響應。
無限迴圈等更常見的錯誤也可能潛入生產系統,並導致例項無響應。
本文重點介紹了一種技術,該技術可用於確定生產環境中凍結例項內部發生了什麼。特別是,此技術將為您獲取例項執行緒的堆疊跟蹤。有了這些資訊,您將更有可能診斷問題並快速解決問題。
以傳統方式部署的 WebObjects 系統包含程式的多個副本,它們分別執行,每個副本都承載來自使用者的某些入站負載。每個“副本”都被稱為一個例項。該SiteConfig.xml檔案定義了例項。此配置檔案位於您的 MacOS-X Server 檔案系統的以下位置。
/Library/WebObjects/Configuration/SiteConfig.xml
在修改它之前,請備份SiteConfig.xml檔案以防出現任何問題。
例項被修改,以便可以使用jdb除錯工具遠端連線到它們。需要將一些“附加引數”插入到配置中的SiteConfig.xml檔案中的每個例項,以便實現這一點。這些附加引數將如文字所示插入到元素additionalArgs中。您需要為每個例項選擇不同的地址 - 從 8000 到 8999 之間選擇地址。這是一個 TCP/IP 埠。請注意,所有附加引數都應顯示在一條連續的行上。作者在此處將其拆分以提高可讀性。
...
<instanceArray type="NSArray">
<element type="NSDictionary">
<id type="NSNumber">1</id>
<port type="NSNumber">2001</port>
<cachingEnabled type="NSString">YES</cachingEnabled>
<additionalArgs type="NSString">
-Xdebug
-Xrunjdwp:transport=dt_socket,address=8121,server=y,suspend=n
</additionalArgs>
...
</element>
該元素標籤將在此處重複,以包含在instanceArray標籤中的所有例項。
該id標籤給出例項編號,您需要記住從例項編號到地址的對映,這些對映在附加引數中。將這些資訊記在一張紙上。例如,在上面,可以看出例項 1 對映到地址 8121。
現在重新啟動您的例項。
例項列在 JavaMonitor 中。下面顯示了一個螢幕截圖,例項編號用紅色圓圈標記。您首先需要確定哪個例項已凍結。
獲得例項編號後,使用您的例項到地址對映(來自設定),識別您要連線到的地址。
使用jdbjava 環境附帶的命令列工具連線到例項並除錯它。為此,請在應用程式伺服器上輸入以下形式的命令。
fooserver$ jdb -attach 8121
如果您要除錯遠端機器,可以使用以下命令。
foodev$ jdb -attach woserverhost:8121
這可能在您的 WebObjects 應用程式伺服器上沒有安裝jdb工具的情況下很有用,因此您需要從安裝了jdb工具的主機執行 jdb 工具。
您現在將使用 java 偵錯程式。有大量命令可以幫助您使用除錯的 java 系統,但本文只關注獲取執行緒堆疊跟蹤。發出命令suspend以凍結所有執行緒,以便可以將其轉儲,然後發出命令where all以獲取所有執行緒的堆疊跟蹤。最後,當您希望再次恢復執行緒時,請發出命令resume。建議您在獲得所需資訊後立即退出jdb環境。
下面顯示了堆疊跟蹤的示例。您會注意到 java 類名和原始碼行號位於堆疊中特定條目末尾。在這裡,我們可以看到名為“WorkerThread103”的執行緒卡住了,試圖從會話儲存中獲取會話。在這種情況下,另一個執行緒很可能擁有會話儲存的鎖定,並且沒有釋放該鎖定。
WorkerThread103: [1] java.lang.Object.wait (native method) [2] java.lang.Object.wait (Object.java:429) [3] com.webobjects.appserver.WOSessionStore.checkOutSessionWithID (WOSessionStore.java:207) [4] com.webobjects.appserver.WOApplication.restoreSessionWithID (WOApplication.java:1,546) [5] com.webobjects.appserver._private.WOComponentRequestHandler._dispatchWithPreparedApplication (WOComponentRequestHandler.java:314) [6] com.webobjects.appserver._private.WOComponentRequestHandler._handleRequest (WOComponentRequestHandler.java:358) [7] com.webobjects.appserver._private.WOComponentRequestHandler.handleRequest (WOComponentRequestHandler.java:432) [8] com.webobjects.appserver.WOApplication.dispatchRequest (WOApplication.java:1,306) [9] nz.co.orcon.osm.webobjects.Application.dispatchRequest (Application.java:428) [10] com.webobjects.appserver._private.WOWorkerThread.runOnce (WOWorkerThread.java:173) [11] com.webobjects.appserver._private.WOWorkerThread.run (WOWorkerThread.java:254) [12] java.lang.Thread.run (Thread.java:552) WorkerThread101: [1] java.net.PlainSocketImpl.accept (PlainSocketImpl.java:351) [2] java.net.ServerSocket.implAccept (ServerSocket.java:448) [3] java.net.ServerSocket.accept (ServerSocket.java:419) [4] com.webobjects.appserver._private.WOWorkerThread.run (WOWorkerThread.java:238) [5] java.lang.Thread.run (Thread.java:552) ...
如果您檢視其他執行緒同時在做什麼,您很有可能確定哪個區域可能存在錯誤。至少,您可以弄清楚應用程式的哪個部分存在錯誤。
儘管這種方法很簡單,但它提供了一種方法,可以使您瞭解凍結例項內部發生了什麼,而不是進行繁瑣的猜測遊戲。
