如何防止 Hangfire 重複作業在連續執行 30 分鐘後重新啟動
我正在開發一個 asp.net mvc-5 Web 應用程序,並且在使用 Hangfire 工具執行長時間執行的後台作業時遇到了問題。問題是如果作業執行時間超過 30 分鐘,hangfire 會自動啟動另一個作業,所以我最終會同時執行兩個類似的作業。
現在我有以下內容: -
- asp.net mvc-5
- IIS-8
- 掛火 1.4.6
- 視窗伺服器 2012
現在我已經定義了一個hangfire 重複作業,在每天17:00 執行。後台作業主要掃描我們的網路中的伺服器和虛擬機並更新數據庫,重複作業將在完成執行後發送電子郵件。當執行時間少於 30 分鐘時,重複性作業過去執行良好。但是今天隨著我們系統的發展,重複性工作在 40 分鐘後完成,而不是像以前那樣需要 22-25 分鐘。我收到了 2 封電子郵件而不是一封電子郵件(電子郵件之間的時間約為 30 分鐘)。現在我手動重新執行作業,我注意到問題如下: -
“當循環作業連續執行 30 分鐘時,將啟動循環作業的新實例,所以我將有兩個實例而不是一個同時執行,所以我收到了 2 封電子郵件。”
現在,如果重複作業的時間少於 30 分鐘(例如 29 分鐘),我不會遇到任何問題,但如果重複作業的執行時間超過 30 分鐘,那麼出於某種原因或另一個掛火將啟動一個新作業。雖然當我在作業執行期間訪問hangfire儀表板時,我發現只有一個活動作業,但當我監控我們的數據庫時,我可以從sql分析器中看到有兩個作業正在訪問數據庫。這發生在重複工作開始後 30 分鐘(在我們的例子中是 17:30),這就是為什麼我收到 2 封電子郵件,這意味著 2 個重複工作在後台執行,而不是一個。
那麼,任何人都可以就此提出建議,如果目前的重複作業執行時間超過 30 分鐘,我如何避免掛火自動啟動新的重複作業?謝謝
您是否查看
InvisibilityTimeout了Hangfire 文件中的設置?預設 SQL Server 作業儲存實現使用正常表作為作業隊列。為確保在意外程序終止的情況下不會失去作業,僅在成功完成後才將其從隊列中刪除。
為了使其對其他工作人員不可見,帶有 OUTPUT 子句的 UPDATE 語句用於獲取排隊的作業並以原子方式更新 FetchedAt 值(向其他工作人員發出信號,表明它已被獲取)。其他工作人員看到獲取的時間戳並忽略作業。但是為了處理程序終止,他們只會在指定的時間內(預設為 30 分鐘)忽略作業。
儘管這種機制確保每個作業都會被處理,但有時它可能會導致重試延遲過長或導致多個作業執行。考慮以下場景:
- 工人 A 取了一份工作(執行了一個小時)並在 12:00 開始。
- 工人 B 在 12:30 獲取相同的作業,因為預設的不可見超時已過期。
- 13:00 的 Worker C(沒有獲取)相同的作業,因為(它會在成功執行後被刪除。)
如果您使用取消令牌,它將在 12:30 為 Worker A 設置,為 Worker B 設置為 13:00。這可能導致您的長時間執行的作業永遠不會執行。如果不使用取消令牌,它將由 WorkerA 和 Worker B 並發執行(從 12:30 開始),但 Worker C 不會獲取它,因為它會在執行成功後被刪除。
因此,如果您有長時間執行的作業,最好配置不可見超時間隔:
var options = new SqlServerStorageOptions { InvisibilityTimeout = TimeSpan.FromMinutes(30) // default value }; GlobalConfiguration.Configuration.UseSqlServerStorage("<name or connection string>", options);從Hangfire 1.5 開始,這個選項現在是
Obsolete. 其他工人看不到正在從事的工作。在使用 SQL Server 時,告別將隱身超時與意外的後台作業重試(預設情況下)相混淆。新的 Hangfire.SqlServer 實現使用普通的舊事務來獲取後台作業並將它們隱藏在其他工作人員面前。
即使在不正常的關閉之後,其他工作人員也可以立即使用該工作,沒有任何延遲。