这篇文章我们来了解一些项目中的一个很重要的功能:任务调度
可能有些同学还不了解这个,其实简单点说任务调度与数据库中的Job是很相似的东西
只不过是运行的物理位置与管理方式有点不一样,从功能上来说我觉得还是差不多的,
存储过程有很大的局限性,耦合性也太高,所以最好把系统的一些Job放在代码层,
于是就有了Quartz.net,我们本篇就是针对Quartz.net的二次开发
一、新建HelloJob
HelloJob.cs,示例Job,每次执行都输出msg变量中的信息
using Common.Logging;
using Quartz; namespace Job.Items
{
public class HelloJob : IJob
{
public const string Message = "msg";
private static readonly ILog log = LogManager.GetLogger(typeof(HelloJob)); public virtual void Execute(IJobExecutionContext context)
{
var jobKey = context.JobDetail.Key;
var message = context.JobDetail.JobDataMap.GetString(Message);
log.InfoFormat("HelloJob: msg: {0}", message);
}
}
}
HelloJobExample.cs,每5秒执行一次
public class HelloJobExample
{
public virtual void Run()
{
ISchedulerFactory sf = new StdSchedulerFactory();
IScheduler sched = sf.GetScheduler(); IJobDetail job = JobBuilder.Create<HelloJob>()
.WithIdentity("job1", "group1")
.Build(); JobDataMap map = job.JobDataMap;
map.Put("msg", "Your remotely added job has executed!"); ITrigger trigger = TriggerBuilder.Create()
.WithIdentity("trigger1", "group1")
.ForJob(job.Key)
.WithCronSchedule("/5 * * ? * *")
.Build(); sched.ScheduleJob(job, trigger);
sched.Start();
}
}
好了,有效代码就那么多,我们来试试
class Program
{
static void Main(string[] args)
{
var example = new HelloJobExample();
example.Run(); Console.ReadKey();
}
}
貌似没什么问题,如愿地执行了。
但是我们想想,实际运行中执行任务的服务器一般都是独立出来的,那怎么去管理这些任务的开启、关闭及暂停呢?
肯定不能每次手动去操作,那太麻烦了。我们的希望是在应用中(系统管理后台)去管理这些任务。万幸Quartz.net足够强大,
他是支持远程操作的,没有太深入了解,不过看调用参数应该是通过TCP请求进行操作的,我们试试看
二、Job远程管理
2.1、新建Job.Items项目,把之前新建的HelloJob.cs放在其中
2.2、新建Job.Server项目
新建RemoteServer.cs
public class RemoteServer : ILjrJob
{
public string Name
{
get { return GetType().Name; }
} public virtual void Run()
{
ILog log = LogManager.GetLogger(typeof(RemoteServer)); NameValueCollection properties = new NameValueCollection();
properties["quartz.scheduler.instanceName"] = "RemoteServer";
properties["quartz.threadPool.type"] = "Quartz.Simpl.SimpleThreadPool, Quartz";
properties["quartz.threadPool.threadCount"] = "";
properties["quartz.threadPool.threadPriority"] = "Normal";
properties["quartz.scheduler.exporter.type"] = "Quartz.Simpl.RemotingSchedulerExporter, Quartz";
properties["quartz.scheduler.exporter.port"] = "";
properties["quartz.scheduler.exporter.bindName"] = "QuartzScheduler";
properties["quartz.scheduler.exporter.channelType"] = "tcp";
properties["quartz.scheduler.exporter.channelName"] = "httpQuartz";
properties["quartz.scheduler.exporter.rejectRemoteRequests"] = "true";
}
}
2.3、新建控制器HelloJobController
public class HelloJobController : Controller
{
public ActionResult Index()
{
try
{
if (HelloJobHelper.Trigger != null)
{
ViewBag.JobKey = "remotelyAddedJob";
ViewBag.State = HelloJobHelper.Scheduler.GetTriggerState(HelloJobHelper.Trigger.Key);
ViewBag.StartTime = HelloJobHelper.Trigger.StartTimeUtc.ToString();
}
else
{
ViewBag.State = "获取Job执行状态失败";
}
}
catch (Exception ex)
{
ViewBag.State = "Job服务器连接失败";
} return View();
}
public ActionResult Run()
{
HelloJobHelper.RunJob(); return RedirectToAction("Index", "HelloJob");
}
public ActionResult Pause()
{
HelloJobHelper.PauseJob(); return RedirectToAction("Index", "HelloJob");
}
public ActionResult Resume()
{
HelloJobHelper.ResumeJob();
return RedirectToAction("Index", "HelloJob");
}
}
2.4、新建HelloJobHelper
先配置连接远端任务服务器的参数,这个要和上面的RemoteServer.cs对应
1 properties["quartz.scheduler.proxy"] = "true";
2 properties["quartz.scheduler.proxy.address"] = "tcp://127.0.0.1:555/QuartzScheduler";
我们来看看开始操作,运行这个方法,任务服务器将自动开启这个Job
public static void RunJob()
{
if (!scheduler.CheckExists(jobKey))
{
IJobDetail job = JobBuilder.Create<HelloJob>()
.WithIdentity(jobKey)
.Build(); JobDataMap map = job.JobDataMap;
map.Put("msg", "Your remotely added job has executed!"); ITrigger trigger = TriggerBuilder.Create()
.WithIdentity(triggerKey)
.ForJob(job.Key)
.WithCronSchedule("/5 * * ? * *")
.Build(); scheduler.ScheduleJob(job, trigger); JobDetail = job;
Trigger = trigger;
}
}
暂停比较简单
public static void PauseJob()
{
scheduler.PauseJob(jobKey);
}
2.5、View
@{
ViewBag.Title = "Index";
Layout = "~/Views/Shared/_Bootstrap.cshtml";
} <!DOCTYPE html> <html>
<head>
<meta name="viewport" content="width=device-width" />
<title>Index</title>
<style>
.col-sm-offset-2 {
margin-left:20px;
}
</style>
</head>
<body>
<br />
@using (Html.BeginForm("Run", "HelloJob", null, FormMethod.Post, new { @id = "form1", @class = "form-horizontal", role = "form" }))
{
@Html.AntiForgeryToken()
<div class="form-group">
<div class="col-sm-offset-2 col-sm-10">
<input type="hidden" name="Id" id="Id" />
<button type="submit" class="btn btn-default">Run</button>
</div>
</div>
} @using (Html.BeginForm("Pause", "HelloJob", null, FormMethod.Post, new { @id = "form2", @class = "form-horizontal", role = "form" }))
{
@Html.AntiForgeryToken()
<div class="form-group">
<div class="col-sm-offset-2 col-sm-10">
<input type="hidden" name="Id" id="Id" />
<button type="submit" class="btn btn-default">Pause</button>
</div>
</div>
} @using (Html.BeginForm("Resume", "HelloJob", null, FormMethod.Post, new { @id = "form3", @class = "form-horizontal", role = "form" }))
{
@Html.AntiForgeryToken()
<div class="form-group">
<div class="col-sm-offset-2 col-sm-10">
<input type="hidden" name="Id" id="Id" />
<button type="submit" class="btn btn-default">Resume</button>
</div>
</div>
} <br />
<div>
<ul>
<li>ViewBag.JobKey: @ViewBag.JobKey</li>
<li>ViewBag.State: @ViewBag.State</li>
<li>ViewBag.StartTime: @ViewBag.StartTime</li>
<li>ViewBag.ExecuteTimes: @ViewBag.ExecuteTimes</li>
</ul>
</div> </body>
</html>
2.6 好了,我们先运行服务端,开起来就好了
2.7、运行Web
2.7.1 点击Run
2.7.2、点击Pause(暂停)
2.7.3、点击Resume(恢复)
2.8、最后看看项目代码层次,涉及3个:MVC、Job.Items、Job.Server
好了,基本的功能有了。这篇就到这里