HttpJob.Agent 组件介绍以及如何使用
搭建一个job调度系统和job的业务代码部署分离,job的业务代码开发不需要过多了解hangfire本身,这就是HttpJob.Agent组件的初衷 如果你使用aspnetcore技术,强烈建议你使用HttpJob.Agent组件来开发job!!
HttpJob.Agent是什么?
是一个基于netcore web的一个中间件,
NUGET地址:Install-Package Hangfire.HttpJob.Agent
帮助创建的HttpJob有以下特色
- job的调度和业务完全分离
- 可以在hangfire的后台进行添加变成一个HttpJob(支持一次性job和周期性job)
- 支持在hangfire后台手动发送该job 执行命令(动态参数指定) 和 停止命令
- 支持多种类型的job,比如 长时间运行,Hang住的job(例如消息队列的监听等)
- 统一UI管理:在Hangfire Dashbord查询job运行状态,比如长时间的运行的job 运行了多长时间等!
- JobAgent里面很方便的把日志(也支持progressbar进度条的方式)打到hangfire的dashbord console里面查看(文末有详细介绍)
JobAgent和Hangfire.HttpJob部署说明
我目前采用的是如下方式
Hangfire.HttpJob 单独部署成windows服务或者docker容器 (部署一台)
小项目的话: 用JobAgent开发的 单独部署成Windows服务或者docker容器
业务线多的话 也可以把JobAgent分开成不同的工程!
如何使用
JobAgent 是作为一个中间件来使用的 DEMO 可以查看
https://github.com/yuzd/Hangfire.HttpJob/tree/master/Test/TestHangfireAgent
配合hangfire调度端,目前jobagent只支持下面三种
- 调度端的storage是redis的Nuget包:Hangfire.HttpJob.Agent.RedisConsole
- 调度端的storage是mysql的Nuget包:Hangfire.HttpJob.Agent.MysqlConsole
- 调度端的storage是sqlserver的Nuget包:Hangfire.HttpJob.Agent.MssqlConsole
这里特别要强调下,hangfire的调度端的storage链接字符串得需要保证 jobagent客户端所在的机器也得能访问到。否则会出现jobagent的job的状态出问题!!
下面的教程是从0到1教如何使用Agent组件快速开发job
1.创建一个netcore的web空的工程(以下示例为aspnetcore2.2版本,aspnetcore3.1版本也正常使用)
根据你hangfire.http使用的是哪种storage你就使用对应类型的agent的nuget包(参考上方说明)
这里我也用NLOG组件来记录日志: 所以也安装下Nlog的包: NLog.Extensions.Logging
新增一个Nlog.config文件,可以参考
https://github.com/yuzd/Hangfire.HttpJob/blob/master/Test/TestHangfireAgent/NLog.Config
配置 startup
说明 默认是会自动寻找当前Assembly下的Job类。 如果想要自己注册非当前Assembly下的Job类需要自己注册。参考如下图:
- 支持注册一个Job的class Type(需继承JobAgent)
- 支持注册一个Assmbly(自动寻找继承了JobAgent的类,然后根据打的标签来区分你要注册的是单例还是多例还是Hang类型,参考下发说明)
- AddJobAgent 代表注册单例 AddTransientJobAgent代表注册多例
在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了
前提条件:写的job类必须要继承JobAgent
继承后必须重写的方法:
- OnStart
特别说明: OnStart方法在被执行的时候是异步执行的,所以能够执行长时间的任务
下面2个方法是虚方法 你可以重写 也可以采用默认的实现方式
- OnStop (默认的实现是将运行的CancelToken设置为取消)
- OnException(默认的实现是上报错误给调度端,状态会变成Fail)
注意点:
如果你重写了OnStop 然后你没有显示调用base.OnStop()方法的话 那你需要自己管理CancelToken
如果你重写了OnException方法 然后你没有显示调用base.OnException方法 那么你的这个异常就被你吃掉了,dashbordUI上该job的此次之行状态会变成成功!
1. 写一个最简单的job
新建一个cs 叫 TestJob.cs
默认注册的单例JOB,下面会有多例的举例
2. 注册到Hangfire里面去
# 特别要注意的以下几个参数
1. Url 要填 Agent的注册地址 “/jobagent”
2. BasicUserName 和 BasicPassword 要填 Agent的配置的basicAuth
3. AgentClass 要填你添加的job类的完整名称
4. DelayFromMinutes这里我们填<=0 代表立即执行 如果填>1 代表延迟分钟数
# 那么对应如下填写:
{
"JobName": "TestJob", //Job名称
"Method": "POST", //http请求的方法
"ContentType": "application/json", //http参数类型
"Url": "http://localhost:5002/jobagent", //Agent的注册地址
"DelayFromMinutes": 1, //1代表延迟1分钟
"Data": "",
"Timeout": 5000, //http调用超时设置
"BasicUserName": "test", //Agent设置的basicAuth
"BasicPassword": "123456", //Agent设置的basicAuth
"QueueName": "recurring", //设置你先要在哪个queue执行
"EnableRetry": false,
"SendSucMail": false,
"SendFaiMail": true, //http失败时发邮件通知
"Mail": "1877682825@qq.com", //http调用失败通知我
"AgentClass": "TestHangfireAgent.Jobs.TestJob,TestHangfireAgent"
}
这里我演示添加一个只能我手动触发的job
添加成功后可以在 job 列表查到
由于我刚刚添加设置的是Cron为空 所以显示【DISABLED】代表只能自己点击按钮执行
由于我们填了AgentClass 这个属性,所以Hangfire会认为这个是一个AgentJob 在[作业]显示的名称里面会有 【JOBAGENT】的字样
如果需要设置Cron但对Cron不熟悉的话可以使用
如下图 手动触发试一试 示:
如果你想单独手动去执行一次又想要运行时使用不同的参数可以使用
可以看到AgentJob的控制台看到 调用执行成功 参数也传的没问题
如果你添加了一个周期性job想要临时暂停可以:
JobAgent开发的job支持查询运行状态
再回到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命令那么jobContext.CancelToken会被设置为取消状态, 来控制终止这个Job。
常见使用场景:消息队列Client端处理
使用也很简单 在类上打一个标签[HangJobUntilStop(true)]即可
记录日志到hangfire 的 DashbordUI 里面
支持 log记录 和 progress进度条两种方式
如下图:
在Job类里面使用