定時任務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的實現原理,歡迎關注。

相關文章
相關標籤/搜索