• 几年前写的一个任务调度模块


    大概是在09年下半年,参与了一个项目,当时项目有一些需要定期执行的任务,并且考虑到后续会有更多的任务需要调度,所以项目负责人决定做一个调度模块。而且,有了调度模块之后,其他项目可以重复利用,从而实现“一次编写处处可用”。这样,在有新的调度任务时,只要按照规则做一些简单的配置就可以了。最终,这个光荣的工作任务就落到了我手上。

     
        接下来说说调度模块的设计与实现思路。
     
    从总体上,调度模块包括两部分:调度管理和调度执行引擎,这两部分独立部署,共用数据库。
     
    一、调度管理
        调度管理主要是对任务、调度规则的配置管理。
     
    1、支持的任务类型
    1)URL
        可以指定需要定期调用的URL,同时可以配置相应的参数列表。这种方式,只要能通过URL进行访问的任务,都可以进行调度。
        优点:只要提供任务的URL,就可以进行调度,很灵活,配置简单。
        缺点:如果URL经过的网络比较差,调度时间稍有影响,但很细微;如果任务比较多或调度比较频繁,将会建议比较多的http连接,从设计上其实不太好。
     
    2)存储过程
        可以指定需要定期调用的存储过程,同时可以配置存储过程的参数,但参数值是固定的。
     
    3)实现调度任务接口方法
        系统定义了一个接口,该接口包含一个用于调度的方法。需要进行调度的任务,可以通过实现该接口,然后只要在调度管理模块进行类名全路径的简单配置,再配置调度规则,就可以实现对该任务的调度。
        另外,按照原来的设计思路,必须支持动态上传加载任务。即在项目上线运行过程中,不重启工程的情况下,可以通过上传class类、jar包任务代码,配置任务及调度规则之后,动态装载class类、jar包进行调度。
        优点:调度任务接口规范化了;动态装载任务的方式实现了任务的热装载,新增任务代码不需要重启工程。
        缺点:与使用URL的方式相比,自由度、灵活性稍差一些。
     
    2、调度规则
        调度规则主要字段有:任务名称/代码、生效/失效日期、首次执行时间、任务类型(周期性/一次性)、每日(时、分、秒)/每周(周几、时、分、秒)/每月(几号、时、分、秒)、间隔(多少天/小时/分/秒)
     
    二、调度执行引擎
        调度管理只是负责任务和规则的管理工作,实际的任务调度是由调度执行引擎负责实现。对任务的监测扫描,任务的启动、暂停、删除以及调度,都在这里实现。
     
        调度框架使用了比较流行的Quartz,结合Spring进行使用。其实当时还使用了另外一项批处理技术(spring batch),但事实上对于本部分的实现,它已经成了鸡肋。后来发现,去掉以后其实结构会更清晰,更易于维护。所以技术的东西,够用、适用就好了,太多太杂有时适得其反。
     
    1、下面贴两张流程图
    1)项目工程启动之后,调度任务的初始化过程


     
    2)监测任务的工作过程


     
        监测任务每隔一段时间会调用一次,如10秒调用一次。
     
    2、动态装载
    1)动态状态类
    Java代码 复制代码 收藏代码
    1. ClassLoader classLoader = Thread.currentThread().getContextClassLoader();   
    2. if (classLoader == null) {   
    3.     classLoader = ClassUtils.class.getClassLoader();   
    4. }   
    5. classLoader .loadClass(name);  
    ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
    if (classLoader == null) {
        classLoader = ClassUtils.class.getClassLoader();
    }
    classLoader .loadClass(name);
     
    2)动态状态装包中的类
    Java代码 复制代码 收藏代码
    1. URL url = new URL("file:" + jarPath); // jarPath为jar包的路径   
    2. URL[] urls = new URL[] {url};   
    3. URLClassLoader urlLoader = new URLClassLoader(urls, classLoader);   
    4. JarFile jarFile = new JarFile(new File(jarPath));   
    5. ZipEntry entry = jarFile.getEntry(jobNameFile); // jobNameFile中存放着所有要执行任务的类名全路径清单,按顺序存放   
    6. Scanner s = new Scanner(jarFile.getInputStream(entry));   
    7. while (s.hasNextLine()) {   
    8.     String name = s.nextLine().trim();   
    9.     Class<?> clazz = urlLoader.loadClass(name);   
    10.     ...   
    11. }  
    URL url = new URL("file:" + jarPath); // jarPath为jar包的路径
    URL[] urls = new URL[] {url};
    URLClassLoader urlLoader = new URLClassLoader(urls, classLoader);
    JarFile jarFile = new JarFile(new File(jarPath));
    ZipEntry entry = jarFile.getEntry(jobNameFile); // jobNameFile中存放着所有要执行任务的类名全路径清单,按顺序存放
    Scanner s = new Scanner(jarFile.getInputStream(entry));
    while (s.hasNextLine()) {
        String name = s.nextLine().trim();
        Class<?> clazz = urlLoader.loadClass(name);
        ...
    }
     
    3、构造cron表达式
    Java代码 复制代码 收藏代码
    1. /**  
    2.  * 构造cron表达式  
    3.  */  
    4. public String getCronExpression(ExecPlan plan) {   
    5.     StringBuffer expression = null;   
    6.     if (plan.getFixedType().equalsIgnoreCase(Constants.FIXED_TYPE_MONTH)) { // 每月   
    7.         expression = new StringBuffer();   
    8.         expression.append(plan.getFixedSeconds()).append(" ");   
    9.         expression.append(plan.getFixedMinutes()).append(" ");   
    10.         expression.append(plan.getFixedHours()).append(" ");   
    11.         expression.append(plan.getFixedDateNum()).append(" * ?");   
    12.     } else if (plan.getFixedType().equalsIgnoreCase(Constants.FIXED_TYPE_WEEK)) { // 每周   
    13.         expression = new StringBuffer();   
    14.         expression.append(plan.getFixedSeconds()).append(" ");   
    15.         expression.append(plan.getFixedMinutes()).append(" ");   
    16.         expression.append(plan.getFixedHours()).append(" ? * ");   
    17.         expression.append(plan.getFixedDateNum());   
    18.     } else if (plan.getFixedType().equalsIgnoreCase(Constants.FIXED_TYPE_DAY)) { // 每日   
    19.         expression = new StringBuffer();   
    20.         expression.append(plan.getFixedSeconds()).append(" ");   
    21.         expression.append(plan.getFixedMinutes()).append(" ");   
    22.         expression.append(plan.getFixedHours()).append(" * * ?");   
    23.     }   
    24.     return expression.toString();   
    25. }  
    /**
     * 构造cron表达式
     */
    public String getCronExpression(ExecPlan plan) {
    	StringBuffer expression = null;
    	if (plan.getFixedType().equalsIgnoreCase(Constants.FIXED_TYPE_MONTH)) { // 每月
    		expression = new StringBuffer();
    		expression.append(plan.getFixedSeconds()).append(" ");
    		expression.append(plan.getFixedMinutes()).append(" ");
    		expression.append(plan.getFixedHours()).append(" ");
    		expression.append(plan.getFixedDateNum()).append(" * ?");
    	} else if (plan.getFixedType().equalsIgnoreCase(Constants.FIXED_TYPE_WEEK)) { // 每周
    		expression = new StringBuffer();
    		expression.append(plan.getFixedSeconds()).append(" ");
    		expression.append(plan.getFixedMinutes()).append(" ");
    		expression.append(plan.getFixedHours()).append(" ? * ");
    		expression.append(plan.getFixedDateNum());
    	} else if (plan.getFixedType().equalsIgnoreCase(Constants.FIXED_TYPE_DAY)) { // 每日
    		expression = new StringBuffer();
    		expression.append(plan.getFixedSeconds()).append(" ");
    		expression.append(plan.getFixedMinutes()).append(" ");
    		expression.append(plan.getFixedHours()).append(" * * ?");
    	}
    	return expression.toString();
    }
     
     
     (转载请注明来源:http://zhanjia.iteye.com/blog/1870065)
  • 相关阅读:
    巡风安装配置 -windows
    Struts2-052 RCE CVE-2017-9805
    CVE-2017-12615和CVE-2017-12616
    Nmap使用指南
    理解HTTP协议
    缓慢拒绝服务攻击- slowloris.pl
    SSL&TLS渗透测试
    Nmap版本检测
    Protocol Buffer学习教程之编译器与类文件(三)
    64位Windows系统下32位应用程序连接MySql
  • 原文地址:https://www.cnblogs.com/wzh123/p/3393023.html
Copyright © 2020-2023  润新知