HangFire快速入門 分佈式後端做業調度框架服務

安裝

NuGet 上有幾個可用的Hangfire 的軟件包。若是在ASP.NET應用程序中安裝HangFire,並使用Sql Server做爲存儲器,那麼請在Package Manager Console窗口中鍵入如下命令:html

PM> Install-Package Hangfire

配置

在安裝package後,添加或者更新如下幾行到Owin Startp類:git

複製代碼
using Hangfire;

// ...

public void Configuration(IAppBuilder app)
{
    GlobalConfiguration.Configuration.UseSqlServerStorage("<connection string or its name>");

    app.UseHangfireDashboard();
    app.UseHangfireServer();
}
複製代碼

須要配置受權

默認狀況下,只有本地有權限訪問Hangfire儀表板。若是須要受權遠程訪問,那麼儀表板的受權必須進行相應的配置。github

而後打開Hangfire儀表板來測試您的配置。編譯項目並在瀏覽器中打開如下URL:數據庫

1
http: //<your-site>/hangfire

 

用法

添加工做

HangFire處理不一樣類型的後臺任務,而且使用一個獨立的上下文環境調用他們。express

Fire-And-forget(發佈/訂閱)

這是一個主要的後臺任務類型,持久化消息隊列會去處理這個任務。當你建立了一個發佈/訂閱任務,該任務會被保存到默認隊列裏面(默認隊列是"Default",可是支持使用多隊列)。多個專一的工做者(Worker)會監聽這個隊列,而且從中獲取任務而且完成任務。後端

BackgroundJob.Enqueue(() => Console.WriteLine("Fire-and-forget"));

延遲

若是想要延遲某些任務的執行,能夠是用如下任務。在給定延遲時間後,任務會被排入隊列,而且和發佈/訂閱任務同樣執行。瀏覽器

BackgroundJob.Schedule(() => Console.WriteLine("Delayed"), TimeSpan.FromDays(1));

 

循環

按照週期性(小時,天等)來調用方法,請使用RecurringJob類。在複雜的場景,您可使用CRON表達式指定計劃時間來處理任務。app

RecurringJob.AddOrUpdate(() => Console.WriteLine("Daily Job"), Cron.Daily);

 

連續

連續性容許您經過將多個後臺任務連接在一塊兒來定義複雜的工做流。框架

var id = BackgroundJob.Enqueue(() => Console.WriteLine("Hello, "));
BackgroundJob.ContinueWith(id, () => Console.WriteLine("world!"));

 

釋放

Hangfire將您的任務保存到持久化庫彙總,而且以可靠的方式處理它們。這意味着,你能夠中斷Hangfire Worder的線程,從新加載應用程序域,或者終止程序,即便這樣您的任務仍會被處理。只有在你代碼的最後一行執行完成,Hangfire纔會標記這個任務完成。而且知道任務可能在最後一行代碼執行以前失敗。它包含多種 自動-重試機制,它能夠自動處理在存儲或代碼執行過程當中發生的錯誤。異步

這對於通用託管環境(如IIS Server)很是重要。它們能夠包含不一樣的優化,超時和錯誤處理代碼(可能致使進程終止)來防止很差的事情發生。若是您沒有使用可靠的處理和自動機制,您的工做可能會丟失。您的最終用戶可能無限期等待某些任務,如電子郵件,報告,通知等。

可是當您的存儲空間破損時,Hangfire沒法作任何事情。請爲您的存儲使用不一樣的故障切換策略,以保證在發生災難時處理每一個做業。

 

原文地址:http://docs.hangfire.io/en/latest/quick-start.html

 

 

 

 

 

 

 

 

 

 

HangFire簡述:
分佈式後端做業調度框架服務,咱們只須要關心業務邏輯代碼,而不用關心調度機制,支持.net framework和.net core

HangFire基本結構:
客戶端(建立任務)、服務端(執行任務)、數據庫(存儲任務列表和執行情況)、儀表盤(在網站上對任務進行監控查看和各類操做)

HangFire適用場景:
定時執行任務、循環執行任務、異步執行耗時任務、A任務執行完成再執行B任務、批量執行任務

HangFire官網: https://www.hangfire.io/
HangFire中文文檔:http://koukouge-hangfire.daoapp.io/quick-start.html 
HangFire英文文檔:http://docs.hangfire.io/en/latest/quick-start.html 
HangFire源碼地址: https://github.com/HangfireIO


image

實戰經驗分享:
網上資料不是不少 都是按照官方例子在講解,缺乏不少關鍵性的概念講解,致使不少夥計在實戰中遇到各類坑。

一、客戶端:建立任務-->一、配置HangFire數據庫鏈接 二、建立任務(在建立任務的時候HangFire會自動將任務序列化並存儲到數據)

二、服務端:執行任務-->一、配置HangFire數據庫鏈接 二、從HangFire數據庫系統表讀取客戶端建立的任務而後開線程並行執行,任務之間不衝突。(服務端可宿主在Windows服務、控制檯程序、IIS中…)

三、數據庫:HangFire程序框架表-->建立任務的時候HangFire會自動生成無需關心,但要注意若是採用現有的數據庫,必須保證數據庫中沒有重名的表,不然你懂(aggregatedcounter、counter、distributedlock、hash、job、jobparameter、jobqueue、jobstate、list、server、set、state),數據庫可採用 MySQL ,MSSQL,Redis視須要而定

四、儀表盤:展現做業列表執行狀態和結果等相關信息-->在.Net WebForm或.Net MVC 或.NetCore MVC網站程序對接HangFire數據庫,MVC 對接方式和WebForm略微不一樣 請參考官方文檔


如何正確理解架設部署上述4個板塊:
重點說客戶端、服務端、儀表盤直之間的關係,數據庫就不用多說了

方案1(不推薦):客戶端A、服務端B、儀表盤C 分別運行在3個獨立的項目中
優缺點:沒什麼優勢,並且AB分開會致使服務端B從數據庫提取任務列表,準備反向加載程序集執行任務的時候,在本身的程序代碼中找不到對應的業務邏輯代碼或者引用類,由於業務邏輯代碼是在客戶端A項目中建立,天然業務邏輯類及功能代碼都在A項目的程序集中,天然找不到。

例子:客戶端A建立的做業是引用YourOwnJobLibrary.dll類中 ShowMeTheMoney() 方法,而服務端B中沒有引用YourOwnJobLibrary.dll 因此沒法執行任務ShowMeTheMoney(),

報錯:System.IO.FileNotFoundException
Could not load file or assembly 'DotNetFrameWorkConsoleApplicationHangFire, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null'. ???????????
System.IO.FileNotFoundException: Could not load file or assembly 'DotNetFrameWorkConsoleApplicationHangFire, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null'. ???????????
File name: 'DotNetFrameWorkConsoleApplicationHangFire, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null'
at System.RuntimeTypeHandle.GetTypeByName(String name, Boolean throwOnError, Boolean ignoreCase, Boolean reflectionOnly, StackCrawlMarkHandle stackMark, IntPtr pPrivHostBinder, Boolean loadTypeFromPartialName, ObjectHandleOnStack type, ObjectHandleOnStack keepalive)
at System.RuntimeTypeHandle.GetTypeByName(String name, Boolean throwOnError, Boolean ignoreCase, Boolean reflectionOnly, StackCrawlMark& stackMark, IntPtr pPrivHostBinder, Boolean loadTypeFromPartialName)
at System.RuntimeType.GetType(String typeName, Boolean throwOnError, Boolean ignoreCase, Boolean reflectionOnly, StackCrawlMark& stackMark)
at System.Type.GetType(String typeName, Boolean throwOnError, Boolean ignoreCase)
at Hangfire.Storage.InvocationData.Deserialize()

解決方案:讓服務端B也引用YourOwnJobLibrary.dll便可,可是這並非咱們想要的結果,之後更新服務什麼的還得兩頭更新很麻煩。

方案2(推薦):客戶端A、服務端B在同一個項目中,儀表盤C獨立網站項目中
優缺點:這樣比較合理,更新服務方便,即使沒有儀表盤C,做業正常調度執行;適合後臺相對固定的做業。
能夠將AB放在Windows服務項目中(VS中能夠建立),這樣系統重啓什麼的毫無顧慮,更新服務程序的時候只需中止服務->替換程序->開啓服務便可。

方案3(還行):客戶端A、服務端B、儀表盤C在同一網站項目只能是網站項目,由於儀表盤只能在Web項目(API、WebForm、MVC )中
優缺點:視狀況也何嘗不可,若是宿主在IIS中,IIS默認20分鐘沒有人訪問會中止,HangFire做業服務也會定製,可將此時間在IIS配置中延長,比較適合任務常常須要靈活變更處理的場景。

重要信息備註:
注1:建立任務能夠是在控制檯程序Main方法中執行一次把任務Load到數據庫,或則在網站上用戶點擊某個按鈕執行後端方法建立。


注2:服務端比較靈活,可宿主在Windows服務、控制檯程序、IIS中…

注3:首次啓動鏈接數據庫時,會自動生成12張系統表,請確保現有庫中不存在如下表名:aggregatedcounter、counter、distributedlock、hash、job、jobparameter、jobqueue、jobstate、list、server、set、state


注4:原則上同一臺電腦上只須要1個服務端存在,測試中發現這麼一種狀況:服務端B宿主在D控制檯程序中,因誤操做在儀表盤C網站項目中也啓動一個HangeFire宿主服務E,最後的結果是服務端B的程序失效,服務端E正常運做,可是儀表盤上顯示找不到任務做業對應的程序集,由於程序集在服務端B程序中,如方案1的System.IO.FileNotFoundException…


注5:HangFire執行的任務裏面若是涉及到C盤建立文件夾 可能會由於權限問題 建立失敗,採用管理員權限運行程序便可建立


實例:按照方案2思路測試

  1. 建立一個.net core 2.0控制檯項目(.net framework/.net core2.0都行)
  2. 安裝nuget Hangfire(針對控制檯程序能夠只安裝Hangfire.core便可 )
  3. 安裝nuget HangFire.MySql.Core(.net framework 也引用此包 若是用HangFire.MySql 下面的配置數據庫連接事變)
  4. 安裝好後就能夠在Main方法中使用了

image

注:控制檯程序關閉,也就是HangFire宿主程序中止,做業沒法繼續執行,想檢測服務做業是否在執行,可定時往記事本中寫入當前時間。

五、網站(.net core)中配置HangFire儀表盤:( .net framework 的網站配置不同 還沒有測試)
image

注1:app.UseHangfireDashboard(); 是讓網站僅僅能夠訪問HangFire數據庫的做業詳情,不負責業務代碼的執行。

注2:app.UseHangfireServer();是讓HangFire服務宿主在Web程序中,參加上面方案2和方案3,若是是方案2則不該該添加此語句,方案3則添加此語句。


運行項目訪問HangFire儀表盤: http://localhost:56013/hangfire/
image

image

相關文章
相關標籤/搜索