對於基於開源XXL-JOB自建任務調度系統的應用而言,可能會遇到任務配置複雜、任務執行效率低、監控和管理困難等需求。阿里雲提供的開源解決方案,支援定時任務調度和任務分區等功能,協助自建定時任務快速接入任務調度平台。
前提條件
子帳號需添加XXL-JOB對應RAM許可權配置。具體資訊,請參見任務調度XXL-JOB版授權。
建立XXL-JOB執行個體。具體操作,請參見建立執行個體。
方案概覽
本方案將從零開始,使用Java語言,手把手教您搭建一個XXL-JOB定時任務,構建Docker鏡像並上傳至阿里雲鏡像倉庫,然後將其接入到分布式任務調度平台XXL-JOB,進行單機和分區廣播的定時任務測試,協助您全面瞭解和掌握XXL-JOB的使用與配置。大致分為以下幾步:
建立應用:通過建立應用對定時任務進行統一管理,方便查看、配置和調度,提升管理效率。
開發及部署應用:編寫定時任務代碼,構建Docker鏡像,並將鏡像上傳至阿里雲鏡像倉庫,實現應用的容器化管理和部署。
測實驗證:確保已接入的應用能夠在XXL-JOB平台上正常自動化調度和管理,任務能夠按計劃準時準確執行。
步驟一:建立應用
登入MSE XXL-JOB控制台,並在頂部功能表列選擇地區。
單擊目標執行個體,進入執行個體詳情頁,在左側導覽列,選擇,單擊建立應用。填寫AppName和名稱,使用系統自動產生的AccessToken,單擊確定。
步驟二:開發及部署應用
1.開發XXL-JOB任務
分布式任務調度XXL-JOB版支援Java應用、Go應用和Python應用接入。如果您想瞭解更多資訊,您可參考開源XXL-JOB的demo工程:
Go版本:xxl-job-executor-go。
Python版本:xxl-job-executor-python。
Java
環境配置:在您的pom.xml中引入
xxl-job-core的Maven依賴。具體版本,參考xxl-job-executor-sample-springboot。<!-- xxl-job-core --> <dependency> <groupId>com.xuxueli</groupId> <artifactId>xxl-job-core</artifactId> <version>2.2.x</version> </dependency>初始化執行器。
@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; } }編寫任務執行代碼,以2.2.x為例。
說明XXL-JOB不同版本介面不同,具體請參考開源demo工程。
@Component public class SampleXxlJob { private static Logger logger = LoggerFactory.getLogger(SampleXxlJob.class); @XxlJob("helloworld") public ReturnT<String> helloworld(String param) throws Exception { XxlJobLogger.log("XXL-JOB, Hello World, start..."); for (int i = 0; i < 5; i++) { XxlJobLogger.log("beat at:" + i); TimeUnit.SECONDS.sleep(2); } System.out.println("XXL-JOB, Hello World, finished"); return ReturnT.SUCCESS; } }
Golang
環境配置:執行以下命令,使用最新的tag拉取Go版本的XXL-JOB的SDK。具體版本,參考xxl-job-executor-go。
go get github.com/xxl-job/xxl-job-executor-go@{最新的tag}編寫初始化執行器。
package main import ( "context" "fmt" xxl "github.com/xxl-job/xxl-job-executor-go" "github.com/xxl-job/xxl-job-executor-go/example/task" "log" ) func main() { exec := xxl.NewExecutor( xxl.ServerAddr("xxxxxx"), //請求地址,控制台應用管理接入配置擷取 xxl.AccessToken("xxxxxxx"), //請求令牌,控制台應用管理接入配置擷取 xxl.ExecutorPort("9999"), //預設9999(非必填) xxl.RegistryKey("golang-jobs"), //執行器名稱 xxl.SetLogger(&logger{}), //自訂日誌 ) exec.Init() exec.Use(customMiddleware) //設定日誌查看handler exec.LogHandler(customLogHandle) //註冊任務handler exec.RegTask("task.test", task.Test) exec.RegTask("task.shardingTest", task.ShardingTest) log.Fatal(exec.Run()) } // 自訂Tlog器 func customLogHandle(req *xxl.LogReq) *xxl.LogRes { return &xxl.LogRes{Code: xxl.SuccessCode, Msg: "", Content: xxl.LogResContent{ FromLineNum: req.FromLineNum, ToLineNum: 2, LogContent: "這個是自訂日誌handler", IsEnd: true, }} } // xxl.Logger介面實現 type logger struct{} func (l *logger) Info(format string, a ...interface{}) { fmt.Println(fmt.Sprintf("自訂日誌 - "+format, a...)) } func (l *logger) Error(format string, a ...interface{}) { log.Println(fmt.Sprintf("自訂日誌 - "+format, a...)) } // 自訂中介軟體 func customMiddleware(tf xxl.TaskFunc) xxl.TaskFunc { return func(cxt context.Context, param *xxl.RunReq) string { log.Println("I am a middleware start") res := tf(cxt, param) log.Println("I am a middleware end") return res } }編寫任務執行代碼。
package task import ( "context" "fmt" xxl "github.com/xxl-job/xxl-job-executor-go" ) func Test(cxt context.Context, param *xxl.RunReq) (msg string) { fmt.Println("test one task" + param.ExecutorHandler + " param:" + param.ExecutorParams + " log_id:" + xxl.Int64ToStr(param.LogID)) return "test done" } func ShardingTest(cxt context.Context, param *xxl.RunReq) (msg string) { fmt.Println("shardingId:" + xxl.Int64ToStr(param.BroadcastIndex) + ", shardingTotal:" + xxl.Int64ToStr(param.BroadcastTotal)) return "ShardingTest done" }
Python
拉取依賴。具體版本,參考xxl-job-executor-python。
pip install pyxxl # 如果日誌需要寫入redis pip install "pyxxl[redis]" # 如果需要從.env載入配置 pip install "pyxxl[dotenv]" # 安裝所有功能 pip install "pyxxl[all]"編寫任務執行代碼。
import asyncio import time from pyxxl import ExecutorConfig, PyxxlRunner from pyxxl.ctx import g config = ExecutorConfig( xxl_admin_baseurl="http://xxljob-1b3fd81****.schedulerx.mse.aliyuncs.com/api/", executor_app_name="xueren-test", access_token="default_token", # executor_listen_host="0.0.0.0", # 如果xxl-admin可以直連executor的ip,可以不填寫executor_listen_host ) app = PyxxlRunner(config) @app.register(name="demoJobHandler") async def test_task(): # you can get task params with "g" g.logger.info("get executor params: %s" % g.xxl_run_data.executorParams) for i in range(10): g.logger.warning("test logger %s" % i) await asyncio.sleep(5) return "成功..." @app.register(name="sync_func") def test_task4(): # 如果要在xxl-admin上看到執行日誌,列印日誌的時候務必用g.logger來列印,預設只列印info及以上的日誌 n = 1 g.logger.info("Job %s get executor params: %s" % (g.xxl_run_data.jobId, g.xxl_run_data.executorParams)) # 如果同步任務裡面有迴圈,為了支援cancel操作,必須每次都判斷g.cancel_event. while n <= 10 and not g.cancel_event.is_set(): # 如果不需要從xxl-admin中查看日誌,可以用自己的logger g.logger.info( "log to {} logger test_task4.{},params:{}".format( g.xxl_run_data.jobId, n, g.xxl_run_data.executorParams, ) ) time.sleep(2) n += 1 return "成功3" if __name__ == "__main__": app.run_executor()
2.部署應用至阿里雲
阿里雲XXL-JOB版僅支援阿里雲網路,需要將您的應用部署到阿里雲上,以下以Java應用部署到Container Service為例進行說明。
Container Service叢集需要和任務調度XXL-JOB版叢集在同一個VPC內。
在SpringBoot應用的根目錄下編寫Dockerfile檔案。
# 下面替換你自己的基礎鏡像 FROM reg.docker.alibaba-inc.com/xxx/xxxx-java:1.0-beta MAINTAINER xueren ENV JAVA_OPTS="" ADD target/xxl-job-executor-sample-springboot-*.jar /app.jar ENTRYPOINT ["sh","-c","java -jar $JAVA_OPTS /app.jar]使用Docker工具,構建Docker鏡像,並上傳到阿里雲鏡像倉庫。
docker login --username=xxx@aliyun.com registry.cn-hangzhou.aliyuncs.com --password=xxxxxx docker buildx build --platform linux/amd64 -t registry.cn-hangzhou.aliyuncs.com/schedulerx/xxljob-demo:2.2.0 . docker push registry.cn-hangzhou.aliyuncs.com/schedulerx/xxljob-demo:2.2.0在左側導覽列的頁面,單擊目標應用操作列的接入配置。
登入阿里雲Container Service,進入目的地組群。在左側導覽列,選擇,單擊右上方的使用YAML建立資源,建立Deployment。以接入方式2(通過-D參數重啟應用)的為例進行接入配置,替換YAML的JAVA_OPTS列中,實現環境變數注入JVM參數。

apiVersion: apps/v1 kind: Deployment metadata: name: xxljob-xueren-test labels: app: xxljob-xueren-test spec: replicas: 2 selector: matchLabels: app: xxljob-xueren-test template: metadata: labels: app: xxljob-xueren-test spec: containers: - name: xxljob-executor image: registry.cn-hangzhou.aliyuncs.com/schedulerx/xxljob-demo:2.2.0 ports: - containerPort: 9999 env: - name: JAVA_OPTS value: >- -Dxxl.job.admin.addresses=http://xxljob-xxxxx.schedulerx.mse.aliyuncs.com -Dxxl.job.executor.appname=xueren_test -Dxxl.job.accessToken=xxxxxxx
步驟三:測實驗證
1.執行器接入驗證
進入目標執行個體詳情頁,單擊左側導覽列的應用管理,在應用列表頁面,單擊目標應用的執行器數量,可看到接入的執行器地址和線上狀態。

2.任務測實驗證
單機任務測試
單機任務表示每次執行在該應用下的所有執行器中按照路由策略選一台等冪執行。
在左側導覽列,選擇任務管理,單擊建立任務。首先進行基本配置,填寫任務名稱和jobHandler名稱,關聯應用選擇目標應用,路由策略選擇輪詢,然後單擊下一步。

進行定時配置,時間類型選擇cron,通過單擊使用產生工具按鈕,產生cron運算式。本樣本以每天12時執行一次為例,然後單擊下一步。

進行通知配置,您可以在此配置逾時警示、成功通知、失敗警示、通知方式、通知對象。本樣本以控制台預設配置為例。

建立完成後,單擊目標任務操作列中的運行一次,在手動執行任務彈框中,指定機器,配置執行個體參數,單擊確定

單擊,查看任務執行記錄。
單擊左側導覽列執行列表,單擊目標執行記錄操作列中的日誌,查看本次任務的執行日誌記錄。

分區廣播任務測試
廣播分區表示每次執行會廣播該應用下所有執行器執行,每個執行器能拿到不同的分區號,可以用來做分布式批處理。開源XXL-JOB分區廣播無彙總功能,阿里雲XXL-JOB可以彙總展示每次執行的所有分區情況。
在左側導覽列,選擇任務管理,單擊建立任務。首先進行基本配置,填寫任務名稱和jobHandler名稱,關聯應用選擇目標應用,路由策略選擇分區廣播。然後單擊下一步。

進行定時配置,時間類型選擇cron,通過單擊使用產生工具按鈕,產生cron運算式。本樣本以每小時第10分執行一次為例,然後單擊下一步。

進行通知配置,您可以在此配置設定逾時警示、成功通知、失敗警示、通知方式、通知對象。本樣本以控制台預設配置為例。

建立完成後,單擊目標任務操作列中的運行一次,在手動執行任務彈框中,指定機器,配置執行個體參數,單擊確定。

單擊,查看任務執行記錄。
單擊左側導覽列的執行列表,在任務執行列表頁,單擊目標任務執行操作列中的詳情,在分區詳情中可彙總展示每台機器的執行情況。

針對每個分區,單擊指定分區操作列中的日誌,查看本次任務的執行日誌記錄。
