[更新] 基于Quartz.NET 的任务调度管理工具

 

更新列表:

  1. 任务参数可视化.
  2. 立即中断正在执行的任务.
  3. 每个任务独立的应用程序域

上一版参见:

基于Quqrtz.NET 做的任务调度管理工具

界面具体变化如下:

任务参数可视化

如上图所示, 在管理任务的界面上就可以知道这个任务需哪些参数/类型 及 参数的说明.

实现方式, 在 Job 上添加 特性 :  ParameterTypeAttribute

 1 namespace JobA {
2 [ParameterType(typeof(Parameter))]
3 public class Job : IJob {
4
5 public static ILog Log = LogManager.GetLogger(typeof(Job));
6 public void Execute(IJobExecutionContext context) {
7 var dataMap = context.JobDetail.JobDataMap;
8 //if (dataMap.ContainsKey("int")) {
9 // var pInt = dataMap.GetIntValue("int");
10 // Console.WriteLine("1 JobA Parameter {0}", pInt);
11 //} else {
12 // Log.Error("缺少参数 int, 未执行");
13 // throw new JobExecutionException("缺少参数");
14 //}
15
16 var p = dataMap.Parse<Parameter>();
17 Console.WriteLine("{0}\t{1}\t{2}\t{3}", p.PDateTime, p.PDecimal, p.PInt, p.PNullableInt);
18
19
20 Thread.Sleep(TimeSpan.FromMinutes(3));
21 }
22 }
23 }

取参数直接调用 dataMap.Parse<Parameter>() 就行了.

Parse 方法在: QM.Common. DatamapParser 中定义.

相比原始的从 DataMap 中用 key / value 方法取参数, 这种处理方式的好处不言而喻.

但是也有缺点, DataMap 支持任何可序列化的类型,

而用这种方法只支持

string, decimal, long, int, single, double, DateTime, DateTimeOffset, TimeSpan , bool, char 这些类型. (没有做更深一步的处理, 有兴趣的,可以尝试自己去实现.)

每个任务独立的应用程序域

试想一下插件式开发, 如果你做的插件需要N个第三方DLL, 而这些DLL并没有引用到主项目上, 怎么办呢? 一堆的 FileLoadException, FileNotFoundException 等错误, 想想都头疼.

如果你开发的插件想拥有自己的配置文件, 又该怎么办呢? 自己实现一个配置文件读取解析? ini ? xml ? 头疼吧.

针对上面的问题, 在这里的最佳解决办法是 : 独立的应用程序域.

这个要从 IScheduler.JobFactory 说起.

在QM.Server.QMServer 的构造方法中, 指定 Schedule.JobFactory 为 IsolatedJobFactory

IsolatedJobFactory 的定义:

 1     public class IsolatedJobFactory : IJobFactory {
2
3 public IJob NewJob(TriggerFiredBundle bundle, IScheduler scheduler) {
4 return NewJob(bundle.JobDetail.JobType);
5 }
6
7 private IJob NewJob(Type jobType) {
8 return new IsolatedJob(jobType);
9 }
10
11 public void ReturnJob(IJob job) {
12 IDisposable disposable = job as IDisposable;
13 if (disposable != null) {
14 disposable.Dispose();
15 }
16 }
17 }

从 NewJob 方法上可以看出, 实例出来的 Job 并不是最终要执行的 Job, 而是 IsolatedJob 的实例, 它类似中间人的身份.

IsolatedJob 实现了 IInterruptableJob 接口, 为中断执行中的任务埋下伏笔.

在 IsolatedJob 的构造方法中, 通过 IsolateDomainLoader 新建一个应用程序域:

IsolatedDomainLoader 的构造函数:

 1 public IsolateDomainLoader(string path, string configFileName = "") {
2 AppDomainSetup setup = new AppDomainSetup();
3 setup.ApplicationName = "IsolateDomainLoader";
4 setup.ApplicationBase = path;
5 setup.DynamicBase = path;
6 setup.PrivateBinPath = path;
7 setup.CachePath = setup.ApplicationBase;
8 setup.ShadowCopyFiles = "true";
9 setup.ShadowCopyDirectories = setup.ApplicationBase;
10 if (!string.IsNullOrWhiteSpace(configFileName)) {
11 setup.ConfigurationFile = configFileName;
12 setup.ConfigurationFile = Path.Combine(path, configFileName);
13 }
14 this.Domain = AppDomain.CreateDomain("ApplicationLoaderDomain", null, setup);
15 }

参数 path 即最终要执行的 job 所在的 dll 的路径.

configFileName 即独立的配置文件名称.

这样一来, 一个 job 一个文件夹, 文件夹内放置这个 job 相关的DLL和配置文件, 和主程序完全隔离开来.

上面说 IsolatedJob 是个中间人, 这里解释一下:

1, IsolatedJobFactory 的 NewJob 方法返回的是 IsolatedJob 的实例, 而不是最终要执行的 Job.

2, 在 IsolatedJob 中, 会通过独立的应用程序域 实例一个最终要执行的 Job 的远程对象(通过 RemoteObject).

3, 当中间人的 Execute 方法被调用时, 会调用远程 Job 对象的 Execute 方法.

4, Interrupt 方法同理.

远程对象续约

因为独立的应用程序域用到了远程对象: MarshalByRefObject, 因此涉及到了远程对象的租约过期及续租的问题.

远程对象的租约默认为 5 分钟, 可以重写 InitializeLifetimeService 方法来修改租约的有效期. 但是一个 Job 不确定要执行多长时间, 修改租约有效期不是很合适, 所以这里是通过续约的方式来处理租约过期的问题.

本人对租约了解不多, 不多嘴.感兴趣的话,可参见源码:

QM.RemoteLoader.RemoteObjectSponsor 类

和 QM.RemoteLoader.IsolateDomainLoader类的 GetObject 方法.

立即中断正在执行的任务

这个命题是有条件的, 即: 任务必须实现: IInterruptableJob 接口.

一般一个任务要执行很长时间, 如果不给个中断的接口, 那就只能关闭服务或等任务执行完毕了.

实现了这个接口,在配合 CancellationToken.ThrowIfCancellationRequested 方法就可以中断当前执行的任务了(别告诉我,你的任务是单线程的).

卸载域

任务执行完成后, 会将关联的 IsolatedJob对象释放, 在 IsolatedJob 的 Dispose 方法中,会把IsolateDomainLoader 对象释放,IsolateDomainLoader 释放的时候, 会把关联的子应用程序域卸载.
所以, 如果如果你的任务是多线程的, 请在线程远行完之前, 进行阻塞.

自定义Job的基类

目前, 如果自定义的 Job 的基类在第三方DLL中, 而且第三方DLL未引用到QM.Server 项目中, 并且不在 QM.Server\Jobs 目录下, 会报:

未能加载文件或程序集 XXX 或它的某一个依赖项。系统找不到指定的文件。

解决办法有两种:

1, 将缺少的DLL放到Jobs 目录下.

2, 将缺少的DLL添加引用到 QM.Server 中.

注意, 该限制只针对 Job 的基类. 除基类使用外的第三方DLL不需要这样做, 在JOB上引用就是了.

放上一段不用的, 可终止的 任务示例代码 给你做参考

 

最后, 源码下载

https://github.com/gruan01/QM

Quartz.NET 的任务调度管理工具的更多相关文章

  1. 基于Quqrtz.NET 做的任务调度管理工具

    基于Quqrtz.NET 做的任务调度管理工具 国庆前,需求让我看了一下任务调度的数据表设计.和之前一样,有100多个字段,p1 ~ p100, 我说这是干嘛啊!按这写,写死去了! 然后在网上搜了一下 ...

  2. 使用Quartz.NET进行任务调度管理

    1.Quartz.NET 介绍 Quartz.NET是一个开源的作业调度框架,是OpenSymphony 的 Quartz API的.NET移植,它用C#写成,可用于winform和asp.net应用 ...

  3. quartz 定时任务调度管理器

    本项目使用的是spring-quartz 以下配置可以开启多个已知定时任务 <?xml version="1.0" encoding="UTF-8"?&g ...

  4. Docker集群管理工具 - Kubernetes 部署记录 (运维小结)

    一.  Kubernetes 介绍 Kubernetes是一个全新的基于容器技术的分布式架构领先方案, 它是Google在2014年6月开源的一个容器集群管理系统,使用Go语言开发,Kubernete ...

  5. 基于KVM、Xen、OpenVZ等虚拟化技术的WEB在线管理工具

    1.Proxmox proxmox是一个开源的虚拟化管理平台,支持集群管理和HA.在存储方面,proxmox除了支持常用的lvm,nfs,iscsi,还支持集群存储glusterfs和ceph,这也是 ...

  6. Linux服务管理(Ubuntu服务管理工具sysv-rc-conf)(转)

    Linux运行级别 Linux系统任何时候都运行在一个指定的运行级上,并且不同的运行级的程序和服务都不同,所要完成的工作和要达到的目的都不同,系统可以在这些运行级之间进行切换,以完成不同的工作. 运行 ...

  7. RDIFramework.NET框架基于Quartz.Net实现任务调度详解及效果展示

    在上一篇Quartz.Net实现作业定时调度详解,我们通过实例代码详细讲解与演示了基于Quartz.NET开发的详细方法.本篇我们主要讲述基于RDIFramework.NET框架整合Quartz.NE ...

  8. Postman - 功能强大的 API 接口请求调试和管理工具

    Postman 是一款功能强大的的 Chrome 应用,可以便捷的调试接口.前端开发人员在开发或者调试 Web 程序的时候是需要一些方法来跟踪网页请求的,用户可以使用一些网络的监视工具比如著名的 Fi ...

  9. JDK 中的证书生成和管理工具 keytool

    参考资料 该文中的内容来源于 Oracle 的官方文档 Java SE Tools Reference .Oracle 在 Java 方面的文档是非常完善的.对 Java 8 感兴趣的朋友,可以直接找 ...

随机推荐

  1. Oracle中merge into的使用 (转)

    该命令使用一条语句从一个或者多个数据源中完成对表的更新和插入数据. ORACLE 9i 中,使用此命令必须同时指定UPDATE 和INSERT 关键词,ORACLE 10g 做了如下改动. 1.ins ...

  2. Python 统计Facebook用户爱好的个数

    CODE: #!/usr/bin/python # -*- coding: utf-8 -*- ''' Created on 2014-8-12 @author: guaguastd @name: f ...

  3. CSDN Androidclient生产 导航帖

    弄个导航棒.的相关知识汇总. CSDN Android的client的效果图: watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvbG1qNjIzNTY1Nzk ...

  4. android从中国天气网获取天气

    http://download.csdn.net/detail/sun6223508/8011669      里面的一切..可完全移植 版权声明:本文博主原创文章.博客,未经同意不得转载.

  5. atitit.无损传输二进制数据串传输网络

    atitit.无损传输二进制数据串传输网络 1. gbk的网络传输问题,为什么gbk不能使用来传输二进制数据 1 2. base64 2 3. iso-8859-1  (推荐) 2 4. utf-8  ...

  6. Linux Howto

    1. Customize the Xfce menu http://wiki.xfce.org/howto/customize-menu

  7. SQLServer-----SQLServer 2008 R2卸载

    watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvaGVrZXdhbmd6aQ==/font/5a6L5L2T/fontsize/400/fill/I0JBQk ...

  8. python有些错误换行问题解决

    有时候数据会遇到一些错误包.例如,正确的数据应: 20141010,aaa,bbb,ccc,ddd,eee 但实际的数据是来: 20141010,aaa,bbb, ccc,ddd, eee 这样出现错 ...

  9. ORA-12638: 无法检索身份证明 解决的方法

    the NTS option makes the Oracle client attempt to use your current Windows domain credentials to aut ...

  10. hdu Simpsons’Hidden Talents(kmp)

    Problem Description Homer: Marge, I just figured out a way to discover some of the talents we weren’ ...