任务调度及远端管理(基于Quartz.net)

这篇文章我们来了解一些项目中的一个很重要的功能:任务调度

可能有些同学还不了解这个,其实简单点说任务调度与数据库中的Job是很相似的东西

只不过是运行的物理位置与管理方式有点不一样,从功能上来说我觉得还是差不多的,

存储过程有很大的局限性,耦合性也太高,所以最好把系统的一些Job放在代码层,

于是就有了Quartz.net,我们本篇就是针对Quartz.net的二次开发

 

一、新建HelloJob

HelloJob.cs,示例Job,每次执行都输出msg变量中的信息

复制代码
 1 using Common.Logging;
 2 using Quartz;  3  4 namespace Job.Items  5 {  6 public class HelloJob : IJob  7  {  8 public const string Message = "msg";  9 private static readonly ILog log = LogManager.GetLogger(typeof(HelloJob)); 10 11 public virtual void Execute(IJobExecutionContext context) 12  { 13 var jobKey = context.JobDetail.Key; 14 var message = context.JobDetail.JobDataMap.GetString(Message); 15 log.InfoFormat("HelloJob: msg: {0}", message); 16  } 17  } 18 }
复制代码

HelloJobExample.cs,每5秒执行一次

复制代码
 1         public class HelloJobExample 
 2  {  3 public virtual void Run()  4  {  5 ISchedulerFactory sf = new StdSchedulerFactory();  6 IScheduler sched = sf.GetScheduler();  7  8 IJobDetail job = JobBuilder.Create<HelloJob>()  9 .WithIdentity("job1", "group1") 10  .Build(); 11 12 JobDataMap map = job.JobDataMap; 13 map.Put("msg", "Your remotely added job has executed!"); 14 15 ITrigger trigger = TriggerBuilder.Create() 16 .WithIdentity("trigger1", "group1") 17  .ForJob(job.Key) 18 .WithCronSchedule("/5 * * ? * *") 19  .Build(); 20 21  sched.ScheduleJob(job, trigger); 22  sched.Start(); 23  } 24 }
复制代码

好了,有效代码就那么多,我们来试试

复制代码
 1     class Program
 2     {
 3 static void Main(string[] args)  4  {  5 var example = new HelloJobExample();  6  example.Run();  7  8  Console.ReadKey();  9  } 10 }
复制代码

貌似没什么问题,如愿地执行了。

 

但是我们想想,实际运行中执行任务的服务器一般都是独立出来的,那怎么去管理这些任务的开启、关闭及暂停呢?

肯定不能每次手动去操作,那太麻烦了。我们的希望是在应用中(系统管理后台)去管理这些任务。万幸Quartz.net足够强大,

他是支持远程操作的,没有太深入了解,不过看调用参数应该是通过TCP请求进行操作的,我们试试看

 

二、Job远程管理

2.1、新建Job.Items项目,把之前新建的HelloJob.cs放在其中

2.2、新建Job.Server项目

新建RemoteServer.cs

复制代码
 1     public class RemoteServer : ILjrJob
 2  {  3 public string Name  4  {  5 get { return GetType().Name; }  6  }  7  8 public virtual void Run()  9  { 10 ILog log = LogManager.GetLogger(typeof(RemoteServer)); 11 12 NameValueCollection properties = new NameValueCollection(); 13 properties["quartz.scheduler.instanceName"] = "RemoteServer"; 14 properties["quartz.threadPool.type"] = "Quartz.Simpl.SimpleThreadPool, Quartz"; 15 properties["quartz.threadPool.threadCount"] = "5"; 16 properties["quartz.threadPool.threadPriority"] = "Normal"; 17 properties["quartz.scheduler.exporter.type"] = "Quartz.Simpl.RemotingSchedulerExporter, Quartz"; 18 properties["quartz.scheduler.exporter.port"] = "555"; 19 properties["quartz.scheduler.exporter.bindName"] = "QuartzScheduler"; 20 properties["quartz.scheduler.exporter.channelType"] = "tcp"; 21 properties["quartz.scheduler.exporter.channelName"] = "httpQuartz"; 22 properties["quartz.scheduler.exporter.rejectRemoteRequests"] = "true"; 23 24  } 25 }
复制代码

2.3、新建控制器HelloJobController

复制代码
 1     public class HelloJobController : Controller
 2  {  3 public ActionResult Index()  4  {  5 try  6  {  7 if (HelloJobHelper.Trigger != null)  8  {  9 ViewBag.JobKey = "remotelyAddedJob"; 10 ViewBag.State = HelloJobHelper.Scheduler.GetTriggerState(HelloJobHelper.Trigger.Key); 11 ViewBag.StartTime = HelloJobHelper.Trigger.StartTimeUtc.ToString(); 12  } 13 else 14  { 15 ViewBag.State = "获取Job执行状态失败"; 16  } 17  } 18 catch (Exception ex) 19  { 20 ViewBag.State = "Job服务器连接失败"; 21  } 22 23 return View(); 24  } 25 public ActionResult Run() 26  { 27  HelloJobHelper.RunJob(); 28 29 return RedirectToAction("Index", "HelloJob"); 30  } 31 public ActionResult Pause() 32  { 33  HelloJobHelper.PauseJob(); 34 35 return RedirectToAction("Index", "HelloJob"); 36  } 37 public ActionResult Resume() 38  { 39  HelloJobHelper.ResumeJob(); 40 return RedirectToAction("Index", "HelloJob"); 41  } 42 }
复制代码

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

复制代码
 1         public static void RunJob()
 2  {  3 if (!scheduler.CheckExists(jobKey))  4  {  5 IJobDetail job = JobBuilder.Create<HelloJob>()  6  .WithIdentity(jobKey)  7  .Build();  8  9 JobDataMap map = job.JobDataMap; 10 map.Put("msg", "Your remotely added job has executed!"); 11 12 ITrigger trigger = TriggerBuilder.Create() 13  .WithIdentity(triggerKey) 14  .ForJob(job.Key) 15 .WithCronSchedule("/5 * * ? * *") 16  .Build(); 17 18  scheduler.ScheduleJob(job, trigger); 19 20 JobDetail = job; 21 Trigger = trigger; 22  } 23 }
复制代码

暂停比较简单

1         public static void PauseJob()
2         {
3  scheduler.PauseJob(jobKey); 4 }

2.5、View

复制代码
 1 @{
 2     ViewBag.Title = "Index";
 3  Layout = "~/Views/Shared/_Bootstrap.cshtml";  4 }  5  6 <!DOCTYPE html>  7  8 <html>  9 <head> 10 <meta name="viewport" content="width=device-width" /> 11 <title>Index</title> 12 <style> 13  .col-sm-offset-2 { 14  margin-left:20px; 15 } 16 </style> 17 </head> 18 <body> 19 <br /> 20  @using (Html.BeginForm("Run", "HelloJob", null, FormMethod.Post, new { @id = "form1", @class = "form-horizontal", role = "form" })) 21  { 22  @Html.AntiForgeryToken() 23 <div class="form-group"> 24 <div class="col-sm-offset-2 col-sm-10"> 25 <input type="hidden" name="Id" id="Id" /> 26 <button type="submit" class="btn btn-default">Run</button> 27 </div> 28 </div> 29  } 30 31  @using (Html.BeginForm("Pause", "HelloJob", null, FormMethod.Post, new { @id = "form2", @class = "form-horizontal", role = "form" })) 32  { 33  @Html.AntiForgeryToken() 34 <div class="form-group"> 35 <div class="col-sm-offset-2 col-sm-10"> 36 <input type="hidden" name="Id" id="Id" /> 37 <button type="submit" class="btn btn-default">Pause</button> 38 </div> 39 </div> 40  } 41 42  @using (Html.BeginForm("Resume", "HelloJob", null, FormMethod.Post, new { @id = "form3", @class = "form-horizontal", role = "form" })) 43  { 44  @Html.AntiForgeryToken() 45 <div class="form-group"> 46 <div class="col-sm-offset-2 col-sm-10"> 47 <input type="hidden" name="Id" id="Id" /> 48 <button type="submit" class="btn btn-default">Resume</button> 49 </div> 50 </div> 51  } 52 53 <br /> 54 <div> 55 <ul> 56 <li>ViewBag.JobKey: @ViewBag.JobKey</li> 57 <li>ViewBag.State: @ViewBag.State</li> 58 

转载于:https://www.cnblogs.com/MuNet/p/6688064.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/397080.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

C# 子类实例化基类 基类使用不了子类的方法_C#高级编程面试考题

一、简答题1.简述C#中的所有访问修饰符及访问权限private(私有的)给类&#xff0c;及所有类成员使用所有类成员的默认访问修饰符可访问范围当前类自身public(公开的)给类&#xff0c;及所有类成员使用可访问范围当前类自身所有的子类同一程序集其他类通过实例化也可以访问其他程…

关于img 403 forbidden的一些思考

网页中经常需要显示图片给用户看&#xff0c;对网站本身来说有的图片是从本地图片服务器来的&#xff0c;但是一旦数量多了以后&#xff0c;磁盘空间又是一个问题。 所以有时就希望显示其他网站的Image&#xff0c;直接把其他网站的图片显示在我的网站上。但并不是所有的外网Im…

python 循环赋值_Python打牢基础,从19个语法开始!

Python简单易学&#xff0c;但又博大精深。许多人号称精通Python&#xff0c;却不会写Pythonic的代码&#xff0c;对很多常用包的使用也并不熟悉。学海无涯&#xff0c;我们先来了解一些Python中最基本的内容。Python的特点解释型语言&#xff0c;无需编译即可运行提供了交互式…

uwp连接mysql数据库_在 UWP 应用中使用 SQLite 数据库

在 UWP 应用中使用 SQLite 数据库Use a SQLite database in a UWP app06/26/2020本文内容可以使用 SQLite 在用户设备上的轻量级数据库中存储和检索数据。You can use SQLite to store and retrieve data in a light-weight database on the users device. 本指南演示如何执行该…

MySQL 的实时性能监控利器

操作系统及MySQL数据库的实时性能状态数据尤为重要&#xff0c;特别是在有性能抖动的时候&#xff0c;这些实时的性能数据可以快速帮助你定位系统或MySQL数据库的性能瓶颈&#xff0c;就像你在Linux系统上使用「top&#xff0c;sar&#xff0c;iostat」等命令工具一样&#xff…

设置linearlayout最大高度_技术案例 | 排烟口个数与挡烟垂壁高度的关系探讨

随着《建筑防烟排烟系统技术标准》( 以下简称新规范) 的正式实施&#xff0c;新规范对排烟系统的设计提出了完全不同的设计理念。根据新规范正文: 当建筑空间净高不大于6m时&#xff0c;每个防烟分区的排烟量应按不小于60m/(h㎡)计算且不小于15,000m/h( 走道不小于13,000m/h) &…

python安装requests第三方模块

2018-08-28 22:04:51 1 .下载到桌面后解压&#xff0c;放到python的目录下 --------------------------------------------------------------------------------------------------------------------------------------------------------- 2 . 在CMD输入以下 F:\>cd /d F…

集算器协助Java处理结构化文本之条件过滤

直接用Java实现文本文件中数据按条件过滤会有如下的麻烦: 1、文件不是数据库&#xff0c;不能用SQL访问。当过滤条件变化时需要改写代码。如果要实现象SQL那样灵活的条件过滤&#xff0c;则需要自己实现动态表达式解析和求值&#xff0c;编程工作量非常大。 2、文件太大时不能一…

python3动态加载模块的方法实现

2019独角兽企业重金招聘Python工程师标准>>> 需求 我们有时写了一个功能&#xff0c;需要不断地调整&#xff0c;但是已经在线上了&#xff0c;而且在执行任务&#xff0c; 这时要更新上去源文件&#xff0c;而不能结束掉当前进程,怎么办&#xff1f; 所以这时&…

python 浮点数最小值_PYTHON学习笔记(3)——基本数据类型

本次学习原内容均来自MOOC国家精品课程《Python程序语言设计》嵩天第一篇在问题——“今天python了吗&#xff1f;”中基本数据类型1、 整数&#xff08;1&#xff09;整数无限制 pow(x,y) 计算 &#xff08;2&#xff09;四种进制 2、 浮点数类型&#xff08;1&#xff09;取整…

Windows Azure移动终端云服务管理(公测版)

概览 云在远方&#xff0c;管理在您手中。在这个移动为先 云为先的世界&#xff0c;服务不再是基于请求才提供&#xff0c;而是主动来到身边方便您的模式了。我们最近将会陆续推出几大移动端利器帮助您随时随地管理您的云服务。 首批利器之中排名第一当属Azure云助手应用, 它是…

学习opencv3中文版_给视觉组新生的一点学习建议

如果说机械组是把机器人做出来电控组让机器人动起来那么视觉组就是让机器人智能化完成一个合格的机器人三者缺一不可今天就让我们来看看视觉组师兄推荐的学习建议吧&#xff01;1语言基础 野狼队视觉组目前使用的主要语言是C&#xff0c;同时也需要具备一定的C语言基础。建议…

如何动态改变audio的播放的src

如何动态改变audio的播放的src 一、总结 一句话总结&#xff1a;js方式在请求外部网站的时候行&#xff0c;php方式在请求内外部资源都行。因为php走在js前面&#xff0c;所以问题可以从php方面想办法。 1、如何使用js控制修改audio的src或它的source 的src属性实现动态改变aud…

mysql 水平拆分实例_2021先定个小目标?搞清楚MyCat分片的两种拆分方法和分片规则!(二):水平拆分实例解析和代码实现!...

一、概述根据表中的数据的逻辑关系&#xff0c;将同一个表中的数据按照某种条件拆分到多台数据库(主机)上面&#xff0c;这种切分称之为数据的水平(横向)切分。二、案例场景在业务系统中, 有一张表(日志表), 业务系统每天都会产生大量的日志数据 , 单台服务器的数据存储及处理能…

30分钟快速搭建移动应用直传OSS服务

30分钟快速搭建移动应用直传服务 背景 这是一个移动互联的时代。手机APP上传的数据会越来越多。把数据存储的问题交给OSS&#xff0c; 让开发者能更加专注于自己的应用逻辑。 那么怎么样基于OSS构建一个APP存储系统呢&#xff1f; 目的 本教程就是让你在30分钟内搭建一个基于OS…

用java判断一个年份是否为闰年_判断闰年还是平年

↑↑↑点击上方图片&#xff0c;了解详情正文&#xff1a;判断一个年份是闰年还是平年。闰年条件&#xff1a;1.可以被400整除。2.可以被4整除&#xff0c;但是不可以被100整除。代码&#xff1a;Private Sub 查询_Click() If Me.年份 Mod 4 0 And Me.年份 Mod 100 <> 0…

【JavaScript吉光片羽】--- 滑动条

灯光的亮度控制需要一个滑动条&#xff0c;先借用lamp源码中Bar&#xff1a; var Bar function (opt) {var defaults {$id: "", // 进度条dom节点idmin: 1, // 刻度最小值stepCount: 5, // 刻度步数step: 1, // 刻度步长$alpha: "",//显示亮度的idtouchE…

python语言用什么关键字来声明一个类_python使用什么关键字定义类

什么是类&#xff1f; 用来描述具有相同的属性和方法的对象的集合。它定义了该集合中每个对象所共有的属性和方法。对象是类的实例。 什么是方法&#xff1f; 类中的函数即为方法 如何定义一个类&#xff1f; 定义类&#xff0c;语法格式如下&#xff1a;class ClassName:. . .…

谷歌+安卓,他已经改变了世界两次,但还想多来几次

回望拉里佩奇的创业经历&#xff0c;小巴发现他在几个创业者最有可能犯&#xff08;si&#xff09;错&#xff08;bi&#xff09;的节点上都处理得很好。 你还记得你用的第一个搜索网站是什么吗&#xff1f; Google.com 讲到它的创始人&#xff0c;一般要连起来念&#xff0c; …

一张图看懂单机/集群/热备/磁盘阵列(RAID)

单机部署(Standalone) 只有一个饮水机提供服务器&#xff0c;服务只部署一份 集群部署(Cluster) 多个饮水机同时提供服务&#xff0c;服务冗余部署&#xff0c;每个冗余的服务都对外提供服务&#xff0c;一个服务挂掉时依然可用 热备部署(Hot-swap) 只有一个桶提供服务&#xf…