WebObjects/Web 應用程式/部署/計劃重啟
讓我們更深入地看看發生了什麼。當指定時間到來時,wotaskd 嚮應用程式傳送一條訊息,要求其開始拒絕新會話。應用程式將開始將所有後續沒有會話的請求重定向到沒有拒絕新會話的例項。當然,在你的情況下,最終所有例項都會拒絕,並且 woadaptor 會舉手表示沮喪並宣稱“無可用例項”。
但對我們來說,有趣的環節發生在之前。在被告知拒絕新會話後,應用程式會悄無聲息地繼續為已經擁有會話的使用者提供服務,等待他們終止會話。當每個會話終止時,它會檢查剩餘會話的數量是否低於閾值(預設值為 1)。如果是,它會呼叫 terminate() 並關閉執行迴圈。此時,如果一切順利,只有守護執行緒在執行,JVM 會停止它們並退出。wotaskd 會注意到應用程式沒有執行,並重新啟動它。前提是所有操作都正常。
現在,會發生什麼問題?我所見過的兩個最常見的問題是 (1) 永久會話 - 會話計數從未降至零,以及 (2) 卡住的非守護執行緒。第一種情況會阻止應用程式呼叫 terminate() 並開始退出程序。第二種情況會阻止 JVM 在主應用程式執行緒停止後終止。
永久會話是由你的程式碼中引發的異常引起的,這些異常會阻止會話被檢入會話儲存區。造成此問題的首要原因是在 session 的 sleep() 方法中引發異常。如果你使用此方法,請用 try...catch 包裹它以處理可丟擲物件。不要讓此方法在任何情況下都丟擲異常。永久會話也可能是由 awake() 和 terminate() 中丟擲的異常引起的,而且我相信還存在其他原因。
卡住的執行緒通常是由於某種執行緒死鎖造成的,並且經常會在從另一個執行緒中請求從未檢入的會話時,由於永久會話而導致。如果你的應用程式正在建立未標記為守護執行緒且在應用程式終止時未關閉的執行緒,則可能會出現類似的情況。
好的,所有這些都很好,但你該怎麼做呢?首先,你要等到這種情況發生並獲得應用程式的執行緒轉儲。這裡有一些說明:http://lists.apple.com/archives/webobjects-dev/2003/Sep/msg00362.html 請注意,你需要編輯的檔案位於 /System/Library/WebObjects/JavaApplications/wotaskd.woa/Contents/Resources 中。確保 appserver 使用者對你要指向的目錄/檔案具有寫入許可權。
接下來,你需要在應用程式中新增一些更好的日誌記錄。至少,我建議你這樣做
- 記錄建立會話時的 ID
- 記錄呼叫會話的 terminate() 時 ID
- 記錄呼叫會話的 terminate() 時應用程式的剩餘 activeSessionsCount()
- 記錄應用程式中 dispatchRequest() 中的 RR 查詢的啟動和停止
- 記錄拒絕會話和 refuseNewSessions(boolean) 中的 activeSessionsCount()
- 記錄呼叫應用程式的 terminate() 時
我的首選是修復你的程式碼。其次,如果你設定了很長的會話超時,而使用者仍在工作,則應用程式可能需要相當長的時間才能重新啟動(只要使用者繼續工作,再加上會話超時)。第三,如果 JVM 正在等待卡住的執行緒,那麼你無能為力,因為傳送文字頁面的任何守護執行緒都已經被殺死了(至少我認為是這樣)。好了,忽略所有這些,當 true 傳遞時,在 refuseNewSessions(boolean) 中以守護執行緒的形式啟動計時器。當計時器觸發時,傳送文字訊息。或者,如果你像我一樣喜歡睡覺,只需呼叫 System.runtime().exit(1)。如果稍後用 false 呼叫 refuseNewSessions(boolean),則停止計時器。這只是以防萬一有人在 JavaMonitor 中點選。