Applications that use a self-built task scheduling system based on the open source XXL-JOB may face challenges. These challenges include complex task configurations, low execution efficiency, and difficulties in monitoring and management. The open source solution provided by Alibaba Cloud supports features such as scheduled task scheduling and task sharding. This solution helps you quickly connect your self-built scheduled tasks to the task scheduling platform.
Prerequisites
A RAM user must be granted the required RAM permissions to use XXL-JOB. For more information, see Task Scheduling XXL-JOB Edition Authorization.
You can create an XXL-JOB instance. For more information, see Create an instance.
Solution overview
This topic explains how to use a software development kit (SDK) to connect Java, Go, and Python applications to MSE-XXLJOB to schedule and execute tasks.
You can implement the business logic for your scheduled tasks in your code and expose a task component identified as a Bean. Then, you can configure the Bean name in the console to trigger the task logic.

This solution includes the following steps:
Create an application: Create an application to centrally manage scheduled tasks. This makes it easier to view, configure, and schedule tasks, which improves management efficiency.
Develop and deploy the application: Write the code for the scheduled task, build a Docker image, and upload the image to an Alibaba Cloud image repository. This process achieves containerized management and deployment of the application.
Test and verify: Ensure that the connected application can be automatically scheduled and managed on the XXL-JOB platform and that tasks are executed accurately and on schedule.
Step 1: Create an application
Log on to the MSE console for XXL-JOB and select a region in the top menu bar.
Click the target instance to go to the instance details page. In the navigation pane on the left, choose and click Create Application. Enter an AppName and a Name. Use the system-generated AccessToken and click OK.
Step 2: Develop and deploy the application
1. Develop an XXL-JOB task
Distributed Task Scheduling for XXL-JOB supports connections from applications written in Java, Go, and Python. For more information, see the open source XXL-JOB demo projects:
Java version: xxl-job-executor-sample-springboot.
Go version: xxl-job-executor-go.
Python version: xxl-job-executor-python.
Java
Environment configuration: In your pom.xml file, add the Maven dependency for
xxl-job-core. For the specific version, see xxl-job-executor-sample-springboot.<!-- xxl-job-core --> <dependency> <groupId>com.xuxueli</groupId> <artifactId>xxl-job-core</artifactId> <version>2.2.x</version> </dependency>Initialize the executor.
@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; } }Write the task execution code. The following code provides an example for version 2.2.x.
NoteThe interfaces for XXL-JOB vary by version. For more information, see the open source demo project.
@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
Environment configuration: Run the following command to pull the Go version of the XXL-JOB software development kit (SDK) using the latest tag. For the specific version, see xxl-job-executor-go.
go get github.com/xxl-job/xxl-job-executor-go@{latest_tag}Write the code to initialize the executor.
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"), // Request address. Obtain this from the connection configuration in the console. xxl.AccessToken("xxxxxxx"), // Request token. Obtain this from the connection configuration in the console. xxl.ExecutorPort("9999"), // Default is 9999. This parameter is optional. xxl.RegistryKey("golang-jobs"), // Executor name xxl.SetLogger(&logger{}), // Custom logger ) exec.Init() exec.Use(customMiddleware) // Set the log view handler exec.LogHandler(customLogHandle) // Register the task handler exec.RegTask("task.test", task.Test) exec.RegTask("task.shardingTest", task.ShardingTest) log.Fatal(exec.Run()) } // Custom log handler func customLogHandle(req *xxl.LogReq) *xxl.LogRes { return &xxl.LogRes{Code: xxl.SuccessCode, Msg: "", Content: xxl.LogResContent{ FromLineNum: req.FromLineNum, ToLineNum: 2, LogContent: "This is a custom log handler", IsEnd: true, }} } // Implementation of the xxl.Logger interface type logger struct{} func (l *logger) Info(format string, a ...interface{}) { fmt.Println(fmt.Sprintf("Custom log - "+format, a...)) } func (l *logger) Error(format string, a ...interface{}) { log.Println(fmt.Sprintf("Custom log - "+format, a...)) } // Custom middleware 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 } }Write the task execution code.
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
Pull the dependencies. For the specific version, see xxl-job-executor-python.
pip install pyxxl # If logs need to be written to Redis pip install "pyxxl[redis]" # To load configurations from .env pip install "pyxxl[dotenv]" # Install all features pip install "pyxxl[all]"Write the task execution code.
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", # If xxl-admin can directly connect to the executor's IP, you do not need to specify 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 "Success..." @app.register(name="sync_func") def test_task4(): # To view execution logs on xxl-admin, you must use g.logger for logging. By default, only logs of level INFO and higher are printed. n = 1 g.logger.info("Job %s get executor params: %s" % (g.xxl_run_data.jobId, g.xxl_run_data.executorParams)) # If a sync task contains a loop, you must check g.cancel_event in each iteration to support the cancel operation. while n <= 10 and not g.cancel_event.is_set(): # If you do not need to view logs from xxl-admin, you can use your own 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 "Success3" if __name__ == "__main__": app.run_executor()
2. Deploy the application to Alibaba Cloud
Alibaba Cloud Distributed Task Scheduling for XXL-JOB supports only Alibaba Cloud networks. You must deploy your application to Alibaba Cloud. The following section uses a Java application deployed to Container Service as an example.
The Container Service cluster must be in the same VPC as the Distributed Task Scheduling for XXL-JOB cluster.
In the root directory of the SpringBoot application, create a Dockerfile file.
# Replace this with your own base image 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]Use Docker to build a Docker image and upload it to the Alibaba Cloud image repository.
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.0On the page, find the target application and click Connection Configuration in the Actions column.
Log on to Alibaba Cloud Container Service and go to the target cluster. In the navigation pane on the left, choose . In the upper-right corner, click Create from YAML to create a Deployment. The following example shows how to use connection type 2 (restarting the application with the -D parameter) for the connection configuration. Replace the value in the JAVA_OPTS section of the YAML to inject environment variables as JVM parameters.

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
Step 3: Test and verify
1. Verify the executor connection
Go to the details page of the target instance. In the navigation pane on the left, click Application Management. On the application list page, click the number in the Executors column for the target application. You can view the connected executor addresses and their online status.

2. Verify the task test
Test a single-machine task
For a single-machine task, one executor is selected from all executors in the application for each execution. The selection is based on the routing policy, and the execution is idempotent.
In the navigation pane on the left, choose Task Management and click Create Task. First, configure the basic settings. Enter a Task Name and a JobHandler Name. For Associated Application, select the target application. Set Routing Policy to Polling, and then click Next.

Configure the schedule. Set Time Type to cron. Click the Use Generator button to generate a Cron Expression. This example uses an expression that runs the task once at 12:00 every day. Then, click Next.

Configure notifications. You can configure timeout alerts, success notifications, failure alerts, notification methods, and notification recipients. This example uses the default configurations in the console.

After the task is created, click Run Once in the Actions column for the target task. In the Run Task Manually dialog box, specify a machine, configure the Instance Parameters, and click OK.

Click to view the task execution records.
In the navigation pane on the left, click Execution List. In the Actions column for the target execution record, click Log to view the execution log records for this task.

Test a sharded broadcast task
A sharded broadcast task means that for each execution, the task is broadcast to all executors in the application. Each executor receives a different shard number, which can be used for distributed batch processing. The open source XXL-JOB does not have an aggregation feature for sharded broadcasts. Alibaba Cloud Distributed Task Scheduling for XXL-JOB can aggregate and display the status of all shards for each execution.
In the navigation pane on the left, choose Task Management and click Create Task. First, configure the basic settings. Enter a Task Name and a JobHandler Name. For Associated Application, select the target application. Set Routing Policy to Sharding Broadcast. Then, click Next.

Configure the schedule. Set Time Type to cron. Click the Use Generator button to generate a Cron Expression. This example uses an expression that runs the task at 10 minutes past every hour. Then, click Next.

Configure notifications. You can configure timeout alerts, success notifications, failure alerts, notification methods, and notification recipients. This example uses the default configurations in the console.

After the task is created, click Run Once in the Actions column for the target task. In the Run Task Manually dialog box, specify a machine, configure the Instance Parameters, and click OK.

Click to view the task execution records.
In the navigation pane on the left, click Execution List. On the task execution list page, click Details in the Actions column for the target task execution. In the Shard Details section, you can view the aggregated execution status of each machine.

For each shard, click Log in the Actions column for the specified shard to view the execution log records for this task.
