精品欧美一区二区三区在线观看 _久久久久国色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技術棧公眾號

在线观看午夜av| 精品一区二区三区免费毛片爱 | 在线免费观看a视频| 人妻少妇被粗大爽9797pw| 色欧美片视频在线观看 | 一区二区三区色| 成人精品三级| 人妻熟女aⅴ一区二区三区汇编| 最新国产成人av网站网址麻豆| 欧美一区成人| 97人妻精品视频一区| 91免费版黄色| 中文字幕色av一区二区三区| 日韩影片中文字幕| 中文字幕天堂网| 欧美国产在线视频| 蜜桃视频第一区免费观看| 国产高清在线观看| 国产熟女高潮视频| 亚洲另类图片色| 一区二区自拍| 天堂在线视频免费观看| 无码 制服 丝袜 国产 另类| 欧美男人的天堂一二区| 国产日产精品_国产精品毛片| 日韩精品视频播放| 久久资源亚洲| 欧美亚洲愉拍一区二区| 成人在线免费观看网站| 91丨porny丨在线中文| www.午夜色| 日韩欧美在线一区二区三区| 欧美在线视屏| 免费看男男www网站入口在线| 国产男女在线观看| 亚洲天堂久久av| 国产精品小仙女| 欧美男人天堂| 国内偷拍精品视频| 久久精品99久久| 欧美一区二区私人影院日本| 亚洲国产清纯| 日本三级在线视频| 精品夜夜澡人妻无码av| 国产精品情侣自拍| 一区二区三区在线免费播放| 欧美挤奶吃奶水xxxxx| 中文字幕码精品视频网站| 最近免费观看高清韩国日本大全| 日韩极品精品视频免费观看| 国产一二精品视频| 小明成人免费视频一区| 久久久久久久久久一区二区三区| 品久久久久久久久久96高清| 日韩精品资源二区在线| 久久精品久久精品| 中文在线аv在线| 黄色小说在线观看视频| 影音先锋亚洲视频| 亚洲色图欧美制服丝袜另类第一页| 国产精品综合网| 国产精品久久久久久久久久齐齐| 国产在线拍揄自揄拍| 免费看黄色a级片| 久久久精品免费视频| 国产精品久久久久婷婷| 国产亚洲第一伦理第一区| 午夜在线视频免费| 无码h肉动漫在线观看| 久久久久资源| 亚洲视频999| 午夜精品久久久久久久| av不卡在线看| 国产高清自拍视频在线观看| 伊人国产精品视频| 91精品美女在线| 亚洲妇女屁股眼交7| 欧美性受xxxx狂喷水| 蜜臀av免费观看| 国产一区二区在线播放| 欧美日韩高清在线| 国产麻豆精品视频| 亚洲免费一区三区| 天天操天天操天天操| 国产麻豆xxxvideo实拍| 青青草原成人| 亚洲国产日韩一级| 日韩精品免费| 欧美人与性动交α欧美精品济南到| 欧美精品久久久久性色| 欧美a在线视频| 成人激情在线观看| 亚洲国产小视频| 国产精品国产三级国产专播品爱网| 亚洲一区在线| 欧美成人精品三级网站| 999免费视频| 中文字幕一区二区人妻在线不卡| 亚洲 国产 欧美一区| 欧美精品videosex极品1| 欧美三电影在线| 91免费国产在线| 亚洲欧美一区在线| 成人av三级| 午夜黄色小视频| 免费一级a毛片夜夜看 | 亚洲自拍一区在线观看| 国产欧美视频一区| 大桥未久一区二区| 国产成人久久久| 亚洲精品国产拍免费91在线| 亚洲激情男女视频| 国产一区二区三区观看| 久久中文字幕av| 婷婷久久综合九色综合99蜜桃| 免费av在线电影| 亚洲欧美日韩一区二区三区四区| 精品人妻一区二区免费视频| 精品成在人线av无码免费看| 99国产超薄肉色丝袜交足的后果 | 欧美在线看片a免费观看| 久久综合av免费| 爽爽淫人综合网网站| 欧洲激情视频| 久久影院一区二区三区| 亚洲丝袜精品| 天天操天天爱天天干| 国产精品久久久久久久久久精爆| 亚洲第一香蕉网| gai在线观看免费高清| 加勒比海盗1在线观看免费国语版| 亚洲a中文字幕| 欧美多人爱爱视频网站| 亚洲精品www久久久久久广东| 欧美日韩亚洲天堂| 中文字幕精品一区二区精品绿巨人 | 成人精品视频一区二区| 午夜精品短视频| 99国产高清| 日韩美女免费视频| 麻豆成人在线看| 亚洲精品一区二区三区婷婷月| 欧美视频在线一区二区三区| 亚洲欧美视频一区| 2019国产精品| 国产suv一区二区三区88区| 久热综合在线亚洲精品| 亚洲一级网站| 天堂美国久久| 欧美大片aaaa| 亚洲涩涩av| 看全色黄大色大片免费久久久| 日韩电影免费观看高清完整版| 国产天堂在线播放视频| 久操免费在线| 黄视频网站在线看| а√天堂中文在线资源bt在线| 婷婷视频在线观看| www.日日夜夜| 国产精品一级视频| 国产精品久久无码一三区| 日韩熟女一区二区| 欧美亚洲精品天堂| 日韩精品乱码久久久久久| 久久久久性色av无码一区二区| 99成人在线观看| 国产精品丝袜一区二区| 中日韩一级黄色片| 免费看一级大片| 日本黄色片免费观看| 农村妇女精品一区二区| 日日骚一区二区三区| 69av视频在线| 国产免费观看av| 无码人妻av一区二区三区波多野| 亚洲成人第一网站| 国产精品成人无码| 91久久久久国产一区二区| 亚洲第一黄色片| 亚洲欧美自偷自拍| 3d成人动漫在线| h片在线播放| 午夜影院在线观看国产主播| 一本大道色婷婷在线| 成人国产激情在线| 日韩在线视频一区二区三区| 岛国精品一区| 欧美日韩一二三四| 中文字幕亚洲综合久久五月天色无吗''| 欧美黄色一级视频| 视频在线观看一区| 国内成+人亚洲+欧美+综合在线 | 欧美成人一区在线| 2021国产精品视频| 91精品国产99久久久久久红楼 | 性欧美xxxx大乳国产app| 青草国产精品久久久久久| 国产成a人亚洲| 国产欧美一二三区| 天天操天天干天天综合网| 欧美裸体一区二区三区| 亚洲女人天堂成人av在线| 久久久影视精品| 91网免费观看| 97在线免费视频观看| 色噜噜狠狠一区二区| 亚洲天堂岛国片| 国产中文字幕视频| 四虎影视精品成人| 成人黄色动漫| 卡通动漫国产精品| 国产手机视频一区二区 | 久久精品免费一区二区三区| 母乳一区在线观看| 91在线视频免费观看| 精品久久久久久亚洲国产300| 亚洲精品一区二区三区香蕉| 欧美黑人巨大精品一区二区| 91精品国产一区二区三区动漫| 天天爱天天做天天操| 天堂av8在线| 久久久久久福利| 天天综合网在线| 最新日韩三级| 99精品在线观看| 成人午夜免费av| 色综合久久天天| 久久五月天色综合| 精品一区二区三区自拍图片区 | 四虎国产精品永远| 成人看片网页| 黄色亚洲在线| 国产欧美久久久精品影院| 69堂国产成人免费视频| 久久免费观看视频| 亚洲精品一区国产精品| xxxx视频在线观看| 一级做a爰片久久毛片| h片在线观看网站| 菠萝蜜一区二区| 国产99精品国产| 欧美精品国产精品| 欧美有码在线观看| 欧美视频在线第一页| 久久久视频6r| 涩涩视频免费看| 一区二区三区亚洲变态调教大结局| 一区二区三区四区五区在线| 国产精品久久久久久久久搜平片| 精品久久久久久久久久久久久久久 | 网站一区二区三区| 日韩免费视频网站| 超碰免费公开在线| 91日韩欧美| 欧美激情综合在线| 精品国产亚洲在线| 亚洲淫片在线视频| 久久久久久久久久久久91| 影音先锋亚洲天堂| 欧美人体视频xxxxx| 欧美区亚洲区| 亚洲美女免费在线| 日韩中文字幕在线精品| 亚洲精品8mav| 日本理论中文字幕| www.在线视频.com| 日韩电影一区| 国产精品色哟哟| 美女福利精品视频| 青春草在线视频免费观看| 免费在线黄色网| 少女频道在线观看免费播放电视剧| 欧美成人自拍| 亚洲大片精品永久免费| 97av在线播放| 亚洲国产日韩欧美在线观看| 国产乱叫456在线| jizz18欧美18| 国产欧美日韩亚州综合 | 色国产综合视频| 国产精品久久久久久中文字| 天天综合网久久| 亚洲av永久纯肉无码精品动漫| 久久aimee| 国产日韩综合av| 欧美精品在线第一页| 波多野结衣家庭教师在线| 337p粉嫩色噜噜噜大肥臀| 大胆国模一区二区三区| 91在线视频18| 中文字幕欧美视频在线| 精品久久久无码人妻字幂| 天天干天天色综合| 国产aa精品| 国产亚洲一区二区在线观看| 欧美精品一区二区免费| 苍井空浴缸大战猛男120分钟| 97精品久久人人爽人人爽| 日韩av三区| 亚洲图片欧美一区| 成人性生交xxxxx网站| 欧美性xxxx图片| av老司机免费在线| 国产精品资源站在线| 中文字幕久久亚洲| 116极品美女午夜一级| 精品国产18久久久久久| 91视频综合| 欧美男人的天堂一二区| 亚洲一区二区三区免费看| 无码人妻aⅴ一区二区三区有奶水 无码免费一区二区三区 | 波多野结衣理论片| 精品72久久久久中文字幕| 欧美日韩中文字幕| 久久久久久a亚洲欧洲aⅴ| 日韩av电影网| 婷婷精品视频| 在线观看亚洲精品| 亚欧精品在线| 国产精品高潮呻吟久久久| 久久久久久久久久久久久久久久久久| 在线观看日韩电影| 亚洲一区二区三区精品在线观看| 在线观看免费观看在线| 国产精品伦理久久久久久| 欧美一级一区二区| av高清在线免费观看| 天天在线女人的天堂视频| 模特精品在线| 久久久国产精品免费| 亚洲天堂2024| 国偷自产一区二区免费视频| 日本一区二区三区在线观看| 91精品国产自产在线观看永久| 国产亚洲精品久久久久久打不开| 精品国产一区二区三区不卡蜜臂| 色婷婷国产精品久久包臀| 在线播放豆国产99亚洲| 天天操天天干天天插| 九一九一国产精品| 国产91在线播放| 三级影片在线看| 精品freesex老太交| 欧美大片日本大片免费观看| 美女黄色片视频| 999av小视频在线| 一区二区在线免费观看| 青青草久久网络| 三级视频在线播放| 国产91精品精华液一区二区三区| 国产精品高精视频免费| 天天操天天摸天天干| 欧美日韩1区| 久久这里有精品视频| 一级二级黄色片| 女厕嘘嘘一区二区在线播放| 欧美tickling挠脚心丨vk| 午夜激情影院在线观看| 国产精品久久久久久久久免费高清| 欧美午夜精品在线| 每日在线更新av| 日本在线影院| 五月婷婷另类国产| 日本手机在线视频| 川上优av中文字幕一区二区| 亚洲午夜精品一区二区三区他趣| 国产成人生活片| 波多野结衣精品| 欧美日韩国产色| 亚洲精品一二三四五区| 国产福利一区二区三区在线播放| 在线观看中文字幕不卡| 在线观看免费黄网站| 高清一区二区中文字幕| 日韩一卡二卡三卡四卡| 欧美日韩人妻精品一区在线| 久久精品福利| 亚洲日本中文字幕免费在线不卡| 美国一级黄色录像| 欧美色图麻豆| 欧洲美女免费图片一区| 欧美一区二区三区四| 男人的天堂久久精品| 91精品天堂| 精品亚洲成a人片在线观看| 亚洲日本在线a| 37pao成人国产永久免费视频| 欧美天堂一区| 亚洲成人av片在线观看| 超薄肉色丝袜一二三| 午夜精品免费| 国产色视频一区| 黄色软件在线| 亚洲国产综合色| 亚洲精品高清无码视频| 亚洲精品黑牛一区二区三区| 中文字幕欧美日韩在线| 日韩精品视频免费播放| 国产精品1024| 在线一区亚洲|