Quartz動態設置併發數量

  quartz存在一個問題,當正在進行的任務已經達到了設置的個數,後續觸發的任務沒有線程可用,會導致系統宕機;

  Quartz通過StdSchedulerFactory工廠創建調度器,initialize方法通過解析quartz.properties配置信息進行加載,默認線程個數爲10,可以通過覆蓋信息定義線程個數,通過Apollo信息進行線程個數配置

            Scheduler scheduler = (new StdSchedulerFactory()).getScheduler();
            //獲取Apollo配置信息
            Config config = ConfigService.getConfig("application");
            String threadCount = config.getProperty("org.quartz.threadPool.threadCount", "");
            //對quartz.properties配置信息進行覆蓋
            Properties props = new Properties();
            InputStream in = TaskScheduleServiceImpl.class.getClassLoader().getResourceAsStream("quartz.properties");
            props.load(in);
            String threadCountProperties = props.get("org.quartz.threadPool.threadCount").toString();
            if ("".equals(threadCount)) {
                if (!threadCount.equals(threadCountProperties)) {
                    props.setProperty("org.quartz.threadPool.threadCount", threadCount);
                    //重新創建調度器
                    StdSchedulerFactory stdSchedulerFactory = new StdSchedulerFactory();
                    stdSchedulerFactory.initialize(props);
                    //關閉原先調度器
                    scheduler.shutdown();
                    scheduler = stdSchedulerFactory.getScheduler();
                    in.close();
                }
            } 

  上面代碼是在系統初始化中執行的,若想實現系統運行中進行動態擴容/縮容調度器線程池大小,可以加一個flag標誌進行判斷,通過獲取當前系統正在執行的任務個數和系統定義的總數進行對比,當達到一定個數或一定比例時,再次調用上面代碼進行動態擴容/縮容。

  上面代碼存在的問題是當關閉調度器時,會殺死原先存在正在進行的任務,這是不友好的操作,可以添加一箇中間件(Redis),將每次觸發執行的任務加入Redis中,執行完從Redis刪除,所以每次系統重啓都從Redis讀取數據,對任務重新執行,執行完再將其從Redis刪除,同時爲了保證任務的唯一性(集羣環境下不管是定時還是立即執行),需要對任務進行加鎖操作,由於只需要保證同一時刻只能有一個任務在運行,保證高可用而不追求強一致性,所以選擇的是Redis分佈式鎖Redisson,根據先到先得策略使用了Redisson的公平鎖。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章