EasyTask——強大而簡單的分散式任務排程平臺

coolma2000發表於2018-02-09

Easy Task 概述

github: https://github.com/cehome-com/easy-task
簡單易用的分散式任務排程平臺。來源於淘寶彩票排程平臺,並先後在淘寶內容抓取平臺和鐵甲二手機任務排程平臺中使用。具有如下特點:

  • 去中心化。
  • 支援上百臺不同業務的應用伺服器接入。任務在每個應用上獨立執行,充分利用應用本身資源。
  • 故障轉移。應用如有多臺執行機器,一臺機器掛掉,其上的任務會切到其它機器。
  • 管理控制檯統一對任務修改、啟動、停止等。控制檯掛掉不影響任務的執行。
  • 可以線上檢視任務日誌,實時瞭解任務執行情況。

架構圖

快速體驗

下載並啟動一個控制檯。控制檯同時也是worker,也能執行任務,預設會啟動一個內建的demoPlugin任務。

  • 下載並啟動

1)方式一:到release中下載或直接下載可執行jar包 https://github.com/cehome-com/resource/raw/master/easy-task/2.0.3/task-console.jar

然後執行命令啟動: java -jar task-console.jar

2) 方式二:直接剪出task-console spring boot程式碼模組,匯入IDE中,執行com.cehome.task.console.TaskConsoleApplication啟動。

如果你想快速部署一套簡單可用的排程系統,可以採用方式二,在task-console程式碼裡面新增外掛,並部署使用。

如果你有多個應用,想接入排程平臺,採用方式一,部署的console只做管理,不做任務執行。

demo圖

  • 點選“檢視日誌”按鈕,可以看到任務執行日誌(如果沒有,可以停10秒再重新整理一下)
  • 點選“修改”檢視或修改任務配置。系統基於spring,Bean名稱“demoPlugin”就是內建的一個spring bean。
  • 點選“停止”可以停止任務。

注:

1)控制檯預設內建了一個H2資料庫(埠9092)來儲存任務配置。你也可以採用外部H2或mysql資料庫。

2)採用方式二剪出task-console程式碼模組,例子中的demoPlugin對應類為com.cehome.task.console.DemoPlugin,你可以直接修改此外掛。

模擬客戶端應用(worker)接入排程平臺

實際使用中,console只是管理任務,不執行任務,任務是在客戶端應用中執行的。下面模擬app1和app2兩個應用接入排程平臺。為了方便,還是用task-console.jar來模擬。執行前,先保證上面的console還在執行狀態。

  • 啟動另一個命令列視窗,執行如下命令啟動app1(埠為8091)

java -jar task-console.jar –task.factory.appName=app1 –server.port=8091

-啟動另一個命令列視窗,執行如下命令啟動app2, (埠為8092)

java -jar task-console.jar –task.factory.appName=app2 –server.port=8092

  • 訪問http://localhost:8080 ,點選列表中demo的“修改”按鈕,彈出修改介面,點選“應用”下拉框,應該能看到app1、app2也在裡面,選擇app2,然後儲存並關閉。
  • 觀察app2的命令列輸出視窗,發現demo已經轉移到在app2中執行了。

現有spring boot應用接入排程平臺

以 task-spring-boot-client-demo 模組來說明spring boot應用如何接入排程平臺。

  • 增加依賴
        <dependency>
            <groupId>com.cehome</groupId>
            <artifactId>task</artifactId>
            <version>2.0.3</version>
        </dependency>
  • 加入@EnableTimeTaskClient註解
package com.cehome.task.client.demo;

import com.cehome.task.annotation.EnableTimeTaskClient;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
@EnableTimeTaskClient
public class BootApplication {
    public static void main(String[] args) {
        SpringApplication.run(BootApplication.class,args);
    }

}
  • 修改配置資訊application.properties

需求配置的資訊說明:

task.factory.appName – 應用名稱,不同應用應該不一樣。

task.factory.name – 叢集名稱,同時也是資料庫表名,定了以後不要隨意改動。
task.datasource.* 配置資料庫資訊,支援H2和mysql資料庫,建議生產環境使用mysql資料庫。

task.log.path – logback任務日誌輸出路徑。
task.log.packages – 任務執行類所在包名,記錄日誌用。多個包名用半形分號隔開。如果不好確定,就用ROOT根日誌。

spring.application.name=boot-client-demo
server.port=8081

#------  main options --------
#應用的名稱
task.factory.appName=boot-client-demo
#叢集名稱(同時也是資料庫表名)
task.factory.name=easy_task

#h2資料庫配置
task.datasource.driverClassName=org.h2.Driver
task.datasource.url=jdbc:h2:tcp://localhost:9092/~/easy_task_db;MODE=MYSQL
task.datasource.username=sa
task.datasource.password=

#------  client options --------
task.log.packages=ROOT
task.log.path=/logs/easy_task/boot_demo
  • 開發任務外掛

任務外掛可以繼承com.cehome.task.client.TimeTaskPlugin,由於執行方法是run()是固定的,在console配置任務資訊時候就可以不指定方法名。stop()方法會在點選停止任務時候觸發,程式碼應用停止任務執行和釋放必要的資源。

package com.cehome.task.client.demo;

import com.alibaba.fastjson.JSONObject;
import com.cehome.task.client.TimeTaskContext;
import com.cehome.task.client.TimeTaskPlugin;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import java.net.Inet4Address;

@Component
public class BootDemoPlugin extends TimeTaskPlugin {
    private static final Logger logger = LoggerFactory.getLogger(BootDemoPlugin.class);
    @Override
    public void run(TimeTaskContext context, JSONObject args) throws Exception {
        logger.info("plugin class name="+this);
        logger.info("task id="+context.getId()+",name="+context.getName());
        logger.info("task run on ip="+ Inet4Address.getLocalHost().getHostAddress());
        logger.info("task run count="+context.getRunTimes());
    }

    @Override
    public void stop(TimeTaskContext context) throws Exception {
        logger.info("task "+context.getName()+" is stopped ");
    }
}


任務外掛也可以是普通的spring bean,但在console配置任務資訊時候,需要指定要執行的方法。

  • 啟動應用task-spring-boot-client-demo
  • 訪問http://localhost:8080 (確保控制檯是啟動狀態的),點選“新增”任務,
    “應用”選擇“boot-client-demo”;計劃時間填5s(5秒);Bean名稱跟上面開發外掛一致,填寫“bootDemoPlugin”;其它必填欄位自己隨意。

新增任務

  • 儲存並關閉,點選“啟動”,然後過10多秒鐘點選“檢視”日誌,如果看到“task run……”日誌,說明一切正常。

現有spring mvc應用接入排程平臺

以 task-spring-mvc-client-demo 模組來說明。

  • 增加依賴
        <dependency>
            <groupId>com.cehome</groupId>
            <artifactId>task</artifactId>
            <version>2.0.3</version>
        </dependency>
  • spring xml中匯入bean:
<import resource="classpath*:task-client-spring-config.xml"></import>
  • 在spring xml 中引入配置資訊spring/config.properties
  <context:annotation-config/>
<context:property-placeholder location="classpath*:spring/config.properties"/>
  • 在對應的spring/config.properties新增配置資訊:

task.factory.appName – 應用名稱,不同應用應該不一樣。

task.factory.name – 叢集名稱,同時也是資料庫表名,定了以後不要隨意改動。
task.datasource.* 配置資料庫資訊,支援H2和mysql資料庫,建議生產環境使用mysql資料庫。

task.log.path – logback任務日誌輸出路徑。
task.log.packages – 任務執行類所在包名,記錄日誌用。多個包名用半形分號隔開。如果不好確定,就用ROOT根日誌。

task.factory.appName=mvc-client-demo
task.factory.name=easy_task

#h2
task.datasource.driverClassName=org.h2.Driver
task.datasource.url=jdbc:h2:tcp://localhost:9092/~/easy_task_db;MODE=MYSQL
task.datasource.username=sa
task.datasource.password=

#------  client options --------
task.log.packages=com.cehome.task.client.demo
task.log.path=/logs/easy_task/mvc_demo

  • 在spring mvc xml配置遠端線上日誌檢視的controller。 不配這個controller則console無法線上連線到應用檢視日誌。

    <context:component-scan
            base-package="com.cehome.task.client.controller"/>
    <mvc:annotation-driven />
  • 開發任務外掛

任務外掛可以繼承com.cehome.task.client.TimeTaskPlugin,由於執行方法是run()是固定的,在console配置任務資訊時候就可以不配置。stop()方法會在點選停止任務時候觸發,程式碼應用停止任務執行和釋放必要的資源。

package com.cehome.task.client.demo;

import com.alibaba.fastjson.JSONObject;
import com.cehome.task.client.TimeTaskContext;
import com.cehome.task.client.TimeTaskPlugin;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import java.net.Inet4Address;

@Component
public class MvcDemoPlugin extends TimeTaskPlugin {
    private static final Logger logger = LoggerFactory.getLogger(MvcDemoPlugin.class);
    @Override
    public void run(TimeTaskContext context, JSONObject args) throws Exception {
        logger.info("plugin class name="+this);
        logger.info("task id="+context.getId()+"task name="+context.getName());
        logger.info("task run on ip="+ Inet4Address.getLocalHost().getHostAddress());
        logger.info("task run count="+context.getRunTimes());
    }

   @Override
    public void stop(TimeTaskContext context) throws Exception {
        logger.info("task "+context.getName()+" is stopped ");
    }
}


任務外掛也可以是普通的spring bean,但在console配置任務資訊時候,需要指定要執行的方法。

  • 在spring xml 加入外掛的掃描路徑
   <context:component-scan  base-package="com.cehome.task.client.demo"/>
  • 啟動應用task-spring-mvc-client-demo
  • 訪問console(不是mvc-demo)http://localhost:8080 (確保控制檯是啟動狀態的),點選“新增”任務,
    應用選擇“mvc-client-demo”;計劃時間填5s(5秒);Bean名稱跟上面開發外掛一致,填寫“mvcDemoPlugin”;其它必填欄位自己隨意。
  • 儲存並關閉,點選“啟動”,然後過10多秒鐘點選“檢視”日誌,如果看到“task run……”日誌,說明一切正常。

使用外部資料庫

預設的情況下,console會啟動一個內部的資料庫,生產環境建議用外部資料庫。還是以H2資料庫來說明:

  • 啟動H2資料庫

http://www.h2database.com/html/download.html 下載h2 資料庫並解壓,進入bin目錄,執行命令啟動資料庫(9092是資料庫訪問埠)。

java -cp h2*.jar org.h2.tools.Server -tcpPort 9092 -tcpAllowOthers -webPort 8082 -webAllowOthers

  • 修改console或client資料庫配置資訊

task.datasource.driverClassName=org.h2.Driver
task.datasource.url=jdbc:h2:tcp://192.168.0.10:9092/~/easy_task_db;MODE=MYSQL
task.datasource.username=sa
task.datasource.password=

如果是console,可以修改task.h2.start=false 表示禁用內部資料庫

task.h2.start=false

mysql資料庫配置參考

task.datasource.driverClassName=com.mysql.jdbc.Driver
task.datasource.url=jdbc:mysql://192.168.0.13:3306/scheduler?useUnicode=true&characterEncoding=utf8&allowMultiQueries=true
task.datasource.username=root
task.datasource.password=123456

最佳實踐建議

  • 獨立mysql資料庫
  • console 至少兩個node
  • 若干應用,每個應用至少保持兩個node


相關文章