跳轉到內容

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)
...

如果您檢視其他執行緒同時在做什麼,您很有可能確定哪個區域可能存在錯誤。至少,您可以弄清楚應用程式的哪個部分存在錯誤。

儘管這種方法很簡單,但它提供了一種方法,可以使您瞭解凍結例項內部發生了什麼,而不是進行繁瑣的猜測遊戲。

華夏公益教科書