詳解Quartz集群

隨着業務量的增長,單機版Quartz已經難以應對分佈式任務管理的需求,此時集群版Quartz就迎刃而解了。集群版Quartz的優點是可以將多台機器作為工作節點來執行任務,這個方案可以提高任務的可靠性、性能和吞吐量。接下來,將從多個方面詳細介紹集群版Quartz的實現原理和使用方法。

一、配置文件

Quartz集群的配置可以放在屬性文件中,集群中每個節點都需要使用相同的配置文件。下面是一個簡單的示例:

org.quartz.scheduler.instanceName = MyClusteredScheduler
org.quartz.scheduler.instanceId = AUTO
org.quartz.jobStore.isClustered = true
org.quartz.jobStore.clusterCheckinInterval = 20000
org.quartz.threadPool.class = org.quartz.simpl.SimpleThreadPool
org.quartz.threadPool.threadCount = 25
org.quartz.threadPool.threadPriority = 5

其中,”org.quartz.scheduler.instanceName”和”org.quartz.scheduler.instanceId”是必須的。

二、消息通訊

Quartz集群依靠JDBC或者RMI方式進行消息通訊,以實現不同節點之間的任務調度信息共享。在消息通訊的過程中,需要注意下面的事項:

1、消息通訊組件不能夠出現重複id的節點;

2、消息通訊組件的狀態一定要準確。

同時,集群中所有節點的數據庫連接信息必須相同。

三、任務執行原則

在Quartz集群模型中,所有的任務都必須實現Job接口,並且該接口應該是StatefulJob的子接口。StatefulJob接口要求任務必須是有狀態的並且支持並發執行。這個要求是Quartz集群正常運行必須遵守的規則,並且可以通過實現StatefulJob接口來實現。

為了確保任務被正確分配到集群中各個節點,我們需要在任務類的添加註解@PersistJobDataAfterExecution。這個註解會在執行任務之前保存任務當前狀態,並在任務執行完成後更新狀態到數據庫。這種方式可以確保任務能夠正確的在不同節點之間傳遞。

四、任務負載均衡

任務負載均衡是Quartz集群中特別重要的一個方面。Quartz使用平衡負載策略以確保在集群中任務的平衡的分配。

四種負載均衡策略如下:

1、默認的負載均衡策略:按照最近的一次執行時間靠前的優先被執行;

2、Round Robin策略:所有節點輪流執行任務,每個節點會輪流執行一次。

3、隨機策略:隨機挑選一個節點去執行任務。

4、基於權重的策略:按照節點配置的權重來分配任務,權重大的節點分配到的任務數量也會比較多。

下面是一個TaskDispatchSelector的示例,可以用來選擇節點:

public class TaskDispatchSelector implements LoadBalanceTaskDispatcher{

    public void dispatchTask(List ctxs) {

        JobExecutionContext selectedContext = null;
        try {
            //......

            //根據權重選擇節點
            selectedContext = new WeightedLoadBalancedScheduler().instanceIdSchedulerMap.entrySet().stream().max(Comparator.comparingInt((entry) -> entry.getValue().getThreadPool().getBusyThreadCount())).get().getValue().getContext();

            //......

            selectedContext.getScheduler().triggerJob(selectedContext.getJobDetail().getKey());
        } catch (Exception e) {
            throw new MyException("Dispatch Quartz Task Fail.", e);
        }
    }
}

五、運行模式

可以在兩種運行模式之間切換:

1、只讀模式:節點向集群中獲取任務並執行。

2、讀寫模式:節點不僅獲取任務,還會去分配或者刪除任務。

可以使用JobStoreCMT來實現讀寫模式。下面是一個JobFactory實現的示例:

public class JobFactory extends AdaptableJobFactory {

    @Autowired
    ApplicationContext applicationContext;

    /**
     * 實例化任務類
     * @param bundle
     * @param method
     * @return
     * @throws Exception
     */
    protected Object createJobInstance(TriggerFiredBundle bundle) throws Exception {
        JobDetail jobDetail = bundle.getJobDetail();
        Class jobClass = jobDetail.getJobClass();
        return applicationContext.getBean(jobClass);
    }
}

六、集群初始化及關閉

對於集群的初始化,需要確保所有節點都按照相同的配置啟動JobScheduler。關閉集群時需要調用shutdown()方法,不要在代碼中手動關閉Scheduler。

下面是一個啟動和關閉Quartz集群的示例:

public class QuartzClusterRunner {

    public void start() {
        try {
            // 初始化Quartz
            SchedulerFactory sf = new StdSchedulerFactory("quartz.properties");
            Scheduler scheduler = sf.getScheduler();

            //監聽Quartz scheduler的啟動與關閉事件,和job調度事件
            scheduler.getListenerManager().addSchedulerListener(new MySchedulerListenerAdapter());

            scheduler.start();
            LOGGER.info("Quartz Scheduler started...");

        } catch (Throwable e) {
            LOGGER.error("Quartz Scheduler start error: {}", e.getMessage(), e);
        }
    }

    public void stop() {
        try {
            LOGGER.info("Shutting Quartz Scheduler down...");
            SchedulerFactory sf = new StdSchedulerFactory();  //注意這裡沒有指定屬性文件
            Scheduler scheduler = sf.getScheduler();
            scheduler.shutdown();
            LOGGER.info("Quartz Scheduler shut down.");
        } catch (Throwable e) {
            LOGGER.error("Quartz Scheduler stop error: {}", e.getMessage(), e);
        }
    }
}

致謝

本文檔參考了官方文檔和網上的一些文章,特此致謝:

1、Quartz官方文檔:

http://www.quartz-scheduler.org/

2、博客:

http://blog.csdn.net/endymionwang/article/details/7329144

http://gold.xitu.io/entry/5691b98c60b2ff006f6d741d

原創文章,作者:MSZXV,如若轉載,請註明出處:https://www.506064.com/zh-hk/n/371817.html

(0)
打賞 微信掃一掃 微信掃一掃 支付寶掃一掃 支付寶掃一掃
MSZXV的頭像MSZXV
上一篇 2025-04-23 18:08
下一篇 2025-04-23 18:08

相關推薦

  • 使用Go-Redis獲取Redis集群內存使用率

    本文旨在介紹如何使用Go-Redis獲取Redis集群的內存使用率。 一、Go-Redis簡介 Go-Redis是一個用於連接Redis服務器的Golang客戶端。它支持Redis…

    編程 2025-04-28
  • Redis5.0集群擴容用法介紹

    Redis是一個內存數據庫,越來越受到開發者的歡迎。在開發中,我們經常需要考慮Redis集群的擴容問題。而Redis5.0針對集群擴容方面進行了多項優化和改進,本文將從多個方面詳細…

    編程 2025-04-27
  • 神經網絡代碼詳解

    神經網絡作為一種人工智能技術,被廣泛應用於語音識別、圖像識別、自然語言處理等領域。而神經網絡的模型編寫,離不開代碼。本文將從多個方面詳細闡述神經網絡模型編寫的代碼技術。 一、神經網…

    編程 2025-04-25
  • Linux sync詳解

    一、sync概述 sync是Linux中一個非常重要的命令,它可以將文件系統緩存中的內容,強制寫入磁盤中。在執行sync之前,所有的文件系統更新將不會立即寫入磁盤,而是先緩存在內存…

    編程 2025-04-25
  • Python輸入輸出詳解

    一、文件讀寫 Python中文件的讀寫操作是必不可少的基本技能之一。讀寫文件分別使用open()函數中的’r’和’w’參數,讀取文件…

    編程 2025-04-25
  • Python安裝OS庫詳解

    一、OS簡介 OS庫是Python標準庫的一部分,它提供了跨平台的操作系統功能,使得Python可以進行文件操作、進程管理、環境變量讀取等系統級操作。 OS庫中包含了大量的文件和目…

    編程 2025-04-25
  • nginx與apache應用開發詳解

    一、概述 nginx和apache都是常見的web服務器。nginx是一個高性能的反向代理web服務器,將負載均衡和緩存集成在了一起,可以動靜分離。apache是一個可擴展的web…

    編程 2025-04-25
  • git config user.name的詳解

    一、為什麼要使用git config user.name? git是一個非常流行的分佈式版本控制系統,很多程序員都會用到它。在使用git commit提交代碼時,需要記錄commi…

    編程 2025-04-25
  • 詳解eclipse設置

    一、安裝與基礎設置 1、下載eclipse並進行安裝。 2、打開eclipse,選擇對應的工作空間路徑。 File -> Switch Workspace -> [選擇…

    編程 2025-04-25
  • Linux修改文件名命令詳解

    在Linux系統中,修改文件名是一個很常見的操作。Linux提供了多種方式來修改文件名,這篇文章將介紹Linux修改文件名的詳細操作。 一、mv命令 mv命令是Linux下的常用命…

    編程 2025-04-25

發表回復

登錄後才能評論