2016-08-04 86 views
12

我已經創建了一個真實安排每天凌晨1:00運行功能doWork(),功能如下:Java的定時服務運行多次

@Schedule(hour = "1", persistent = false) 
    public void doWork() 
    { 
     System.out.println("Starting .....\nTIME: " + System.currentTimeMillis()); 
     System.out.println("this : " + this); 

     //Some code here, if-conditions and try/catch blocks. No loops 

     System.out.println("Exiting .....\nTIME: " + System.currentTimeMillis()); 
     System.out.println("this : " + this); 
    } 

的問題是,這個函數運行不止一次,而不是按計劃進行。

一旦我創建它,它就像預期的一樣運行(每天早上1:00:00)。幾天後,它開始在1:03:00運行(這沒有任何意義,因爲它是非持久的,並且服務器中沒有停機時間)。之後,該功能開始運行不止一次,間隔非常短(秒差)

有誰知道什麼可能會導致這種情況,或告訴我我能做些什麼來解決它?

[編輯]: 環境的詳細信息

應用服務器:在WebSphere Application Server 8.5.5

IDE:Rational Application Developer的9.1

數據庫管理系統:IBM DB2 10.1

+3

您正在使用哪個應用程序服務器(和版本)?這可能有助於檢查是否存在與該AS相關的問題。 –

+0

你如何記錄服務運行的時間?日誌輸出?系統/服務器時間? – kolossus

+0

@OlivierGrégoire我正在使用WebSphere Application Server 8.5.5 –

回答

1

我相信你正在觀察容器試圖重試失敗的doWork()調用。

EJB定時器服務是事務性的。

如果超時方法的執行會引發任何運行時異常,那麼事務將回滾並且容器將嘗試再次執行超時方法。請參閱§18.2.8EJB 3.1規範的事務。

此外,如果事務超時到期,某些實現將只標記回滾的當前事務並繼續處理。這將導致定時器調用最終失敗,並嘗試重試。

此重試機制未詳細說明,實際行爲因實現而異。有些人會永遠重試,其他人會在嘗試多次後放棄。例如,WebSphere提供了一種指定重試策略的方法。見Creating timers using the EJB timer service for enterprise beans

最後,如果您的應用程序跨多個節點運行,那麼您可能每個服務器實例都有一個計時器運行。根據§18.2.3規範的非持久定時器:

對於自動非持久性定時器,容器在應用程序初始化期間爲容器所分佈的每個JVM創建一個新的非持久性定時器。

如果這些都執行相同的任務,那麼這可能會導致足夠的混亂產生錯誤,回滾和後續重試。

+0

根據日誌,doWork()方法首次成功運行,然後再次運行並失敗並繼續重試。 問題是,它需要一個csv文件,解析它,刪除數據庫中的所有內容,然後保留解析的數據。 根據日誌,在第一次嘗試數據庫被清空並重新填充成功,然後該方法再次運行,並不斷重試,最後我得到一個空的數據庫。 由於第一次嘗試成功,我不明白爲什麼在第一次嘗試後再次調用該方法? –

+0

在任何人都可以進一步推測之前,您仍然需要提供更多環境細節。此外,您如何確保最初的事務成功完成 - 即在'doWork()'退出之後? –

+0

由於日誌記錄,我確信它在第一次嘗試中成功完成。通過檢查數據庫日誌,我可以看到解析後的.csv文件中的記錄已成功保存到數據庫中。然後繼續重試,刪除數據庫中的所有內容,並最終得到一個空的數據庫。 請檢查編輯環境的詳細信息 –