WebObjects/Web 應用程式/部署/常見問題和故障排除
我正在處理的當前應用程式在呼叫 editingContext.saveChanges 時會凍結大約一分鐘。以下訊息將新增到系統輸出中
<WorkerThread3> <WOWorkerThread id=3 socket=Socket[addr=/xxx.xxx.xxx.xxx,port=51634,localport=51563]> Exception while sending response: java.net.SocketException: Broken pipe
奇怪的是,實際上沒有丟擲異常,並且更改已儲存到資料庫。關於此訊息的含義,有什麼線索嗎?
此訊息表示 woadaptor 在分配的時間內未收到您的應用程式的響應。此時,woapdator 會結束通話您的應用程式,假設它已死或過於繁忙。如果您運行了多個例項,woadaptor 將把請求轉發到另一個例項。對於元件操作,這將產生會話過期或無法恢復頁面的錯誤訊息。
當您的應用程式最終完成處理請求時,它會嘗試將結果返回給 woadaptor,但發現它已結束通話(即關閉了套接字,斷開了管道)。此時,上面的異常將輸出到日誌。
有幾種方法可以避免這種情況
- 最佳化您的應用程式,以便更快地處理請求。
- 使用 WOLongReponsePage 處理長時間執行的請求。
- 在 JavaMonitor 中增加連線超時和接收超時值,以便 woadaptor 會等待足夠長的時間,直到您的應用程式提供響應。
注意: 如果此訊息發生在其他情況下(即不是在處理請求需要很長時間時),它可能僅表示使用者在瀏覽器中按下了停止按鈕或單擊了另一個連結。
Wotaskd 使用名為 SpawnOfWotaskd.sh 的指令碼啟動新的 WOA 例項,該指令碼位於 OS X 上的 /System/Library/WebObjects/JavaApplications/wotaskd.woa/Contents/Resources/SpawnOfWotaskd.sh。出於某種原因,此指令碼被編寫為丟棄 stderr。這意味著如果您想獲得執行緒堆疊轉儲,您將無能為力。幸運的是,這是一個簡單的修復。如果您編輯 SpawnOfWotaskd.sh,股票版本看起來像
#!/bin/sh $@ 1>/dev/null 2>&1 &
請注意,流 1 轉到 /dev/null,流 2 寫入流 1。糟糕。將其更改為
#!/bin/sh $@ 1>>/var/log/webobjects.err 2>&1 &
現在唯一的問題是,WebObjects 應用程式通常以 appserver 使用者身份執行,這意味著它們將無法寫入此檔案。要解決此問題,您可以以 root 身份“touch /var/log/webobjects.err”,然後將空檔案 chown 到您的 WebObjects 應用程式執行的任何使用者。
啊,是的,AWT 的樂趣。如果您觸控任何 AWT 類(即使是那些沒有意義的類,例如 Dimension 或 Rectangle),AWT Toolkit 將被建立(在靜態塊中),並且 AWT 將嘗試連線到視窗伺服器。當然,當您在開發模式下執行時,您有權訪問視窗伺服器,一切都很順利。只要您嘗試以 appserver 使用者身份部署,一切都亂了套。您有幾個選項可以解決此問題
- 停止使用它們。這是避免此問題最可靠的方法。在不需要時不要使用 AWT 類。顯然,這往往說起來容易做起來難。
- 將 -Djava.awt.headless=true 新增到您的 VM 啟動引數。這告訴 AWT 使用無頭模式。如果您使用的是舊版本的 Apple JVM,這可能仍然會導致問題(奇怪的除錯語句要求您在控制檯上按一個鍵)。
- PJA Toolkit。這實際上是一個很酷的庫。它是 AWT 工具包的純 Java 實現。在普通系統上,您的 AWT 實現是 JNI(與您的本地視窗系統通訊)。PJA 提供了所有功能的純 Java 實現,這些功能是普通 AWT 工具包會嘗試執行的。顯然它並沒有真正使用視窗伺服器,而是類似於具有虛擬幀緩衝區的 VNC 伺服器。
- 以 root 身份執行。這通常不建議,但您可以修改您的 /System/Library/StartupItems/WebObjects/WebObjects 指令碼,以便以 root 身份執行 WO,而不是 appserver 使用者。您將在該指令碼中找到有關如何執行此操作的說明。
對於在 Mac OS X 上遇到監視器問題的人,請檢查以下引數
- 檢查機器在 DNS 中是否被正確識別,包括反向查詢。
- 驗證在監視器中新增機器時,您是否包含了完全限定名稱,例如“machine.domain.com”,而不僅僅是“machine”。使用較短的版本可能會起作用,但實際上不起作用(Apple 有此說明)。
- 檢查介面卡配置(/System/Library/WebObjects/Adaptors/Apache/apache.conf),特別是例項發現方法:這需要與 wotaskd 的命令列啟動一致(請參閱 /System/Library/StartupItems/ 中的指令碼)。您可能需要手動修改指令碼。
- 一切設定完成後,重新啟動。它應該可以工作。
在舊版本的 OS X 伺服器中,WOtaskd 和 JavaMonitor 是使用 StartupItems 系統啟動的。在較新版本的 OS X 伺服器和 WebObjects 中,Apple 使用了新的 launchd 框架。如果您使用開發人員工具安裝 WebObjects,您通常只會在 Startupitem 指令碼中找到這些指令碼,因此您應該遵循這些說明。
有關 launchd 的概述,您可以閱讀 Apple 的文件。
WebObjects launch daemon 項預設情況下處於停用狀態,因此您需要做的第一件事是啟用它們
- cd /System/Library/LaunchDaemons
- 編輯“com.apple.womonitor.plist”和“com.apple.wotaskd.plist”
- 將 Disabled 鍵從“true”更改為“false”
- 儲存並退出
接下來,您需要手動載入 launch daemon 項
- 以 root 身份執行“launchctl”
- “list”並查詢 com.webobjects.womonitor 和 com.webobjects.wotaskd
- 如果它們確實存在,您需要手動載入它們
- “load /System/Library/LaunchDaemons/com.apple.wotaskd.plist”
- “load /System/Library/LaunchDaemons/com.apple.womonitor.plist”
- 再次“list”並驗證它們都出現
- “start com.webobjects.wotaskd”
- “start com.webobjects.womonitor”
- 退出 launchctl(按 ctrl-c)
wotaskd 和 womonitor 現在都應該在執行。您可以透過訪問 https://:56789 來測試監視器。
如果這不起作用,請檢查 /Library/WebObjects/Configuration 上的檔案系統許可權,這些許可權應該是 appserver:appserverusr,或者至少應該具有對該目錄的寫入許可權。
在終端視窗中執行以下命令將準確告訴您為什麼 wotaskd 未啟動...
sudo -u appserver /System/Library/WebObjects/JavaApplications/wotaskd.woa/Contents/Resources/javawoservice.sh -appPath /System/ Library/WebObjects/JavaApplications/wotaskd.woa/wotaskd
在開發人員安裝和舊版本的 Mac OS X Server 安裝中,WebObjects 是使用舊的 StartupItems 系統啟動的。預設情況下,wotaskd 和 womonitor 處於停用狀態。幸運的是,啟用它們很容易
- cd /System/Library/StartupItems/WebObjects
- 編輯“WebObjects”
- 搜尋“-appPath”,您將在指令碼的此區域中找到四行註釋掉的程式碼。
- 要以 root 身份執行 WebObjects,請取消註釋前兩條命令(您應該會看到 WOTASKD 和 WOMONITOR 行)
- 要以另一個使用者身份執行 WebObjects(預設情況下為 appserver 使用者),請取消註釋第二組行
- 儲存並退出
- 使用以下兩種方法之一啟動 WebObjects 服務
- sudo systemstarter start "WebObjects Services"
- ./WebObjects start
進行這些更改後,wotaskd 和 womonitor 將在重新啟動後自動啟動。
注意:不要在安裝了 WO 5.3.* 的 MacOS X 10.4.* 伺服器機器上執行這些步驟。在這種情況下,程序會以 LaunchDeamon(如上所述)的形式啟動。如果您啟用了啟動項,系統會嘗試啟動兩次 wotaskd,這會導致什麼都無法正常工作。
有多種方法可以處理死鎖和應用程式掛起。
如果您使用的是 效能分析器 或偵錯程式,您通常可以暫停執行並檢視應用程式到底是在哪裡崩潰的。
如果您使用的是 JDK 1.4,您可以嚮應用程式傳送 QUIT 訊號,它將轉儲所有活動執行緒。在 OS X 上,找到應用程式的 pid,然後執行 'kill -QUIT yourAppPID'。執行緒堆疊跟蹤將轉儲到日誌檔案。如果您在日誌中沒有看到任何輸出,請檢視上面的“我的 stderr 在哪裡?!”以瞭解可能的原因。
如果您使用的是 JDK 1.5,除了可以嚮應用程式傳送 QUIT 訊號之外,您還可以(以 root 或啟動使用者的身份)附加到應用程式,並使用 'jstack' 應用程式呼叫 'jstack yourAppPID' 獲取執行緒堆疊轉儲。
如果您看到 WOWorkerThreads 在等待恢復會話時掛起,這通常意味著之前的請求從未正確檢查其會話的某個位置丟擲了異常。WebObjects 中的會話訪問是單執行緒的。可能導致這種情況的常見情況包括從您的 awake 方法丟擲異常以及從 DirectAction 方法丟擲異常。
在 JDK 1.4 中,您將能夠看到每個堆疊跟蹤持有的物件鎖列表。您可以透過查詢包含兩個或多個重疊鎖的多個執行緒來查詢死鎖。在 JDK 1.5 中,VM 會檢測死鎖情況,並在執行緒堆疊轉儲中識別它們。