天天看點

3千字帶你搞懂XXL-JOB任務排程平台思維導圖一、概述二、為什麼需要任務排程平台三、為什麼選擇XXL-JOB四、安裝五、永遠的HelloWord六、談談架構設計絮叨

思維導圖

3千字帶你搞懂XXL-JOB任務排程平台思維導圖一、概述二、為什麼需要任務排程平台三、為什麼選擇XXL-JOB四、安裝五、永遠的HelloWord六、談談架構設計絮叨
文章已收錄Github精選,歡迎Star: https://github.com/yehongzhi/learningSummary

一、概述

在平時的業務場景中,經常有一些場景需要使用定時任務,比如:

  • 時間驅動的場景:某個時間點發送優惠券,發送短信等等。
  • 批量處理資料:批量統計上個月的賬單,統計上個月銷售資料等等。
  • 固定頻率的場景:每隔5分鐘需要執行一次。

是以定時任務在平時開發中并不少見,而且對于現在快速消費的時代,每天都需要發送各種推送,消息都需要依賴定時任務去完成,應用非常廣泛。

二、為什麼需要任務排程平台

在Java中,傳統的定時任務實作方案,比如Timer,Quartz等都或多或少存在一些問題:

  • 不支援叢集、不支援統計、沒有管理平台、沒有失敗報警、沒有監控等等

而且在現在分布式的架構中,有一些場景需要分布式任務排程:

  • 同一個服務多個執行個體的任務存在互斥時,需要統一的排程。
  • 任務排程需要支援高可用、監控、故障告警。
  • 需要統一管理和追蹤各個服務節點任務排程的結果,需要記錄儲存任務屬性資訊等。

顯然傳統的定時任務已經不滿足現在的分布式架構,是以需要一個分布式任務排程平台,目前比較主流的是elasticjob和xxl-job。

elasticjob由當當網開源,目前github有6.5k的Star,使用的公司在官網登記有76家。

3千字帶你搞懂XXL-JOB任務排程平台思維導圖一、概述二、為什麼需要任務排程平台三、為什麼選擇XXL-JOB四、安裝五、永遠的HelloWord六、談談架構設計絮叨

跟xxl-job不同的是,elasticjob是采用zookeeper實作分布式協調,實作任務高可用以及分片。

3千字帶你搞懂XXL-JOB任務排程平台思維導圖一、概述二、為什麼需要任務排程平台三、為什麼選擇XXL-JOB四、安裝五、永遠的HelloWord六、談談架構設計絮叨

三、為什麼選擇XXL-JOB

實際上更多公司選擇xxl-job,目前xxl-job的github上有15.7k個star,登記公司有348個。毫無疑問elasticjob和xxl-job都是非常優秀的技術架構,接下來我們進一步對比讨論,探索一下為什麼更多公司會選擇xxl-job。

首先先介紹一下xxl-job,這是出自大衆點評許雪裡(xxl就是作者名字的拼音首字母)的開源項目,官網上介紹這是一個輕量級分布式任務排程架構,其核心設計目标是開發迅速、學習簡單、輕量級、易擴充。跟elasticjob不同,xxl-job環境依賴于mysql,不用ZooKeeper,這也是最大的不同。

elasticjob的初衷是為了面對高并發複雜的業務,即使是在業務量大,伺服器多的時候也能做好任務排程,盡可能的利用伺服器的資源。使用ZooKeeper使其具有高可用、一緻性的,而且還具有良好的擴充性。官網上寫elasticjob是無中心化的,通過ZooKeeper的選舉機制選舉出主伺服器,如果主伺服器挂了,會重新選舉新的主伺服器。是以elasticjob具有良好的擴充性和可用性,但是使用和運維有一定的複雜。

3千字帶你搞懂XXL-JOB任務排程平台思維導圖一、概述二、為什麼需要任務排程平台三、為什麼選擇XXL-JOB四、安裝五、永遠的HelloWord六、談談架構設計絮叨

xxl-job則相反,是通過一個中心式的排程平台,排程多個執行器執行任務,排程中心通過DB鎖保證叢集分布式排程的一緻性,這樣擴充執行器會增大DB的壓力,但是如果實際上這裡資料庫隻是負責任務的排程執行。但是如果沒有大量的執行器的話和任務的情況,是不會造成資料庫壓力的。實際上大部分公司任務數,執行器并不多(雖然面試經常會問一些高并發的問題)。

相對來說,xxl-job中心式的排程平台輕量級,開箱即用,操作簡易,上手快,與SpringBoot有非常好的內建,而且監控界面就內建在排程中心,界面又簡潔,對于企業維護起來成本不高,還有失敗的郵件告警等等。這就使很多企業選擇xxl-job做排程平台。

四、安裝

4.1 拉取源碼

搭建xxl-job很簡單,有docker拉取鏡像部署和源碼編譯兩種方式,docker部署的方式比較簡單,我就講源碼編譯的方式。首先到github拉取xxl-job源碼到本地。

3千字帶你搞懂XXL-JOB任務排程平台思維導圖一、概述二、為什麼需要任務排程平台三、為什麼選擇XXL-JOB四、安裝五、永遠的HelloWord六、談談架構設計絮叨

4.2 導入IDEA

拉取源碼下來後,可以看到項目結構,如下:

3千字帶你搞懂XXL-JOB任務排程平台思維導圖一、概述二、為什麼需要任務排程平台三、為什麼選擇XXL-JOB四、安裝五、永遠的HelloWord六、談談架構設計絮叨

導入到IDEA,配置一下Maven,下載下傳相關的jar包,稍等一下後,就可以看到這樣的項目:

3千字帶你搞懂XXL-JOB任務排程平台思維導圖一、概述二、為什麼需要任務排程平台三、為什麼選擇XXL-JOB四、安裝五、永遠的HelloWord六、談談架構設計絮叨

4.3 初始化資料庫

前面講過xxl-job需要依賴mysql,是以需要初始化資料庫,在xxl-jobdocdb路徑下找到tables_xxl_job.sql檔案。在mysql上運作sql檔案。

3千字帶你搞懂XXL-JOB任務排程平台思維導圖一、概述二、為什麼需要任務排程平台三、為什麼選擇XXL-JOB四、安裝五、永遠的HelloWord六、談談架構設計絮叨

4.4 配置檔案

接着就改一下配置檔案,在admin項目下找到application.properties檔案。

### 排程中心JDBC連結
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=
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
### 報警郵箱
spring.mail.host=smtp.qq.com
spring.mail.port=25
[email protected]
spring.mail.password=xxx
spring.mail.properties.mail.smtp.auth=true
spring.mail.properties.mail.smtp.starttls.enable=true
spring.mail.properties.mail.smtp.starttls.required=true
spring.mail.properties.mail.smtp.socketFactory.class=javax.net.ssl.SSLSocketFactory
### 排程中心通訊TOKEN [選填]:非空時啟用;
xxl.job.accessToken=
### 排程中心國際化配置 [必填]: 預設為 "zh_CN"/中文簡體, 可選範圍為 "zh_CN"/中文簡體, "zh_TC"/中文繁體 and "en"/英文;
xxl.job.i18n=zh_CN
## 排程線程池最大線程配置【必填】
xxl.job.triggerpool.fast.max=200
xxl.job.triggerpool.slow.max=100
### 排程中心日志表資料儲存天數 [必填]:過期日志自動清理;限制大于等于7時生效,否則, 如-1,關閉自動清理功能;
xxl.job.logretentiondays=10           

4.5 編譯運作

簡單一點直接跑admin項目的main方法啟動也行。

3千字帶你搞懂XXL-JOB任務排程平台思維導圖一、概述二、為什麼需要任務排程平台三、為什麼選擇XXL-JOB四、安裝五、永遠的HelloWord六、談談架構設計絮叨

如果部署在伺服器呢,那我們需要打包成jar包,在IDEA利用Maven插件打包。

3千字帶你搞懂XXL-JOB任務排程平台思維導圖一、概述二、為什麼需要任務排程平台三、為什麼選擇XXL-JOB四、安裝五、永遠的HelloWord六、談談架構設計絮叨

然後在xxl-jobxxl-job-admintarget路徑下,找到jar包。

3千字帶你搞懂XXL-JOB任務排程平台思維導圖一、概述二、為什麼需要任務排程平台三、為什麼選擇XXL-JOB四、安裝五、永遠的HelloWord六、談談架構設計絮叨

然後就得到jar包了,使用java -jar指令就可以啟動了。

3千字帶你搞懂XXL-JOB任務排程平台思維導圖一、概述二、為什麼需要任務排程平台三、為什麼選擇XXL-JOB四、安裝五、永遠的HelloWord六、談談架構設計絮叨

到這裡就已經完成了!打開浏覽器,輸入

http://localhost:8080/xxl-job-admin

進入管理頁面。預設賬号/密碼:admin/123456。

3千字帶你搞懂XXL-JOB任務排程平台思維導圖一、概述二、為什麼需要任務排程平台三、為什麼選擇XXL-JOB四、安裝五、永遠的HelloWord六、談談架構設計絮叨

五、永遠的HelloWord

部署了排程中心之後,需要往排程中心注冊執行器,添加排程任務。接下來就參考xxl-job寫一個簡單的例子。

首先建立一個SpringBoot項目,名字叫"xxljob-demo",添加依賴。

<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter</artifactId>
    </dependency>
    <dependency><!-- 官網的demo是2.2.1,中央maven倉庫還沒有,是以就用2.2.0 -->
        <groupId>com.xuxueli</groupId>
        <artifactId>xxl-job-core</artifactId>
        <version>2.2.0</version>
    </dependency>
</dependencies>           

接着修改application.properties。

# web port
server.port=8081
# log config
logging.config=classpath:logback.xml
spring.application.name=xxljob-demo
### 排程中心部署跟位址 [選填]:如排程中心叢集部署存在多個位址則用逗号分隔。執行器将會使用該位址進行"執行器心跳注冊"和"任務結果回調";為空則關閉自動注冊;
xxl.job.admin.addresses=http://127.0.0.1:8080/xxl-job-admin
### 執行器通訊TOKEN [選填]:非空時啟用;
xxl.job.accessToken=
### 執行器AppName [選填]:執行器心跳注冊分組依據;為空則關閉自動注冊
xxl.job.executor.appname=xxl-job-demo
### 執行器注冊 [選填]:優先使用該配置作為注冊位址,為空時使用内嵌服務 ”IP:PORT“ 作為注冊位址。進而更靈活的支援容器類型執行器動态IP和動态映射端口問題。
xxl.job.executor.address=
### 執行器IP [選填]:預設為空表示自動擷取IP,多網卡時可手動設定指定IP,該IP不會綁定Host僅作為通訊實用;位址資訊用于 "執行器注冊" 和 "排程中心請求并觸發任務";
xxl.job.executor.ip=
### 執行器端口号 [選填]:小于等于0則自動擷取;預設端口為9999,單機部署多個執行器時,注意要配置不同執行器端口;
xxl.job.executor.port=9999
### 執行器運作日志檔案存儲磁盤路徑 [選填] :需要對該路徑擁有讀寫權限;為空則使用預設路徑;
xxl.job.executor.logpath=/data/applogs/xxl-job/jobhandler
### 執行器日志檔案儲存天數 [選填] : 過期日志自動清理, 限制值大于等于3時生效; 否則, 如-1, 關閉自動清理功能;
xxl.job.executor.logretentiondays=10           

接着寫一個配置類XxlJobConfig。

@Configuration
public class XxlJobConfig {
    private Logger logger = LoggerFactory.getLogger(XxlJobConfig.class);
    @Value("${xxl.job.admin.addresses}")
    private String adminAddresses;
    @Value("${xxl.job.accessToken}")
    private String accessToken;
    @Value("${xxl.job.executor.appname}")
    private String appname;
    @Value("${xxl.job.executor.address}")
    private String address;
    @Value("${xxl.job.executor.ip}")
    private String ip;
    @Value("${xxl.job.executor.port}")
    private int port;
    @Value("${xxl.job.executor.logpath}")
    private String logPath;
    @Value("${xxl.job.executor.logretentiondays}")
    private int logRetentionDays;

    @Bean
    public XxlJobSpringExecutor xxlJobExecutor() {
        logger.info(">>>>>>>>>>> xxl-job config init.");
        XxlJobSpringExecutor xxlJobSpringExecutor = new XxlJobSpringExecutor();
        xxlJobSpringExecutor.setAdminAddresses(adminAddresses);
        xxlJobSpringExecutor.setAppname(appname);
        xxlJobSpringExecutor.setAddress(address);
        xxlJobSpringExecutor.setIp(ip);
        xxlJobSpringExecutor.setPort(port);
        xxlJobSpringExecutor.setAccessToken(accessToken);
        xxlJobSpringExecutor.setLogPath(logPath);
        xxlJobSpringExecutor.setLogRetentionDays(logRetentionDays);
        return xxlJobSpringExecutor;
    }
}           

接着編寫一個任務類XxlJobDemoHandler,使用Bean模式。

@Component
public class XxlJobDemoHandler {
    /**
     * Bean模式,一個方法為一個任務
     * 1、在Spring Bean執行個體中,開發Job方法,方式格式要求為 "public ReturnT<String> execute(String param)"
     * 2、為Job方法添加注解 "@XxlJob(value="自定義jobhandler名稱", init = "JobHandler初始化方法", destroy = "JobHandler銷毀方法")",注解value值對應的是排程中心建立任務的JobHandler屬性的值。
     * 3、執行日志:需要通過 "XxlJobLogger.log" 列印執行日志;
     */
    @XxlJob("demoJobHandler")
    public ReturnT<String> demoJobHandler(String param) throws Exception {
        XxlJobLogger.log("java, Hello World~~~");
        XxlJobLogger.log("param:" + param);
        return ReturnT.SUCCESS;
    }
}           

在resources目錄下,添加logback.xml檔案。

<?xml version="1.0" encoding="UTF-8"?>
<configuration debug="false" scan="true" scanPeriod="1 seconds">
    <contextName>logback</contextName>
    <property name="log.path" value="/data/applogs/xxl-job/xxl-job-executor-sample-springboot.log"/>
    <appender name="console" class="ch.qos.logback.core.ConsoleAppender">
        <encoder>
            <pattern>%d{HH:mm:ss.SSS} %contextName [%thread] %-5level %logger{36} - %msg%n</pattern>
        </encoder>
    </appender>
    <appender name="file" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <file>${log.path}</file>
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <fileNamePattern>${log.path}.%d{yyyy-MM-dd}.zip</fileNamePattern>
        </rollingPolicy>
        <encoder>
            <pattern>%date %level [%thread] %logger{36} [%file : %line] %msg%n
            </pattern>
        </encoder>
    </appender>
    <root level="info">
        <appender-ref ref="console"/>
        <appender-ref ref="file"/>
    </root>
</configuration>           

寫完之後啟動服務,然後可以打開管理界面,找到執行器管理,添加執行器。

3千字帶你搞懂XXL-JOB任務排程平台思維導圖一、概述二、為什麼需要任務排程平台三、為什麼選擇XXL-JOB四、安裝五、永遠的HelloWord六、談談架構設計絮叨

接着到任務管理,添加任務。

3千字帶你搞懂XXL-JOB任務排程平台思維導圖一、概述二、為什麼需要任務排程平台三、為什麼選擇XXL-JOB四、安裝五、永遠的HelloWord六、談談架構設計絮叨
3千字帶你搞懂XXL-JOB任務排程平台思維導圖一、概述二、為什麼需要任務排程平台三、為什麼選擇XXL-JOB四、安裝五、永遠的HelloWord六、談談架構設計絮叨

最後我們可以到任務管理去測試一下,運作demoJobHandler。

3千字帶你搞懂XXL-JOB任務排程平台思維導圖一、概述二、為什麼需要任務排程平台三、為什麼選擇XXL-JOB四、安裝五、永遠的HelloWord六、談談架構設計絮叨
3千字帶你搞懂XXL-JOB任務排程平台思維導圖一、概述二、為什麼需要任務排程平台三、為什麼選擇XXL-JOB四、安裝五、永遠的HelloWord六、談談架構設計絮叨

點選儲存後,會立即執行。點選檢視日志,可以看到任務執行的曆史日志記錄。

3千字帶你搞懂XXL-JOB任務排程平台思維導圖一、概述二、為什麼需要任務排程平台三、為什麼選擇XXL-JOB四、安裝五、永遠的HelloWord六、談談架構設計絮叨

打開剛剛執行的執行日志,我們可以看到,運作成功。

3千字帶你搞懂XXL-JOB任務排程平台思維導圖一、概述二、為什麼需要任務排程平台三、為什麼選擇XXL-JOB四、安裝五、永遠的HelloWord六、談談架構設計絮叨

這就是簡單的Demo示範,非常簡單,上手也快。

六、談談架構設計

下面簡單地說一下xxl-job的架構,我們先看官網提供的一張架構圖來分析。

3千字帶你搞懂XXL-JOB任務排程平台思維導圖一、概述二、為什麼需要任務排程平台三、為什麼選擇XXL-JOB四、安裝五、永遠的HelloWord六、談談架構設計絮叨

從架構圖可以看出,分别有排程中心和執行器兩大組成部分

  • 排程中心。負責管理排程資訊,按照排程配置發出排程請求,自身不承擔業務代碼。支援可視化界面,可以在排程中心對任務進行新增,更新,删除,會實時生效。支援監控排程結果,檢視執行日志,檢視排程任務統計報表,任務失敗告警等等。
  • 執行器。負責接收排程請求,執行排程任務的業務邏輯。執行器啟動後需要注冊到排程中心。接收排程中心的發出的執行請求,終止請求,日志請求等等。

接下來我們看一下xxl-job的工作原理。

3千字帶你搞懂XXL-JOB任務排程平台思維導圖一、概述二、為什麼需要任務排程平台三、為什麼選擇XXL-JOB四、安裝五、永遠的HelloWord六、談談架構設計絮叨
  • 任務執行器根據配置的排程中心的位址,自動注冊到排程中心。
  • 達到任務觸發條件,排程中心下發任務。
  • 執行器基于線程池執行任務,并把執行結果放入記憶體隊列中、把執行日志寫入日志檔案中。
  • 執行器的回調線程消費記憶體隊列中的執行結果,主動上報給排程中心。
  • 當使用者在排程中心檢視任務日志,排程中心請求任務執行器,任務執行器讀取任務日志檔案并傳回日志詳情。

絮叨

看完以上的内容,基本算入門了。實際上,xxl-job還有很多功能,要深入學習,還需要到

官網

去研究探索。最好就是自己在本地搭建一個xxl-job來玩玩,動手實踐是學得最快的學習方式。

上面所有例子的代碼都上傳Github了:

https://github.com/yehongzhi/mall

覺得有用就點個贊吧,你的點贊是我創作的最大動力~

拒絕做一條鹹魚,我是一個努力讓大家記住的程式員。我們下期再見!!!

3千字帶你搞懂XXL-JOB任務排程平台思維導圖一、概述二、為什麼需要任務排程平台三、為什麼選擇XXL-JOB四、安裝五、永遠的HelloWord六、談談架構設計絮叨
能力有限,如果有什麼錯誤或者不當之處,請大家批評指正,一起學習交流!