1、首先添加job任务,它的需求是描述BackgroundJobInfo参数(它是可以序列化的,可以存储),怎么操作 Execute(TArgs args)
2、何时操作,比如一种常见是隔断时间执行,直到成功结束,然后删除这个job,保证这些任务一定能执行得到,这个BackgroundJobWorker就负责这个
而BackgroundWorkerManager就管理这些worker, 启动,停止操作
这个Job的实际执行操作,由IBackgroundJobExecuter代理完成的。
3、HangFire是对job任务入列操作,它的适配器可以执行Execute的操作
4、RabbitMQ: 从AbpBackgroundJobOptions得到job
工作队列JobQueue=》 入列EnqueueAsync,发送事件到消息总线里去,开始操作(消费操作)、结束操作
1、Abstractions抽象公共方法
添加到AbpBackgroundJobOptions里,TArgs
是一个简单的C#类, 用于存储作业数据.,一般是TransientDependency方法
public interface IBackgroundJob<in TArgs> { void Execute(TArgs args); }
作业任务管理器,在单线程中FIFO(先入先出),重试作业执行直到作业执行成功或超时. 默认作业超时时间是2天. 记录所有异常 ,作业执行成功时从存储中(数据库)删除作业. 如果超时, 作业会在数据库中被设置为abandoned,作业的重试等待时间会越来越长. 作业第一次重试等待1分钟, 第二次重试等待2分钟, 第三次重试等待4分钟,以此类推,以固定的时间间隔轮询存储中的作业. 查询作业, 按优先级排序(asc)然后按尝试次数排序(asc).
任务入列不是马上执行。
- 首先我们会通过参数的类型,获取到任务的名称。(假设任务上面没有标注
BackgroundJobNameAttribute
特性,那么任务的名称就是参数类型的FullName
。) - 构造一个
BackgroundJobInfo
对象。 - 通过
IBackgroundJobStore
持久化任务信息。
IBackgroundWorker只有开始、结束的操作,它有一种类型是周期性执行操作是PeriodicBackgroundWorkerBase,单例
而ABP实现的BackgroundJobWorker, OnPreApplicationInitialization()
方法内解析出后台作业管理器(IBackgroundWorkerManager
),调用它的 Add()
方法,添加到管理器当中。
其DoWork方法
1、从IBackgroundJobStore,得到等待的List<BackgroundJobInfo>。
先排除 被放弃的任务 ,包含达到执行时间的任务,然后根据任务的优先级从高到低进行排序。重试次数少的优先执行,预计执行时间越早的越先执行。最后从这些数据中,筛选出 maxResultCount
结果并返回
2、得到IBackgroundJobExecuter、IClock、IBackgroundJobSerializer
3、遍历每一个Job,得到这个Job的配置,将BackgroundJobInfo.JobArgs,jobConfiguration.ArgsTyper反序列化,
得到JobExecutionContext的上下文
4、IBackgroundJobExecuter执行操作,它是执行IBackgroundJob
var job = context.ServiceProvider.GetService(context.JobType); var jobExecuteMethod = context.JobType.GetMethod(nameof(IBackgroundJob<object>.Execute)); jobExecuteMethod.Invoke(job, new[] { context.JobArgs });
IBackgroundWorkerManager是管理IBackgroundWorker,它存储着所有IBackgroundWorker的列表,它可以添加,开始、结束操作。
集成Hangfire