精品欧美一区二区三区在线观看 _久久久久国色av免费观看性色_国产精品久久在线观看_亚洲第一综合网站_91精品又粗又猛又爽_小泽玛利亚一区二区免费_91亚洲精品国偷拍自产在线观看 _久久精品视频在线播放_美女精品久久久_欧美日韩国产成人在线

項目終于用上了 xxl-job!

開發 前端
不知不覺寫了這么多,從 xxl-job 的基礎介紹,到實戰部署、核心功能、進階技巧,再到最佳實踐和踩坑經驗,應該把 xxl-job 的核心內容都覆蓋到了。

兄弟們,最近咱們項目終于跟 “定時任務” 的那些破事兒徹底說拜拜了 ,因為咱們上了 xxl-job!

說實話,在沒? xxl-job 之前,我跟定時任務的恩怨情仇能寫?本?說。最開始用 Timer 的時候,那叫?個心驚膽戰,服務器?重啟,之前排好的任務跟失憶了似的,全沒了;后來換成 ScheduledExecutorService,雖然比 Timer 穩點,但集群環境下又掉坑里了 —— 好幾個節點同時跑同一個任務,數據直接亂套,查問題的時候我跟個偵探似的,對著日志翻了半宿,最后發現是沒做分布式鎖;再后來試過自己寫 quartz 集群,配置文件改得我頭都大了,而且監控和日志還得自己搭,折騰半天效果還不咋地。

直到某天跟隔壁項目的老周吃飯,他跟我吹 “我們項目用 xxl-job,定時任務那叫一個絲滑,啥重啟丟失、集群重復執行的問題都沒有,監控日志還全給你整得明明白白”,我當時眼睛一亮,回來就拉著團隊調研,這不,沒多久就給項目安排上了,用了快一個月,真心覺得 “早用早香”!

今天就跟大家好好嘮嘮 xxl-job,從它是啥、怎么搭、怎么用,到實際項目里的坑和技巧,全給你們扒得明明白白,保證小白能看懂,老鳥能撿著干貨。

一、先搞明白:xxl-job 到底是個啥?

可能還有兄弟沒接觸過 xxl-job,先給大家用大白話科普下。xxl-job 是個開源的分布式任務調度框架,作者是許雪里(xxl 就是他名字的首字母縮寫),這框架在 GitHub 上星標都快 3 萬了,國內很多公司都在用,穩定性不用多說。

簡單說,它就是幫咱們搞定 “定時干活” 的工具,而且是 “分布式” 的 —— 比如你有 10 臺服務器,想讓某個任務每天凌晨 2 點在其中一臺上跑,或者讓 10 臺服務器分攤不同的任務,xxl-job 都能給你安排得明明白白。

對比咱們之前用的那些 “土方法”,xxl-job 的優勢簡直太明顯了:

  1. 不用自己折騰集群:之前自己搭 quartz 集群,要配置數據庫、改數據源,還得擔心節點同步問題,xxl-job 自帶集群支持,改倆配置就行;
  2. 有現成的監控和日志:之前查任務執行情況,得登錄服務器翻日志文件,xxl-job 在網頁上就能看任務執行狀態、失敗原因,甚至能看完整日志,省了我好多時間;
  3. 支持多種任務類型:不光能執行 Java 代碼里的方法,還能直接在網頁上寫 Groovy 腳本(GLUE 模式),改任務邏輯不用重新打包部署,簡直是迭代神器;
  4. 容錯性強:任務執行失敗了能自動重試,執行器掛了調度中心會報警,再也不用半夜被運維電話叫醒說 “任務沒跑起來” 了。

這么說吧,之前處理定時任務我得 “天天盯著”,現在用上 xxl-job,我基本不用管,偶爾看眼監控就行,摸魚時間都變多了(這話可別讓領導看見)。

二、實戰第一步:把 xxl-job 搭起來

光說不練假把式,咱們直接上實戰 —— 怎么把 xxl-job 的調度中心和執行器搭起來。別擔心,步驟很簡單,跟著走就行。

2.1 先準備環境(這些都是基礎,別偷懶)

首先得有這幾樣東西,沒有的先裝上:

  • JDK:1.8 及以上(咱們 Java 項目基本都是 1.8,高版本也兼容,別用太老的就行);
  • MySQL:5.7 及以上(xxl-job 要存調度信息、任務配置這些,得有個數據庫);
  • Maven:3.0 及以上(用來編譯源碼,打包項目);
  • 一個 Spring Boot 項目(咱們實際開發基本都是 Spring Boot,這里就以 Spring Boot 為例,非 Spring Boot 項目后面也會提一嘴)。

2.2 部署調度中心(相當于 “指揮中心”)

調度中心就是 xxl-job 的 “大腦”,所有任務的配置、調度邏輯都在這兒,還能看監控和日志。部署起來特別簡單,分三步:

第一步:下載源碼

直接去 GitHub 下 xxl-job 的源碼,地址是:https://github.com/xuxueli/xxl-job 。建議下最新的穩定版,別追更到開發版,萬一有 bug 就麻煩了。

下完之后解壓,用 IDEA 打開,項目結構很清晰,主要看這兩個模塊:

  • xxl-job-admin:這就是調度中心,是個 Spring Boot 項目;
  • xxl-job-executor-samples:執行器的示例,里面有 Spring Boot、Spring、非 Spring 的示例,咱們后面會參考這個寫自己的執行器。

第二步:初始化數據庫

調度中心需要數據庫存數據,源碼里已經給咱們準備好了 SQL 腳本,路徑在xxl-job/doc/db/tables_xxl_job.sql。

打開 MySQL,新建一個數據庫(比如叫xxl_job),然后執行這個 SQL 腳本。執行完之后會生成 8 張表,不用管這些表是干嘛的,反正 xxl-job 自己會用,咱們只要保證表建好了就行。

這里提醒一句:別改表名和字段名,不然調度中心會報錯,到時候排查起來很麻煩。

第三步:改配置、編譯、啟動

打開xxl-job-admin模塊下的application.properties文件,主要改三個地方:

1.數據庫連接:把spring.datasource.url、spring.datasource.username、spring.datasource.password改成你自己的 MySQL 地址、用戶名和密碼。比如我的配置是這樣的:

spring.datasource.url=jdbc:mysql://127.0.0.1:3306/xxl_job?useUnicode=true&characterEncoding=UTF-8&autoReconnect=true&serverTimezone=Asia/Shanghai
spring.datasource.username=root
spring.datasource.password=123456

這里注意,URL 后面要加serverTimezone=Asia/Shanghai,不然可能會報時區錯誤,踩過這個坑的兄弟應該懂。

2.端口號:默認是 8080,要是你本地 8080 被占了(比如 Tomcat),就改成別的,比如 8081,改server.port就行。

3.登錄密碼:默認的登錄賬號是 admin,密碼是 123456,要是想改密碼,后面登錄之后在網頁上改更方便,這里先不用動。

改完配置之后,就可以編譯打包了。在 IDEA 的 Terminal 里執行mvn clean package -Dmaven.test.skip=true,等編譯完成,在xxl-job-admin/target目錄下會生成一個 jar 包,比如xxl-job-admin-2.4.0.jar(版本號可能不一樣)。

然后執行java -jar xxl-job-admin-2.4.0.jar啟動調度中心。啟動成功之后,打開瀏覽器訪問http://localhost:8080/xxl-job-admin(端口號跟你配置的一致),能看到登錄頁面,輸入 admin/123456 登錄,就說明調度中心部署成功了!

登錄之后的界面很直觀,左邊有任務管理、執行器管理、監控報表這些菜單,后面咱們會一個個用到。

2.3 開發執行器(相當于 “干活的小弟”)

調度中心是 “指揮中心”,那執行器就是 “干活的小弟”—— 實際的任務邏輯(比如同步數據、清理日志)都是在執行器里寫的,執行器會注冊到調度中心,等著調度中心發指令來執行任務。

咱們以 Spring Boot 項目為例,寫一個自己的執行器,分四步:

第一步:引入依賴

在自己的 Spring Boot 項目的 pom.xml 里,引入 xxl-job 的執行器依賴。注意版本要跟調度中心的版本一致,不然可能有兼容性問題:

<dependency>
    <groupId>com.xuxueli</groupId>
    <artifactId>xxl-job-core</artifactId>
    <version>2.4.0</version> <!-- 跟調度中心版本一致 -->
</dependency>

第二步:加配置

在application.yml(或者 application.properties)里加執行器的配置,我習慣用 yml,看著更清晰:

xxl:
  job:
    admin:
      # 調度中心的地址,要是調度中心是集群,就用逗號分隔,比如http://127.0.0.1:8080/xxl-job-admin,http://127.0.0.1:8081/xxl-job-admin
      addresses: http://127.0.0.1:8080/xxl-job-admin
    executor:
      # 執行器的名稱,這個很重要,后面在調度中心配置任務的時候要用到,必須一致
      appname: xxl-job-executor-demo
      # 執行器的IP地址,默認不用填,會自動獲取,要是有多網卡可以指定
      ip:
      # 執行器的端口號,默認是9999,要是啟動多個執行器,端口號要不一樣
      port: 9999
      # 執行器的日志路徑,默認是/data/applogs/xxl-job/jobhandler,也可以自己改
      logpath: /data/applogs/xxl-job/jobhandler
      # 執行器日志的保存天數,默認7天,超過會自動刪除
      logretentiondays: 30
    # 訪問令牌,要是調度中心配置了令牌,這里就要填一樣的,默認沒有,不用填
    accessToken:

這里有幾個坑要注意:

  • 執行器的 appname 必須跟后面在調度中心配置的一致,不然執行器注冊不上;
  • 要是啟動多個執行器(集群),port 必須不一樣,比如第一個 9999,第二個 10000;
  • 調度中心的 addresses 要是集群,一定要寫全,不然執行器可能只注冊到一個調度中心節點。

第三步:寫配置類

新建一個配置類,比如XxlJobConfig,用來初始化執行器的客戶端,代碼直接抄示例就行,不用改太多:

import com.xxl.job.core.executor.impl.XxlJobSpringExecutor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class XxlJobConfig {
    private Logger logger = LoggerFactory.getLogger(XxlJobConfig.class);
    @Value("${xxl.job.admin.addresses}")
    private String adminAddresses;
    @Value("${xxl.job.executor.appname}")
    private String appname;
    @Value("${xxl.job.executor.ip}")
    private String ip;
    @Value("${xxl.job.executor.port}")
    private int port;
    @Value("${xxl.job.accessToken}")
    private String accessToken;
    @Value("${xxl.job.executor.logpath}")
    private String logPath;
    @Value("${xxl.job.executor.logretentiondays}")
    private int logRetentionDays;
    @Bean
    public XxlJobSpringExecutor xxlJobExecutor() {
        logger.info(">>>>>>>>>>> xxl-job executor init.");
        XxlJobSpringExecutor xxlJobSpringExecutor = new XxlJobSpringExecutor();
        xxlJobSpringExecutor.setAdminAddresses(adminAddresses);
        xxlJobSpringExecutor.setAppname(appname);
        xxlJobSpringExecutor.setIp(ip);
        xxlJobSpringExecutor.setPort(port);
        xxlJobSpringExecutor.setAccessToken(accessToken);
        xxlJobSpringExecutor.setLogPath(logPath);
        xxlJobSpringExecutor.setLogRetentionDays(logRetentionDays);
        return xxlJobSpringExecutor;
    }
}

第四步:寫實際的任務邏輯

這一步是核心,咱們寫個簡單的任務,比如 “每隔 5 秒打印一次當前時間”,再寫個實際業務中常用的 “定時同步用戶數據” 的任務。

新建一個任務類,比如DemoJobHandler,用@XxlJob注解標記任務方法,注解里的 value 就是任務的標識,后面在調度中心配置的時候要用到:

import com.xxl.job.core.context.XxlJobHelper;
import com.xxl.job.core.handler.annotation.XxlJob;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import java.text.SimpleDateFormat;
import java.util.Date;
@Component
public class DemoJobHandler {
    private static final Logger logger = LoggerFactory.getLogger(DemoJobHandler.class);
    // 任務1:每隔5秒打印當前時間
    @XxlJob("printTimeJob")
    public void printTimeJob() {
        // XxlJobHelper.log()是xxl-job提供的日志方法,打印的日志能在調度中心看到
        XxlJobHelper.log("printTimeJob start...");
        try {
            // 獲取當前時間
            String currentTime = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date());
            // 打印時間
            logger.info("當前時間:{}", currentTime);
            XxlJobHelper.log("當前時間:{}", currentTime);
            // 任務執行成功,不用寫這個也會默認成功,要是失敗了要拋異常或者調用XxlJobHelper.handleFail()
            XxlJobHelper.handleSuccess("任務執行成功");
        } catch (Exception e) {
            // 任務執行失敗,記錄日志并標記失敗
            XxlJobHelper.log("任務執行失敗:{}", e.getMessage());
            XxlJobHelper.handleFail("任務執行失敗");
        }
    }
    // 任務2:定時同步用戶數據(模擬實際業務)
    @XxlJob("syncUserJob")
    public void syncUserJob() {
        XxlJobHelper.log("syncUserJob start...");
        try {
            // 1. 獲取需要同步的用戶數據(這里模擬從數據庫查詢)
            XxlJobHelper.log("開始查詢需要同步的用戶數據...");
            // 模擬查詢到10條數據
            int userCount = 10;
            XxlJobHelper.log("查詢到{}條需要同步的用戶數據", userCount);
            // 2. 同步用戶數據到目標系統(這里模擬調用接口)
            XxlJobHelper.log("開始同步用戶數據...");
            for (int i = 1; i <= userCount; i++) {
                XxlJobHelper.log("正在同步第{}條用戶數據...", i);
                // 模擬同步耗時
                Thread.sleep(100);
            }
            // 3. 同步完成,更新同步狀態(這里模擬更新數據庫)
            XxlJobHelper.log("用戶數據同步完成,共同步{}條", userCount);
            XxlJobHelper.handleSuccess("用戶數據同步成功,共同步" + userCount + "條");
        } catch (Exception e) {
            XxlJobHelper.log("用戶數據同步失敗:{}", e.getMessage());
            XxlJobHelper.handleFail("用戶數據同步失敗:" + e.getMessage());
        }
    }
}

這里要注意:

  • 任務方法的返回值可以是 void,也可以是 String,但推薦用 void,然后通過XxlJobHelper.handleSuccess()或XxlJobHelper.handleFail()來標記任務狀態;
  • 日志一定要用XxlJobHelper.log(),這樣在調度中心的 “任務日志” 里才能看到,用自己項目的 logger 也能打印,但得去執行器的日志文件里看,不方便;
  • 要是任務執行失敗,一定要拋異常或者調用XxlJobHelper.handleFail(),不然調度中心會認為任務執行成功,到時候出問題了都不知道。

第五步:啟動執行器并驗證注冊

寫完代碼之后,啟動 Spring Boot 項目。啟動成功之后,去調度中心的 “執行器管理” 頁面,就能看到咱們配置的執行器(xxl-job-executor-demo),而且 “在線機器地址” 里會顯示執行器的 IP 和端口,狀態是 “在線”,這就說明執行器注冊成功了!

要是沒注冊上,別慌,先檢查這幾點:

  1. 執行器的 appname 是不是跟調度中心里的一致;
  2. 調度中心的 addresses 是不是寫對了;
  3. 執行器的端口是不是被占用了;
  4. 看執行器的日志,有沒有報 “注冊失敗” 的錯誤,比如連接不上調度中心、令牌不一致等。

三、核心功能詳解:xxl-job 能幫咱們干哪些活?

部署好調度中心和執行器之后,咱們就該用 xxl-job 來配置任務了。調度中心的 “任務管理” 頁面是核心,這里能配置任務、啟動 / 停止任務、查看日志,咱們一個個說。

3.1 配置一個任務(以 printTimeJob 為例)

點擊 “任務管理”->“新增”,會彈出一個表單,里面的字段很多,但關鍵的就幾個,咱們一個個填:

  • 執行器:選擇咱們之前注冊的執行器(xxl-job-executor-demo);
  • 任務描述:寫清楚這個任務是干嘛的,比如 “每隔 5 秒打印當前時間”,別寫 “任務 1”,不然過倆月你自己都忘了;
  • 調度類型:選 “CRON”,這是最常用的,支持復雜的定時規則;
  • CRON 表達式:比如 “*/5 * * * * ?”,表示每隔 5 秒執行一次。要是不會寫 CRON 表達式,調度中心里有個 “CRON 表達式生成器”,點進去選就行,特別方便;
  • 任務參數:要是任務需要參數,可以在這里填,比如同步用戶數據的任務需要填 “同步日期 = 2024-05-20”,后面在任務方法里可以通過XxlJobHelper.getJobParam()獲取;
  • 執行器路由策略:選 “第一個” 就行,后面再講其他策略;
  • 調度過期策略:選 “忽略”,意思是要是任務因為某種原因過期了(比如執行器掛了,恢復后發現該執行的任務沒執行),就忽略,不補執行;
  • 阻塞處理策略:選 “單機串行”,意思是要是上一個任務還沒執行完,下一個任務就等著,別并發執行;
  • 失敗重試次數:選 1,意思是任務執行失敗后,再重試 1 次;
  • 任務超時時間:填 0,意思是不超時,要是有超時需求可以填具體時間(毫秒),比如 300000 表示 5 分鐘超時,超時后任務會被強制終止;
  • GLUE 類型:選 “BEAN”,意思是任務邏輯在執行器的 Java 代碼里(就是咱們寫的@XxlJob方法),后面再講 “GLUE” 類型;
  • GLUE 備注:不用填;
  • 執行參數:不用填;
  • Misfire 策略:選 “默認” 就行。

填完之后點 “保存”,然后在任務列表里找到這個任務,點擊 “啟動”,任務就開始執行了!

3.2 查看任務執行情況和日志

任務啟動后,怎么知道它有沒有在執行呢?有兩個地方可以看:

  1. 任務列表的 “上次執行時間” 和 “下次執行時間”:要是 “上次執行時間” 在不斷更新,說明任務在正常執行;
  2. “調度日志” 頁面:這里能看到每個任務的調度記錄,包括調度時間、調度結果、執行器地址等。要是調度結果是 “成功”,說明調度中心成功把任務指令發給了執行器;要是 “失敗”,會顯示失敗原因,比如執行器離線、路由策略找不到執行器等。

要是想查看任務執行的詳細日志,點擊任務列表里的 “日志” 按鈕,就能進入 “任務日志” 頁面。這里能看到每次任務執行的日志,包括XxlJobHelper.log()打印的內容,還有執行結果(成功 / 失敗)、執行時間、耗時等。要是任務執行失敗,日志里會顯示錯誤信息,直接就能定位問題,不用再去執行器的服務器上翻日志了,這一點真的太香了!

3.3 常用的核心功能講解

除了上面說的基本配置,xxl-job 還有很多實用的功能,咱們挑幾個常用的講講:

3.3.1 執行器路由策略(集群環境下必用)

當執行器是集群(多個執行器節點)的時候,調度中心會根據 “路由策略” 來決定把任務發給哪個執行器。常用的路由策略有:

  • 第一個:總是把任務發給集群里的第一個執行器;
  • 最后一個:總是把任務發給集群里的最后一個執行器;
  • 輪詢:按順序把任務發給每個執行器,比如第一個任務發給節點 1,第二個發給節點 2,第三個再發給節點 1,適合負載均衡;
  • 隨機:隨機把任務發給某個執行器,適合對執行器沒有特殊要求的場景;
  • 一致性 HASH:根據任務參數的 HASH 值來選擇執行器,同一個參數的任務會發給同一個執行器,適合需要任務冪等的場景,比如根據用戶 ID 同步數據,同一個用戶的任務總是發給同一個執行器,避免重復同步;
  • 最不經常使用:把任務發給最近執行任務最少的執行器,適合負載不均的場景;
  • 最近最久未使用:把任務發給最近最久沒執行任務的執行器,也適合負載均衡;
  • 故障轉移:先選一個執行器發任務,要是失敗了就換下一個,直到成功,適合對任務執行成功率要求高的場景;
  • 忙碌轉移:先檢查執行器的狀態,要是執行器忙碌(有任務在執行),就換下一個,適合不想讓執行器過載的場景。

實際項目中,最常用的是 “輪詢” 和 “一致性 HASH”,根據業務場景選就行。比如咱們的同步用戶數據任務,用 “輪詢” 就能讓多個執行器分攤任務,提高效率;要是任務需要根據參數冪等,就用 “一致性 HASH”。

3.3.2 GLUE 模式(改任務邏輯不用重新部署)

之前咱們配置任務的時候,GLUE 類型選的是 “BEAN”,意思是任務邏輯在執行器的 Java 代碼里,要是改任務邏輯,就得改代碼、重新打包、部署執行器,很麻煩。

而 “GLUE” 模式(支持 Java、Python、NodeJS、PHP、Shell)就不一樣了 —— 任務邏輯直接寫在調度中心的網頁上,改完之后不用部署執行器,直接生效!

比如咱們寫一個 Shell 腳本的 GLUE 任務,步驟是:

  • 新增任務,GLUE 類型選 “GLUE (Shell)”;
  • 點擊任務列表里的 “GLUE” 按鈕,進入 GLUE 編輯頁面,寫 Shell 腳本,比如:
#!/bin/bash
echo "當前時間:$(date +%Y-%m-%d\ %H:%M:%S)"
echo "這是一個GLUE Shell任務"
  • 保存腳本,啟動任務,然后查看日志,就能看到腳本執行的結果。

要是想改腳本,直接在網頁上改,保存之后下一次任務執行就會用新腳本,不用動執行器的代碼。這個模式特別適合經常改邏輯的簡單任務,比如清理日志、備份數據這些,省了很多部署的時間。

不過要注意,GLUE 模式適合簡單任務,復雜的業務邏輯還是建議用 BEAN 模式,放在執行器里寫,方便調試和維護。

3.3.3 失敗重試和報警(不用半夜盯任務)

之前咱們配置任務的時候,填了 “失敗重試次數”,比如填 1,意思是任務執行失敗后,調度中心會再重試 1 次。這個功能能避免很多偶發的失敗,比如網絡波動、數據庫臨時不可用等,提高任務執行的成功率。

要是重試之后還是失敗,怎么辦呢?xxl-job 支持報警功能,能把失敗信息發給指定的人,比如通過郵件、釘釘、企業微信等。

配置報警的步驟也很簡單:

  • 先在調度中心的 “系統管理”->“報警組管理” 里新建一個報警組,填報警組名稱,然后添加接收報警的郵箱(支持多個,用逗號分隔);
  • 在 “任務管理” 里編輯任務,把 “報警郵件” 選成咱們新建的報警組;
  • 當任務執行失敗(包括重試后失敗),調度中心就會給報警組里的郵箱發郵件,郵件里會包含任務名稱、執行時間、失敗原因等信息。

要是想支持釘釘或企業微信報警,需要自己寫報警處理器,實現com.xxl.job.core.alarm.JobAlarm接口,然后在調度中心的配置里注冊這個處理器,網上有很多現成的示例,照著改就行。

有了報警功能,再也不用半夜盯著任務了,要是任務失敗,郵件會直接發給你,第二天上班處理就行(前提是領導允許你第二天處理,哈哈)。

3.3.4 任務依賴(先執行 A 任務,再執行 B 任務)

有時候咱們的任務有依賴關系,比如必須先執行 “同步用戶數據” 任務(A 任務),再執行 “同步用戶訂單數據” 任務(B 任務),這時候就需要用 xxl-job 的 “任務依賴” 功能。

配置任務依賴的步驟:

  1. 先確保 A 任務已經存在;
  2. 新增 B 任務的時候,在 “任務依賴” 字段里選擇 A 任務;
  3. 保存之后,B 任務會在 A 任務執行成功之后才會執行;要是 A 任務執行失敗,B 任務就不會執行。

這個功能特別適合有先后順序的任務,比如數據同步場景,必須先同步基礎數據,再同步關聯數據,不然會出現數據缺失的問題。

四、進階技巧:讓 xxl-job 用得更順手

咱們已經會用 xxl-job 的基本功能了,但在實際項目中,還有一些進階技巧能讓 xxl-job 用得更順手,比如監控、集群部署、性能優化等。

4.1 監控報表(一眼看清任務狀態)

調度中心的 “監控報表” 頁面特別實用,能看到任務的執行情況、失敗統計、執行器狀態等,主要有三個報表:

  1. 任務執行報表:按天統計任務的執行次數、成功次數、失敗次數、平均耗時,能直觀看到任務的執行趨勢;
  2. 任務失敗報表:統計最近失敗的任務,包括任務名稱、失敗時間、失敗原因,能快速定位問題任務;
  3. 執行器報表:統計每個執行器的在線狀態、任務執行次數、平均耗時,能看到執行器的負載情況。

每天上班先看一眼監控報表,就能知道昨天的任務有沒有問題,執行器是不是正常,不用一個個去查任務日志,省了很多時間。

4.2 調度中心集群(保證高可用)

調度中心是 xxl-job 的核心,要是調度中心掛了,所有任務都沒法執行,所以必須做集群部署,保證高可用。

調度中心集群部署特別簡單,步驟是:

  • 準備兩臺(或多臺)服務器,都部署調度中心(步驟跟之前一樣);
  • 所有調度中心都連接同一個 MySQL 數據庫(因為任務配置、調度記錄都存在數據庫里,必須共享);
  • 在前面加一個 Nginx,做負載均衡,把請求分發到各個調度中心節點。

Nginx 的配置示例:

upstream xxl-job-admin {
    server 192.168.1.100:8080; # 調度中心節點1
    server 192.168.1.101:8080; # 調度中心節點2
}
server {
    listen 80;
    server_name xxl-job-admin.example.com; # 自己的域名
    location / {
        proxy_pass http://xxl-job-admin;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
    }
}

這樣一來,就算其中一個調度中心節點掛了,另一個還能正常工作,任務調度不會受影響。而且執行器配置調度中心地址的時候,直接填 Nginx 的地址(比如http://xxl-job-admin.example.com/xxl-job-admin)就行,不用填所有節點的地址。

4.3 執行器集群(提高任務執行效率)

當任務量很大的時候,單個執行器可能處理不過來,這時候就需要部署執行器集群,多個執行器一起干活,提高效率。

執行器集群部署也很簡單:

  • 準備兩臺(或多臺)服務器,都部署同一個執行器(代碼一樣);
  • 所有執行器的 appname 必須一致(不然調度中心會認為是不同的執行器);
  • 所有執行器的 port 不一樣(比如節點 1 是 9999,節點 2 是 10000);
  • 所有執行器的 admin.addresses 都填調度中心的地址(要是調度中心是集群,就填 Nginx 的地址)。

部署完成之后,去調度中心的 “執行器管理” 頁面,就能看到 “在線機器地址” 里有多個執行器節點,然后配置任務的時候,路由策略選 “輪詢”,就能讓多個執行器分攤任務了。

比如咱們的同步用戶數據任務,之前單個執行器同步 1000 條數據要 10 分鐘,部署兩個執行器之后,每個執行器同步 500 條,5 分鐘就能完成,效率直接翻倍。

4.4 性能優化(讓 xxl-job 跑得更快)

在高并發場景下,比如有上千個任務同時執行,xxl-job 可能會出現調度延遲、執行慢的問題,這時候就需要做一些性能優化:

  1. 優化數據庫:調度中心的數據庫是瓶頸之一,建議給常用的表(比如 xxl_job_qrtz_trigger_log、xxl_job_qrtz_fired_trigger)加索引,比如給 trigger_log 表的 job_id、trigger_time 字段加索引;另外,定期清理歷史日志,比如只保留 30 天的日志,避免表數據量太大導致查詢慢;
  2. 調整線程池參數:調度中心和執行器都有線程池,默認參數可能不夠用,可以根據實際情況調整。比如調度中心的xxl.job.admin.triggerpool.fast.max和xxl.job.admin.triggerpool.slow.max,分別表示快速任務和慢速任務的線程池大小,要是任務多,可以調大;執行器的線程池大小可以在配置類里設置,比如xxlJobSpringExecutor.setExecutorPoolCoreSize(10);
  3. 避免任務阻塞:要是任務執行時間太長(比如超過 1 小時),會占用執行器的線程,導致其他任務阻塞,建議把長任務拆成短任務,比如把 “同步一天的用戶數據” 拆成 “同步每小時的用戶數據”,每個任務執行時間短,不容易阻塞;
  4. 使用異步執行:要是任務不需要同步執行(比如發送通知、日志統計),可以在任務方法里用異步線程執行,比如用 Spring 的@Async注解,這樣任務方法能快速返回,釋放執行器的線程,提高并發能力。

五、實際項目中的最佳實踐和踩坑經驗

最后,跟大家分享一些實際項目中用 xxl-job 的最佳實踐和踩坑經驗,都是我踩過的坑,希望大家能避開。

5.1 最佳實踐

  1. 任務命名規范:任務名稱要清晰,能看出來是干嘛的,比如 “sync_user_data_daily”(每天同步用戶數據),別用 “task1”“job2” 這種模糊的名稱,不然時間長了沒人知道是干嘛的;
  2. 參數配置化:任務需要的參數(比如同步日期、同步數量)別硬編碼在代碼里,要么在任務配置的 “任務參數” 里填,要么存在配置中心(比如 Nacos、Apollo),這樣改參數不用改代碼;
  3. 任務冪等性:分布式任務一定要保證冪等性,比如同步用戶數據的時候,先查一下數據有沒有已經同步過,避免重復同步導致數據重復。可以用任務參數(比如同步日期 + 用戶 ID)作為唯一鍵,或者在數據庫里加唯一索引;
  4. 任務拆分:別把所有邏輯都放在一個任務里,比如 “同步用戶數據 + 同步訂單數據 + 發送通知”,應該拆成三個獨立的任務,這樣某個任務失敗了,不會影響其他任務,而且排查問題也方便;
  5. 定期檢查任務:每周或每月檢查一下任務的執行情況,看看有沒有長期失敗的任務、執行時間過長的任務,及時優化,避免問題積累。

5.2 踩坑經驗

  1. 調度中心和執行器時間不同步:之前遇到過任務到點不執行的問題,查了半天發現執行器服務器的時間比調度中心慢了 10 分鐘,調度中心認為任務該執行了,但執行器的時間還沒到,所以不執行。解決方法:所有服務器(包括調度中心和執行器)都配置 NTP 時間同步,保證時間一致;
  2. 任務參數有特殊字符:要是任務參數里有逗號、空格等特殊字符,在 BEAN 模式下用XxlJobHelper.getJobParam()獲取的時候會有問題,比如參數是 “startDate=2024-05-20,endDate=2024-05-21”,逗號會被當成參數分隔符。解決方法:把參數用 JSON 格式傳遞,比如 “{"startDate":"2024-05-20","endDate":"2024-05-21"}”,然后在代碼里解析 JSON;
  3. 執行器日志路徑不存在:要是執行器配置的 logpath 路徑不存在,執行器會啟動失敗。解決方法:啟動執行器之前,先創建好日志路徑,或者在配置里用默認路徑;
  4. CRON 表達式寫錯:比如想寫 “每天凌晨 2 點執行”,寫成了 “0 0 2 * * ?” 是對的,但寫成 “0 2 0 * * ?” 就錯了,會變成每天凌晨 0 點 2 分執行。解決方法:用調度中心的 “CRON 表達式生成器” 生成 CRON,生成之后先測試一下,比如把 CRON 改成 “*/1 * * * * ?”(每隔 1 秒執行),看任務是不是正常執行,沒問題再改成實際的 CRON;
  5. 調度中心集群沒共享數據庫:之前部署調度中心集群的時候,兩個節點連接了不同的 MySQL 數據庫,導致任務配置不同步,一個節點能看到任務,另一個節點看不到。解決方法:所有調度中心節點必須連接同一個 MySQL 數據庫,保證數據共享。

六、總結

不知不覺寫了這么多,從 xxl-job 的基礎介紹,到實戰部署、核心功能、進階技巧,再到最佳實踐和踩坑經驗,應該把 xxl-job 的核心內容都覆蓋到了。

說實話,xxl-job 真的是一個特別優秀的分布式任務調度框架,上手簡單,功能強大,穩定性好,而且開源免費,國內很多大公司都在使用,不用擔心后續維護問題。

責任編輯:武曉燕 來源: 石杉的架構筆記
相關推薦

2025-02-18 14:08:14

2025-05-26 09:31:23

2025-06-03 08:20:00

Feign微服務

2022-12-19 08:32:57

項目Feign框架

2020-07-17 09:33:39

CPU內存調度

2022-03-26 17:13:22

ElasticJobxxl-job分布式

2024-09-14 09:59:04

2022-12-13 08:29:13

項目插入式注解

2022-09-23 13:57:11

xxl-job任務調度中間件

2023-01-04 09:23:58

2025-06-27 09:31:25

2023-11-30 22:06:43

2024-09-09 08:11:12

2024-08-27 09:34:24

2025-08-05 01:45:00

XXL-JOB自動注冊運維

2024-12-04 10:47:26

2024-07-31 08:18:40

2021-12-26 19:07:51

MySQL存儲容器

2021-12-26 00:03:27

響應式編程異步

2022-01-27 08:44:58

調度系統開源
點贊
收藏

51CTO技術棧公眾號

国产日韩二区| 综合网中文字幕| 男女午夜激情视频| 在线视频1区2区| 国产福利精品一区二区| 91av在线网站| 女教师淫辱の教室蜜臀av软件| 麻豆国产精品| 色综合久久久久综合| 亚洲乱码一区二区三区| 亚洲黄色在线观看视频| 日韩高清不卡一区二区| 欧美国产日韩免费| 鲁丝一区二区三区| 91精品入口| 欧美亚洲综合色| 日韩成人三级视频| 岛国在线视频免费看| 丁香婷婷综合激情五月色| 国产精品第一视频| 国产一级片免费看| 久久一区二区三区喷水| 亚洲精品国产福利| 三级黄色片播放| 亚洲精品粉嫩美女一区| 亚洲一二三四区| 日本免费在线视频观看| 日本亚洲欧美| 处破女av一区二区| 亚洲a一级视频| 精品无码一区二区三区的天堂| 国产综合精品一区| www.亚洲成人| 日本免费www| 青青草原在线亚洲| 精品国产污污免费网站入口 | 亚洲国产一成人久久精品| 日韩大片在线观看视频| 潘金莲一级淫片aaaaa| 外国电影一区二区| 色成年激情久久综合| 日韩中文字幕在线免费| 欧美大胆的人体xxxx| 亚洲三级久久久| 自拍偷拍99| www.黄在线观看| 久久人人超碰精品| 久久久久久国产精品mv| 国产www视频| 国产精品一区在线观看乱码 | 欧美国产乱子伦| 欧美日韩国产一二| 男女av在线| 久久精品一区八戒影视| 欧美日韩国产不卡在线看| 人成免费电影一二三区在线观看| 99久久99久久精品国产片果冻| 国产女主播一区二区| 日本国产在线观看| 91一区在线观看| 国产日韩欧美一区二区| 人妻精品一区一区三区蜜桃91| 高清不卡在线观看av| 粉嫩高清一区二区三区精品视频| 亚洲国产精品久久久久久6q| 成人性色生活片| 国产乱码精品一区二区三区卡 | 久久国产精品久久久久久久久久| 国产亚洲精品久久久久久豆腐| 视频在线不卡免费观看| 久久的精品视频| 免看一级a毛片一片成人不卡| 激情国产一区| 欧美一乱一性一交一视频| 五月天亚洲视频| 亚洲av鲁丝一区二区三区| 久久九九热re6这里有精品| 日韩黄色在线免费观看| 国产18无套直看片| 久久久人成影片免费观看| 欧美精品在线观看| 国产成人一区二区三区影院在线 | 亚洲欧美日韩小说| 无码人妻精品一区二区蜜桃百度| 久久av色综合| 色www精品视频在线观看| 欧美wwwwwww| 最新国产精品精品视频| 日韩精品黄色网| 日本不卡一区视频| 黑人一区二区| 国产精品福利小视频| 99热这里只有精品5| 99视频有精品| 在线成人性视频| 成人av影院在线观看| 色综合天天综合网国产成人综合天| 欧美在线aaa| 波多野结衣欧美| 中文字幕av一区| 国产一级片免费| 蜜桃视频第一区免费观看| 99re资源| 91xxx在线观看| 欧美日韩亚洲视频| 一区二区三区四区毛片| 亚洲成a人片77777在线播放| 久久成人精品电影| 国产精品xxxxxx| 成人av网站免费观看| 亚洲欧洲另类精品久久综合| 绿色成人影院| 日韩精品最新网址| 亚洲精品天堂网| 在线亚洲观看| 99精品欧美一区二区三区| www视频在线观看免费| 亚洲成a人片在线不卡一二三区| 91n.com在线观看| 亚洲69av| 8x拔播拔播x8国产精品| av加勒比在线| 国产精品国产三级国产aⅴ中文| 女人天堂av手机在线| 欧美高清hd| 日韩中文字幕免费视频| 亚洲另类在线观看| 波多野结衣亚洲一区| av久久久久久| 精品中文视频| 免费91在线视频| 亚洲一级片免费看| 中文字幕av一区二区三区| 欧美日韩中文在线视频| 免费看久久久| 韩剧1988免费观看全集| 亚洲精品一区二区三区不卡| 亚洲女人****多毛耸耸8| 色播五月综合网| 精品国产中文字幕第一页| 欧美性受xxxx黑人猛交| 亚洲aⅴ乱码精品成人区| 亚洲成人av电影| 中文字幕永久免费| 欧美区亚洲区| yy111111少妇影院日韩夜片| 性欧美video高清bbw| 日韩一区二区精品在线观看| 国产真实乱在线更新| 激情综合色播激情啊| 国产又爽又黄ai换脸| 国产一区二区三区精品在线观看 | 毛片网站在线看| 欧美一区二区免费| 澳门黄色一级片| 国产盗摄女厕一区二区三区| 毛片在线视频观看| 91精品久久久久久综合五月天| 欧美激情日韩图片| 神马午夜电影一区二区三区在线观看| 亚洲一区影音先锋| 又黄又爽的网站| 在线综合视频| 茄子视频成人在线观看 | 欧美一区二区三区免费| 91高清免费观看| 国产精品亚洲综合一区在线观看| 国产一级大片免费看| 精品自拍偷拍| 日产精品99久久久久久| a√资源在线| 欧美一区二区在线视频| 日本少妇全体裸体洗澡| 久久久久久久综合色一本| 日本免费观看网站| 欧美在线高清| 久久99精品久久久久子伦| julia一区二区三区中文字幕| 色综合伊人色综合网| 亚洲精华国产精华精华液网站| 欧美日韩国产在线播放| 国产综合精品久久久久成人av| 国产呦萝稀缺另类资源| 国产午夜福利100集发布| 国产麻豆精品久久| 91在线视频精品| 牛牛精品一区二区| 最近2019中文字幕mv免费看| 黄色av网址在线| 色视频一区二区| 日韩在线中文字幕视频| 99视频有精品| 色一情一区二区三区| 99综合精品| 中文网丁香综合网| 色婷婷狠狠五月综合天色拍| 国产啪精品视频网站| 9765激情中文在线| 色一情一乱一区二区| 日本人妻熟妇久久久久久| 欧美三级视频在线观看| 日本中文字幕免费| 国产精品久99| 丰满少妇高潮一区二区| 国产一区二区三区日韩| 少妇性l交大片| 午夜久久影院| 亚洲精品成人久久久998| 精品少妇一区| 亚洲一区亚洲二区亚洲三区| 中文日产幕无线码一区二区| 欧美成人免费小视频| 国产永久免费高清在线观看视频| 日韩精品中午字幕| 91成品人影院| 色av综合在线| 日韩 欧美 综合| 亚洲精品伦理在线| 亚洲色图 激情小说| 91小视频在线| 美女黄色一级视频| 国产在线一区二区综合免费视频| 精品国产成人av在线免| 在线观看不卡| 久久亚洲a v| 天天插综合网| 中文字幕一区二区三区四区五区六区 | 精品一区二区国产| 欧美日韩黄网站| 国产专区欧美专区| 国产精品黄色片| 国产不卡视频在线| 中老年在线免费视频| 97免费在线视频| 国产www视频在线观看| 欧美裸体男粗大视频在线观看| 天天在线视频色| 中文字幕日韩av| av男人的天堂在线| 一区国产精品视频| 国产女人在线视频| 亚洲人高潮女人毛茸茸| 青青草娱乐在线| 精品无人区乱码1区2区3区在线| 丰满人妻熟女aⅴ一区| 精品欧美一区二区在线观看| www.污视频| 亚洲精品一线二线三线| 亚洲a视频在线观看| 欧美xxxxxxxx| 欧美熟女一区二区| 亚洲电影免费观看高清完整版在线观看| 亚洲成人中文字幕在线| 亚洲成人a级网| 日韩一区免费视频| 亚洲精品美女久久久| 日韩欧美亚洲系列| 亚洲欧美成人一区二区在线电影| 欧美另类自拍| 中文字幕久热精品视频在线| 欧美jizz18hd性欧美| 久久成年人视频| 成人影院在线播放| 日韩免费av片在线观看| 小明成人免费视频一区| 91精品视频免费| 亚洲欧洲国产精品一区| 精品日本一区二区| 欧美日韩国产高清电影| 日本女人高潮视频| 欧美视频官网| 国产aaa一级片| 久久国产三级精品| 手机在线播放av| 不卡av在线免费观看| 90岁老太婆乱淫| 国产精品久久久久aaaa| 国产一级视频在线播放| 日韩欧美精品在线观看| 99re6热在线精品视频播放速度| 自拍一区在线观看| 国产精品第1页| 88久久精品| 欧美一区二区三区在线播放| 图片小说视频色综合| 久久手机在线视频| 老司机午夜精品视频在线观看| 青青草久久伊人| av亚洲精华国产精华精| 欧美日韩国产黄色| 亚洲一区二区三区四区不卡| wwwwww在线观看| 精品久久久久久久久久久久久久久久久| 视频二区在线| 欧美成人精品在线观看| 亚洲三级欧美| 亚洲一区二区三区乱码aⅴ蜜桃女| 亚洲第一福利专区| 成人毛片100部免费看| 视频一区国产视频| 这里只有精品在线观看视频| 国产精品美女久久久久久久久| 日韩欧美a级片| 欧美精品久久天天躁| 日本亚洲一区| 国产69精品久久久| 懂色av色香蕉一区二区蜜桃| 欧美日韩一区二区三区在线视频| 午夜天堂精品久久久久| 亚洲三级视频网站| 97精品视频在线观看自产线路二| 午夜精品一区二区三区视频| 欧美伊人久久久久久午夜久久久久| 欧美一级免费片| 免费99精品国产自在在线| 成人国产一区| 欧美一区国产一区| 一区二区国产精品| 亚洲乱妇老熟女爽到高潮的片| 国产精品久久777777| 尤物av无码色av无码| 久久婷婷激情| 97精品人妻一区二区三区蜜桃| 亚洲日本中文字幕区| 国产天堂第一区| 亚洲精品一二区| 国产剧情av在线播放| 亚洲sss综合天堂久久| 天堂美国久久| 色播五月综合网| 国产天堂亚洲国产碰碰| 亚洲男人的天堂在线视频| 亚洲第一综合天堂另类专| 青青草视频在线免费直播| 91久久嫩草影院一区二区| 欧美成人自拍| 岛国av免费在线| 国产精品蜜臀av| 亚洲一区二区视频在线播放| 在线观看视频亚洲| 国产亚洲精品精品国产亚洲综合| 欧美日韩三区四区| 久久精品首页| 天天躁日日躁aaaa视频| 91成人免费网站| 国产色在线 com| 国产精品久久久久久久电影| 国产精品入口久久| 亚洲国产精品三区| 国产精品免费aⅴ片在线观看| 中文字幕你懂的| 久久精品视频网站| 欧美1区2区3| 国产免费黄色一级片| 99久久精品99国产精品| 日韩黄色在线播放| 亚洲天堂av在线播放| 精品久久在线| 久久久久久久久久久久久国产| 国产·精品毛片| 日韩美女视频网站| 亚洲人成电影网站色…| 少妇高潮一区二区三区99| 亚洲免费视频播放| 成人激情黄色小说| www.国产一区二区| 一道本无吗dⅴd在线播放一区| 欧美成人一二区| 黑人巨茎大战欧美白妇| 成人高清在线视频| 青青艹在线观看| 久久在线观看视频| 精品福利一区| 久久久久国产精品熟女影院| 国产精品久久久久一区二区三区| 国产三级漂亮女教师| 国产69精品久久久久99| 欧美天天综合| 国产chinesehd精品露脸| 精品久久久久久久久久| 超碰免费在线| 高清国产在线一区| 日韩专区欧美专区| 久草视频在线资源| 亚洲日本欧美中文幕| 精品国产亚洲日本| 亚洲精品乱码久久久久久自慰| 国产精品日韩成人| 日本高清视频网站| 成人国产精品色哟哟| 亚洲激情亚洲| 懂色av粉嫩av蜜臀av一区二区三区| 精品剧情v国产在线观看在线| 欧美性理论片在线观看片免费| 天天操天天干天天玩| 久久天堂av综合合色蜜桃网 | 777精品伊人久久久久大香线蕉| 成人影院在线视频| 偷拍盗摄高潮叫床对白清晰| 久久色中文字幕|