0. 简介
在某些时候我们可能会需要执行后台任务,或者是执行一些周期性的任务。比如说可能每隔 1 个小时要清除某个临时文件夹内的数据,可能用户会要针对某一个用户群来群发一组短信。前面这些就是典型的应用场景,在 Abp 框架里面为我们准备了后台作业和后台工作者来帮助我们解决这个问题。
后台作业与后台工作者的区别是,前者主要用于某些耗时较长的任务,而不想阻塞用户的时候所使用。后者主要用于周期性的执行某些任务,从 “工作者” 的名字可以看出来,就是一个个工人,而且他们每个工人都拥有单独的后台线程。
0.1 典型场景
后台作业
- 某个用户按下了报表按钮来生成一个需要长时间等待的报表。你添加这个工作到队列中,当报表生成完毕后,发送报表结果到该用户的邮箱。
- 在后台作业中发送一封邮件,有些问题可能会导致发送失败(网络连接异常,或者主机宕机);由于有后台作业以及持久化机制,在问题排除后,可以重试以保证任务的成功执行。
后台工作者
- 后台工作者能够周期性地执行旧日志的删除。
- 后台工作者可以周期性地筛选出非活跃性用户,并且发送回归邮件给这些用户。
1. 启动流程
后台作业与后台工作者都是通过各自的 Manager(IBackgroundJobManager/IBackgroundWorkerManager) 来进行管理的。而这两个 Manager 分别继承了 ISingletonDependency 接口,所以在启动的时候就会自动注入这两个管理器以便开发人员管理操作。
这里值得注意的一点是,IBackgroundJobManager 接口是 IBackgroundWorker 的派生接口,而 IBackgroudWorker 是归属于 IBackgroundWorkerManager 进行管理的。
所以,你可以在 AbpKernelModule 里面看到如下代码:
public sealed class AbpKernelModule : AbpModule { public override void PostInitialize() { // 注册可能缺少的组件 RegisterMissingComponents(); // ... 忽略的代码 // 各种管理器的初始化操作 // 从配置项中读取,是否启用了后台作业功能 if (Configuration.BackgroundJobs.IsJobExecutionEnabled) { var workerManager = IocManager.Resolve<IBackgroundWorkerManager>(); // 开始启动后台工作者 workerManager.Start(); // 增加后台作业管理器 workerManager.Add(IocManager.Resolve<IBackgroundJobManager>()); } } }可以看到,后台作业管理器是作为一个后台工作者被添加到了 IBackgroundWorkerManager 当中来执行的。
2. 代码分析
2.1 后台工作者
2.1.1 后台工作者管理器
Abp 通过后台工作者管理器来管理后台作业队列,所以我们首先来看一下后台工作者管理器接口的定义是什么样子的。
public interface IBackgroundWorkerManager : IRunnable { void Add(IBackgroundWorker worker); }还是相当简洁的,就一个 Add 方法用来添加一个新的后台工作者对象。只是在这个地方,可以看到该接口又是集成自 IRunnable 接口,那么该接口的作用又是什么呢?
转到其定义可以看到,IRunable 接口定义了三个基本的方法:Start()、Stop()、WaitStop() ,而且他拥有一个默认实现 RunableBase,其实就是用来标识一个任务的运行状态。
