关于Quartz的Windows Services停止问题?

原因是有个quartz job是从启动开始就不会休息的任务,做的事也相对于简单。在维护时,虽然有写了一个bat来卸载服务,xxx.exe uninstall 【topshelf来做services】虽然可以直接卸载服务,但无法把进程正常结束,倒置一直停留并持续运行中。只要手工KILL进程就可以了。

应该说这一直是我余留的老问题,由于有一个简单有效的临时方案,所以一直没有彻底去解决。

Thread.Interrupt

先来看一示例,相对于:

    class Program
    {
        static bool isShutdown = false;
        static void run()
        {
            long secondUnit = 10000 * 1000;
            while (!isShutdown)
            {
                Console.WriteLine("线程运行中……");
                long time = System.DateTime.Now.Ticks;
                while ((System.DateTime.Now.Ticks - time) < secondUnit)
                {
                }
            }
            Console.WriteLine("线程退出。");
        }
        static void Main(string[] args)
        {
            Thread thread = new Thread(new ThreadStart(run));
            Console.WriteLine("启动线程。");
            thread.Start();
            Thread.Sleep(3000);
            Console.WriteLine("执行Interrupt()。");
            thread.Interrupt();
            Thread.Sleep(3000);
            Console.WriteLine("退出程序");
            Console.Read();
        }
    }

以上,执行结果:
启动线程。
线程运行中……
线程运行中……
线程运行中……
执行Interrupt()。
线程运行中……
线程运行中……
线程运行中……
退出程序
线程运行中……
线程运行中……
…..

并没有跟我们想的一般,甚至程序退出后还在运行中。

原因是 Thread.Interrupt 并不会直接中断一个正在运行的线程。MSDN解释道:

如果此线程当前未阻塞在等待、休眠或联接状态中,则下次开始阻塞时它将被中断。
ThreadInterruptedException 在中断的线程中引发,但要在该线程阻塞之后才引发。如果该线程一直未阻塞,则一直都不会引发该异常,因而该线程可能无需中断就能完成。

而正确的中断线程应该是通过共享变量来,即 IsShutdown。所以对于Job而言合理处理IsShutdown非常重要。

WaitToKillServiceTimeout

等待杀死Service时间,换言之对于一个Service被停止时,会有多长时间来等待。如果按我没有合理的处理IsShutdown 来说,设置多长时间也是徒劳。

位置:HKEY_LOCAL_MACHINE/SYSTEM/CurrentControlSet/Control,默认:5000毫秒。

故而,综合以上两点。

每次正在运行的任务,需要利用中断变量来判断是否正确退出并做一些存储工作,否则会变得很为难。

开发简单Quartz.Net远程管理遇到的些问题

之前的一些项目是依赖时IIS进程下面,所以很容易就可以获取到相关Quartz的Job、Trigger等状态信息,相关代码也是直接通过官网的示例,并无做过多研究,当然也运行得很好。直到,通过Topshelf依附到Windows Services(以下简称:QA)中,因为需要对Job管理(以下简称:QB)也是必然了,虽说有很多现成的,但出于特殊需求还是自己在内部实现了。(采用工具方式可参考张善友BLOG

环境:ASP.NET、.Net Framework 4.0、IIS6.0。

1、Failed: Scheduler with name ‘XXXScheduler’ already exists.

我想大部分人会跟我一样,在任何一个需要调度的页面,通过以下方式来创建或获取任何一个Job。

ISchedulerFactory factory = new Quartz.Impl.StdSchedulerFactory();
 factory.GetScheduler();

但其实这样默认返回IScheduler,不管是哪种方式的配置,始终是quartz.config或web.config等等为优先。

当我的Web项目里面需要同时管理QA和QB时,由于每一次页面请求都会进行实例,倒置了Scheduler重复。其实真正做法应该是在Application_Start做QA、QB实例,以便我在其他任何页面调用。示例:

protected void Application_Start(object sender, EventArgs e)
 {
   // 远程
   NameValueCollection props = new NameValueCollection();
   props["quartz.scheduler.instanceName"] = "QAScheduler";
   props["quartz.scheduler.proxy"] = "true";
   props["quartz.scheduler.proxy.address"] = string.Format("tcp://{0}:{1}/{2}", "localhost", "555", "QuartzScheduler");
   ISchedulerFactory factory = new Quartz.Impl.StdSchedulerFactory(props);
   factory.GetScheduler();
   // 本地(自动按quartz.config配置项)
   ISchedulerFactory factory_local = new Quartz.Impl.StdSchedulerFactory();
   factory_local.GetScheduler();
 }

其他需要涉及到的页面:

ISchedulerFactory factory = new Quartz.Impl.StdSchedulerFactory();
IScheduler _scheduler = factory.GetScheduler("SchedulerName");// SchedulerName可以通过factory.AllSchedulers来获取。

2、Error communicating with remote scheduler.

这个错误只有在引用远程Quartz管理时才会出现异常,我总结下来会2种情况遇到这种异常:

a、Quartz没有启动。

b、防火墙。

待补充……

Quartz.NET 2.0 任务配置文档说明

新版Quartz.NET2.0(包括目前的beta版)更改任务配置文档格式,1.0以前的配置文件无法在2.0中使用。所以想升级到2.0的版本需要注意配置文档,另外2.0不再支持.net framework 1.0、2.0,所以您的.net framework版本必须在3.5 sp1以上。

以下是一个完整任务配置文档示例:

<?xml version="1.0" encoding="utf-8"?>
<!-- This file contains job definitions in schema version 2.0 format -->
<job-scheduling-data xmlns="http://quartznet.sourceforge.net/JobSchedulingData" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="2.0">  
  <processing-directives> 
    <overwrite-existing-data>true</overwrite-existing-data> 
  </processing-directives>  
  <schedule> 
    <job> 
      <name>sampleJob</name>  
      <group>sampleGroup</group>  
      <description>Sample job for Quartz Server</description>  
      <job-type>Quartz.Server.SampleJob, Quartz.Server</job-type>  
      <durable>true</durable>  
      <recover>false</recover> 
    </job>  
    <trigger> 
      <simple> 
        <name>sampleSimpleTrigger</name>  
        <group>sampleSimpleGroup</group>  
        <description>Simple trigger to simply fire sample job</description>  
        <job-name>sampleJob</job-name>  
        <job-group>sampleGroup</job-group>  
        <misfire-instruction>SmartPolicy</misfire-instruction>  
        <repeat-count>-1</repeat-count>  
        <repeat-interval>10000</repeat-interval> 
      </simple> 
    </trigger> 
  </schedule> 
</job-scheduling-data>

主要有三个节点:

pre-processing-commands(只允许一次)

processing-directives(只允许一次)

schedule(允许无穷次)

<pre-processing-commands>元素

在调度任务和触发器之前执行的命令,子元素其实就是包含预先删除调度任务和触发器,这里可以用星号(*)来代表所有调度任务或触发器。

<processing-directives>元素

在调度任务和触发器之前应该遵守的规则,其包含:

overwrite-existing-data:允许覆盖调度任务和触发器。

ignore-duplicates:忽略相同调度任务和触发器,并不会产品错误。

<schedule>元素

这是配置调度任务和触发器节点,也是主角。跟1.0不同的是,不在用<job>节点来保证<job-detail>和<trigger>相对应。2.0版本<job>和<trigger>是同级关系,至于子元素跟1.0是相同的。

 

题外话,Job类不能有构造函数,为此我调试半天。

ASP.NET与Quartz.NET计划任务

很多时候我们希望在应用程序中按指定时间执行一些任务,一种解决办法是使用客户端就用程序或WINDOWS服务来执行,较早的一些项目就是采用这些方法,写个简单的控制台应用程序,然后由WINDOWS任务计划调用。这又让我想起我的一个同学,他曾经也在他的项目中使用WINDOWS服务来解决问题。

在ASP.NET应用程序中,并不是只能采用以上那些办法。取而代之的是通过IIS线程执行你的任务。而Quartz是第三方开源的作业调度框架,而Quartz.NET是Open Symphony 的 Quartz API的.NET移植,它用C#写成,可用于winform和asp.net应用中。

在Quartz.NET有三个主要组成部分:调度,作业和触发器。写到这里感觉很多余,关于Quartz.NET方面的知识,我这里将提供一些地址。而这里我将叙述遇到的一些问题及解决方案:

1、应用池回收调度停止

Quartz.NET本身是寄托于IIS线程上面,所以一但应用池回收,导致放在内存中的数据也跟着丢失。因此对于这个问题,需要从IIS应用池配置、ASP.NET应用程序双方面结合。

IIS应用池配置主要是减少线程自动回收,主要影响因素包括:回收工作进程(分钟)、空闲超时关闭工作进程。

ASP.NET应用程序处理办法通过Application_Start和Application_End分别加载Quartz.NET和关闭Quartz.NET,特别是在Application_End时可以使用类似这种萎缩的方式,解决当由IIS应用池回收自动加载问题:

Thread.Sleep(1000);
string url = "Web Url";
HttpWebRequest myHttpWebRequest = (HttpWebRequest)WebRequest.Create(url);HttpWebResponse myHttpWebResponse = (HttpWebResponse)myHttpWebRequest.GetResponse();
Stream receiveStream = myHttpWebResponse.GetResponseStream();

其实综合起来并不能很好解决所有问题,比较机器重启后等。

参考

  1. 开源的作业调度框架 – Quartz.NET
  2. Quartz.NET – Enterprise Job Scheduler for .NET Platform(官网)

© 2017 卡片机色彩 沪ICP备13032872号-3

Theme by cipchk

to top