項目介紹:
Hangfire:是一個開源的job調度系統,支持分佈式JOB!!html
Hangfire.HttpJob 是我針對Hangfire開發的一個組件,該組件和Hangfire自己是獨立的。能夠獨立更新Hangfire版本不影響!git
該組件已被Hangfire官方採納,在Hangfire官網能夠查到:github
開源地址:web
https://github.com/yuzd/Hangfire.HttpJobsql
該項目目的是:
剝離Job調度和業務json
Hangfire.HttpJob到底是幹嗎的
- 傳統使用Hangfire都是把JOb的處理邏輯代碼寫在和Hangfire的同一個工程!
缺點: 這樣就耦合在了一塊兒,若是業務線增大,會致使每一個業務線的Job處理邏輯都得和Hangfire耦合在一塊兒!發佈的時候全部業務線Job都得暫停調度
- 而使用了Hangfire.HttpJob的話 就是把Hangfire的服務拓展成能夠把Job的處理邏輯代碼寫在別的工程裏面(以webapi的形式暴露給Hangfire去調度)
優勢:這樣就解耦了Hangfire和業務處理邏輯,業務job開發者能夠忽略Hangfire的存在!不一樣的業務線分開不一樣的JobAgent能夠分別部署,發佈互不影響
Hangfire.HttpJob
是對Hangfire的一個擴展插件,利用Hangfire.HttpJob能夠快速搭建分部署Job調度Server。api
特色是:app
- 業務與調度徹底分離。
- 支持定點執行 延遲執行 週期性循環執行,支持秒級別
- 配合JobAgent組件能夠實現Job管理 監控 日誌等
共有三篇文章
開源分佈式Job系統,調度與業務分離-如何建立一個計劃httpjob任務
開源分佈式Job系統,調度與業務分離-如何建立週期性的HttpJob任務
開源分佈式Job系統,調度與業務分離-HttpJob.Agent組件介紹以及如何使用
本篇教程:HttpJob.Agent組件介紹以及如何使用
HttpJob.Agent是什麼?
是一個基於netcore web的一箇中間件,專門用於配合Hangfire.HttpJob 開發HttpJob的組件分佈式
NUGET地址:Install-Package Hangfire.HttpJob.Agent測試
幫助快速建立HttpJob並有如下特點
- job的調度和業務徹底分離
- 能夠在hangfire的後臺進行添加變成一個HttpJob
- 支持在hangfire後臺手動發送該job 執行命令 和 中止命令
- 支持 長時間運行
如何使用
JobAgent 是做爲一箇中間件來使用的 DEMO 能夠查看 https://github.com/yuzd/Hangfire.HttpJob/tree/master/Test/TestHangfireAgent
JobAgent:一個JobAgent表示一個App 經過netcore web形式部署,一個JobAgent能夠宿主多個Job
Job:表示單個Job,用於處理特定的業務邏輯
1.建立一個netcore的web空的工程
安裝nuget包
這裏我也用NLOG組件來記錄日誌: 因此也安裝下Nlog的包: NLog.Extensions.Logging
新增一個Nlog.config文件,能夠參考 https://github.com/yuzd/Hangfire.HttpJob/blob/master/Test/TestHangfireAgent/NLog.Config
配置startup
在appsettings.json裏面配置JobAgent的啓動參數
參數說明
字段名稱 | 備註 |
---|---|
Enabled | 表明是否啓用JobAgent |
SitemapUrl | 表明JobAgent的請求地址 默認"/jobagent" |
EnabledBasicAuth | 表明是否開啓basicAuth認證 若是true 須要設置下面2個參數 |
BasicUserName | basicAuth認證的用戶名 |
BasicUserPwd | basicAuth認證的密碼 |
AgentJob 分下面兩種
- 單例的Job ===> 指的是在Agent運行期間只會存在一個實例 若是該實例沒有執行完畢 是不容許再次執行的
- 多例的Job ===> 每次執行都會新生成一個實例
PS:Job類都是註冊在Netcore 的 DI容器裏面的,因此能夠在job類的構造方法 注入你想要的類,好比Logger組件
開始寫job了
1. 寫一個最簡單的job
新建一個cs 叫 TestJob.cs
讓它繼承 JobAgent 而且重寫 下面3個方法
- OnStart
- OnStop
- OnException
特別說明: OnStart方法在被執行的時候是在一個獨立的線程執行的,因此可以執行長時間的任務
默認註冊的單例JOB,下面會有多例的舉例
2. 註冊到Hangfire裏面去
# 特別要注意的如下幾個參數 1. Url 要填 Agent的註冊地址 「/jobagent」 2. BasicUserName 和 BasicPassword 要填 Agent的配置的basicAuth 3. AgentClass 要填你添加的job類的完整名稱 4. DelayFromMinutes這裏咱們填-1 表明必須手動執行 若是填0表明是當即執行 若是填>1 表明延遲分鐘數 # 那麼對應以下填寫: { "JobName": "TestJob", //Job名稱 "Method": "POST", //http請求的方法 "ContentType": "application/json", //http參數類型 "Url": "http://localhost:5002/jobagent", //Agent的註冊地址 "DelayFromMinutes": -1, //-1表明必須手動啓動 "Data": "", "Timeout": 5000, //http調用超時設置 "BasicUserName": "test", //Agent設置的basicAuth "BasicPassword": "123456", //Agent設置的basicAuth "EnableRetry": false, "SendSucMail": false, "SendFaiMail": true, //http失敗時發郵件通知 "Mail": "1877682825@qq.com", //http調用失敗通知我 "AgentClass": "TestHangfireAgent.Jobs.TestJob,TestHangfireAgent" }
添加成功後能夠在job列表查到
- 因爲我剛剛添加設置的是DelayFromMinutes:-1 因此【隊列】這裏顯示【multiple】表明能夠屢次運行 而且 只能本身點擊按鈕執行
- 因爲咱們填了AgentClass 這個屬性,因此Hangfire會認爲這個是一個AgentJob 在[做業]顯示的名稱裏面會有 JobAgent的字樣
以下圖所示:
- 手動觸發試一試
能夠填參數 也能夠不填參數 這裏咱們測試就隨便寫
能夠看到AgentJob的控制檯看到 調用執行成功 參數也傳的沒問題
再回到Hangfire的後臺看下調用的日誌
注意:因爲這個是一個單例的JOB,在Onstart方法裏面咱們 採用 await Task.Delay(1000 * 10); 延遲了10秒 因此若是你在這10秒內重複執行這個Job 會提示 這個Job正在running 不能從新啓動!等OnStart方法執行完畢後這個job才能被再次調用
2. 建立一個多例的JOB
其實很簡單 就是在類上面加一個[TransientJob]標籤就變成多例了
以下圖所示 咱們建立一個測試多例的job:TestTransientJob.cs 而後在它的類上面打上一個[TransientJob]標籤 以下圖所示:
採用和上面同樣的方式註冊到Hangfire裏面去! 和上面單例的惟一區別就是 多例的Job 每次都是一個新的實例,不會判斷你上一個實例有沒有執行完.
3. 建立一個能夠Hang住OnStart方法的Job
意思就是 Job在執行OnStart方法完成的時候 不去結束這個Job 而是Hang住。 和Console.ReadKey() 相似的感受!!
等到收到OnStop命令纔去終止這個Job。
常見使用場景:消息隊列Client端處理
使用也很簡單 在類上打一個標籤[HangJobUntilStop(true)]便可
20190605追加一個用於JobAgent的記錄log到hangfire 後臺 Console 中間件
NUGET 地址: https://www.nuget.org/packages/Hangfire.HttpJob.Agent.MysqlConsole/
也是開源的 開源代碼在:https://github.com/yuzd/Hangfire.HttpJob
這個中間件的目的是能讓JobAgent 寫log到hangfire的Console
如圖:
如何在JobAgent記錄日誌並且Hangfire後臺能查到呢?
-
首先引用上面的MysqlConsole中間件的NUGET包
-
在application.json裏面配置
-
在startUp.cs文件裏面註冊
-
在Job類裏面使用
注意說明:
若是你不註冊使用MysqlConsole這個中間件的話,
那麼默認的: jobContext.Console.WriteLine 方法 等於 _logger.LogInformation(message);