一、为什么要用Job
国内的一些定时任务一般是用Windows的计划任务执行bat里面实现的。bat的内容是打开一个ie和访问任务网址,但是这个曾引发了以下问题:
1、360导致的权限问题导致bat无法打开
2、登录服务器浏览网址的时候网址会被关闭(频率为一分钟左右)
3、ie占用资源过多,服务器曾内存爆满
4、无法监控执行结果和实时反馈错误信息给管理员
5、添加任务过程过于繁琐
6、任务数量大时无法管理
Job的优势:
1、使用http访问可以根据返回状态判断执行情况,如果任务网址没有返回,而是访问期间发生exception,job这边也会跳到catch
2、在finally写了释放http请求,不会存在资源占用过多的情况
3、配置过程简单。上主站的系统工具的Quartz管理简单配置即可
4、可在网页端实时管理任务和查看运行日志
5、当任务执行出错时可以发送邮件给管理员
二、 实现
2.1 基本配置
TestJob.cs:实现IJob,在Execute方法里编写要处理的业务逻辑,系统就会按照Quartz的配置,定时处理。
/// <summary>
/// 任务
/// </summary>
public sealed class FlightJob : JobBase, IJob
{
public void Execute(IJobExecutionContext context)
{
base.ExecuteJob(context, () =>
{
string webSite = context.JobDetail.JobDataMap.Get("TaskParam") != null ? context.JobDetail.JobDataMap.Get("TaskParam").ToString() : "";
TaskHelper.AccessWebPages(webSite);
});
}
}
配置文件,分别选中→右键属性→复制到输入目录设为:始终复制
3.2 集中式管理架构
3.2.1 架构图
3.2.2 架构思想
在两台机器分别安装了Quartz的服务,同时配置输出端口5555,这个在quartz.config里面的quartz.scheduler.exporter.port配置,然后启用调度容器,获取数据库所有的任务,添加至调度容器(如图3.2.1)。用户在网页端(系统工具-Quartz任务管理)配置任务的时候,会通过这个端口实例化调度容器,因为任务的添加需要有一个类(执行的内容),所以需要反射dll中的执行类来进行添加任务(后面发现其实写死在程序里更好)。然后两台机器就会根据触发器执行任务了。
3.2.3 小细节
1.根据时间触发器执行任务的时候,两台机器会同时往表里插入执行的任务ID,因为设置了唯一约束所以只会有一个机器插入成功,从而实现了负载均衡。
2.由于两台机器需要配置端口5555,所以需要在防火墙那添加入站和出站规则。
3.因为网站端连接两个端口配置调度容器的时候,他们两个调度容器的instancename不能一样,一样的话会报错,这个是负载程序里面唯一的不同点。
4.如果不想要任务并发执行的话,可以在执行任务的方法上面添加[DisallowConcurrentExecution],这样的话会等上次任务执行完才调用这次任务。
5.在写async异步方法时,如果在方法里面写了await,在外面千万不能wait这个方法,因为web端的上下文存在排他性,会互相等待造成死锁。