定时任务schedInstId初始化

说道定时任务,你们立马会想到Quartz,强大的任务调度引擎和时间规则配置让咱们只须要专一于业务,并且使用极其方便,但是最近中信云上就栽了一个大跟头。java

中信云有测试环境和正式环境,定时任务框架在测试环境上跑的很溜,可是一更新到正式环境加载初始化就报错,报错信息以下:apache

Couldn't generate instance Id!
org.quartz.SchedulerException: Couldn't get host name! [See nested exception: java.net.UnknownHostException: iZ2ze6wfyo1q58e7lo99kvZ: iZ2ze6wfyo1q58e7lo99kvZ]
        at org.quartz.simpl.SimpleInstanceIdGenerator.generateInstanceId(SimpleInstanceIdGenerator.java:36)
        at org.quartz.impl.StdSchedulerFactory.instantiate(StdSchedulerFactory.java:1184)
        at org.quartz.impl.StdSchedulerFactory.getScheduler(StdSchedulerFactory.java:1484)
        at net.luculent.liems.business.bd.util.BdTaskServlet.init(BdTaskServlet.java:36)
        at javax.servlet.GenericServlet.init(GenericServlet.java:158)
        at org.apache.catalina.core.StandardWrapper.initServlet(StandardWrapper.java:1282)
        at org.apache.catalina.core.StandardWrapper.loadServlet(StandardWrapper.java:1195)
        at org.apache.catalina.core.StandardWrapper.load(StandardWrapper.java:1085)
        at org.apache.catalina.core.StandardContext.loadOnStartup(StandardContext.java:5318)
        at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5610)
        at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:147)
        at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1572)
        at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1562)
        at java.util.concurrent.FutureTask.run(FutureTask.java:262)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
        at java.lang.Thread.run(Thread.java:745)

看到这个报错后,猜想应该和环境有问题,上网查找解决办法都是出奇的一致,以为问题不是大问题,解决办法以下:api

进入线上环境(centOs6.x):  

1, 查看主机名(命令) : hostname 

2, 打开hosts文件:  vi /etc/hosts 查看是否有乱码等异常内容

3, 确保有: 127.0.0.1   后跟上面用hostname命令查看到的主机名,   若是没有则加上

  如 :   hostname ->   USER-1234

 则: 127.0.0.1  USER-1234

正式环境上配置后效果立杆见影,报错没有了,接下来验证业务,可是全部全部程序都打不开了,找来日志发现是受权失败了,打开刚刚配置的文件app

127.0.0.1   localhost localhost.localdomain localhost4 localhost4.localdomain4 iZ2ze6wfyo1q58e7lo99kvZ
::1         localhost localhost.localdomain localhost6 localhost6.localdomain6

发现以前的配置都是带了域名的,因而我也加了一个域名框架

127.0.0.1   localhost localhost.localdomain localhost4 localhost4.localdomain4 iZ2ze6wfyo1q58e7lo99kvZ.localdomain
::1         localhost localhost.localdomain localhost6 localhost6.localdomain6

结果是受权能够了,可是定时任务又报了相同的错,因而总结出了我想要的配置和受权的配置起了冲突,我这里不能改受权,因而只能从定时任务下手了dom

报错的地方是初始化任务计划的id,在StdSchedulerFactory里面找到了这个报错的这个类ide

if (schedInstId.equals(AUTO_GENERATE_INSTANCE_ID)) {
            autoId = true;
            instanceIdGeneratorClass = cfg.getStringProperty(
                    PROP_SCHED_INSTANCE_ID_GENERATOR_CLASS,
                    "org.quartz.simpl.SimpleInstanceIdGenerator");
        }
        else if (schedInstId.equals(SYSTEM_PROPERTY_AS_INSTANCE_ID)) {
            autoId = true;
            instanceIdGeneratorClass = 
                    "org.quartz.simpl.SystemPropertyInstanceIdGenerator";
        }
public class SimpleInstanceIdGenerator implements InstanceIdGenerator {
    public String generateInstanceId() throws SchedulerException {
        try {
            return InetAddress.getLocalHost().getHostName() + System.currentTimeMillis();
        } catch (Exception e) {
            throw new SchedulerException("Couldn't get host name!", e);
        }
    }
}
public class SystemPropertyInstanceIdGenerator implements InstanceIdGenerator {

  /**
   * System property to read the instanceId from
   */
  public static final String SYSTEM_PROPERTY = "org.quartz.scheduler.instanceId";

  /**
   * Returns the cluster wide value for this scheduler instance's id, based on a system property
   * @return the value of the {@link SystemPropertyInstanceIdGenerator#SYSTEM_PROPERTY system property}
   * @throws SchedulerException Shouldn't a value be found
   */
  public String generateInstanceId() throws SchedulerException {
    String property = System.getProperty(SYSTEM_PROPERTY);
    if(property == null) {
      throw new SchedulerException("No value for '" + SYSTEM_PROPERTY
                                   + "' system property found, please configure your environment accordingly!");
    }
    return property;
  }
}

顿时思路如泉涌,感叹人家代码的设计好灵活,就像为我这个尴尬境遇专门设计的,也才反应过来测试环境是单机的,正式环境是集群的,测试环境就没有调用这个方法,因而决定使用SystemPropertyInstanceIdGenerator 来初始化id,找出了配置文件quartz.properties 修改了instanceId为SYS_PROP测试

org.quartz.scheduler.instanceName = scheduler
org.quartz.scheduler.instanceId = SYS_PROP

org.quartz.threadPool.class = org.quartz.simpl.SimpleThreadPool
org.quartz.threadPool.threadCount = 10
org.quartz.threadPool.threadPriority = 5
org.quartz.threadPool.threadsInheritContextClassLoaderOfInitializingThread = true

org.quartz.jobStore.misfireThreshold = 60000
org.quartz.jobStore.class = org.quartz.impl.jdbcjobstore.JobStoreTX
org.quartz.jobStore.driverDelegateClass=org.quartz.impl.jdbcjobstore.PostgreSQLDelegate
org.quartz.jobStore.tablePrefix = QRTZ_
org.quartz.jobStore.maxMisfiresToHandleAtATime=10
org.quartz.jobStore.isClustered = true

修改了catalina.sh添加了系统属性this

JAVA_OPTS="$JAVA_OPTS -Dorg.quartz.scheduler.instanceId=01"

 重启环境,终于实现世界和平了.net

总结:有时候咱们在解决问题彻底没有思路的时候就须要从源码入手,这就须要咱们平时多看看一些开源的框架源码,初期不建议打开代码一行一行过,能够经过官方的api文档来阅读各个方法做用,经过各类场景代码来跟踪调试,在后面咱们会分享Quartz的实现原理,欢迎关注。

相关文章
相关标签/搜索