Fading Coder

One Final Commit for the Last Sprint

Home > Tech > Content

Distributed Task Scheduling with XXL-JOB

Tech 1

Overview

What is Task Scheduling?

Consider the following real-world scenarios:

  • A coupon distribution system that automatically issues vouchers at 10:00 AM, 3:00 PM, and 8:00 PM daily
  • A banking application that sends SMS reminders three days before credit card payment due dates
  • A finance platform that reconciles and aggregates the previous day's transactions at 00:10 every morning

These are the types of problems task scheduling is designed to solve. Task scheduling automates the execution of specific jobs at predetermined times without manual intervention.

Why Distributed Scheduling?

Spring Framework provides a built-in scheduling mechanism through the @Scheduled annotation. By annotating a method in a service class and enabling scheduling on the application entry point, you can achieve basic task automation:

@Scheduled(cron = "0/20 * * * * ?")
public void processBatch() {
    // batch processing logic
}
@SpringBootApplication
@EnableScheduling
public class Application {
    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }
}

This approach works well for single-instance deployments. However, when your application runs acros multiple nodes in a distributed or clustered environment, serious problems emerge.

Consider a daily point accumulation feature that awards users bonus points at midnight. In a single-server setup, @Scheduled handles this correctly. But in a clustered environment where three application instances are running behind a load balancer, each instance would independently trigger the job—resulting in triple credit issuance for every user.

While you could theoretically configure only one instance to run scheduled tasks, this introduces critical vulnerabilities:

  1. Single Point of Failure: If the designated instance crashes or becomes unavailable, the scheduled task never executes.
  2. Resource Bottleneck: A single server must handle the full computational load of all scheduled jobs, leading to performance degradation.
  3. Scalability Limits: When order volume grows from 10,000 to 100,000 per minute, a single server's CPU, memory, and I/O capacity becomes a hard ceiling that cannot be exceeded regardless of optimization efforts.

Distributed scheduling solves these problems by centralizing job coordination while allowing execution to be distributed across multiple nodes.

XXL-JOB Architecture

XXL-JOB is an open-source distributed task scheduling platform originally developed by Dianping. It is designed for rapid development, minimal learning curve, lightweight footprint, and easy extensibility. The platform has been running in production at Dianping, handling over one million job executions.

Other companies known to use XXL-JOB include JD.com, Uxin, 360 Financial, Lenovo, and NetEase.

The architecture separates concerns into two core components:

  • Admin (调度中心): The centralized management console responsible for job registration, triggering requests, and monitoring. It does not contain any business logic.
  • Executor: The worker component deployed alongside your application that receives调度 requests from the admin and executes the corresponding job handlers.

This decoupling ensures that business logic and scheduling logic remain independent, improving system stability and making horizontal scaling straightforward.

Quick Start Guide

Source Code

Clone the repository:

git clone https://gitee.com/xuxueli03.23/xxl-job.git

Key directories:

Directory Purpose
doc/ Database scripts and documentation
xxl-job-core/ Shared library containing core scheduling logic
xxl-job-admin/ Spring Boot application serving as the admin console
xxl-job-executor-samples/ Example executor implementations

Database Setup

Execute the SQL initialization script included in the repository:

mysql -u root -p < doc/db/tables_xxl_job.sql

This creates the necesssary tables for job metadata, execution logs, and registry information.

Deploying the Admin Console

Configuration

Update the database connection settings in xxl-job-admin/src/main/resources/application.properties:

spring.datasource.url=jdbc:mysql://192.168.202.200:3306/xxl_job?useUnicode=true&characterEncoding=UTF-8&autoReconnect=true&serverTimezone=Asia/Shanghai
spring.datasource.username=your_username
spring.datasource.password=your_password
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver

spring.mail.host=smtp.qq.com
spring.mail.port=25
spring.mail.username=alerts@example.com
spring.mail.from=alerts@example.com
spring.mail.properties.mail.smtp.auth=true

Startup

Run XxlJobAdminApplication directly from your IDE or via the command line. The admin console will be available at:

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

Default credentials: admin / 123456

Deploying the Executor

Maven Dependency

Add the following dependency to your Spring Boot project's pom.xml:

<dependency>
    <groupId>com.xuxueli</groupId>
    <artifactId>xxl-job-core</artifactId>
    <version>2.3.1</version>
</dependency>

Configuration

Add the following properties to your application.properties:

xxl.job.admin.addresses=http://127.0.0.1:8080/xxl-job-admin
xxl.job.accessToken=default_token
xxl.job.executor.appname=my-task-executor
xxl.job.executor.ip=127.0.0.1
xxl.job.executor.port=9999
xxl.job.executor.logpath=/data/applogs/xxl-job/executor
xxl.job.executor.logretentiondays=30

Executor Bean Configuration

Create a configuration class to initialize the executor:

@Configuration
public class XxlJobConfiguration {

    @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.ip}")
    private String ip;


    @Value("${xxl.job.executor.port}")
    private int port;


    @Bean
    public XxlJobExecutor xxlJobExecutor() {
        XxlJobExecutor executor = new XxlJobExecutor();
        executor.setAdminAddresses(adminAddresses);
        executor.setAppname(appname);
        executor.setIp(ip);
        executor.setPort(port);
        executor.setAccessToken(accessToken);
        executor.setLogPath("/data/applogs/xxl-job/executor");
        executor.setLogRetentionDays(30);
        return executor;
    }
}

Bean Mode: Method-Based Tasks

The Bean mode supports method-level job development. Each job is implemented as a simple method annotated with @XxlJob, and the framework automatically registers it as a handler in the executor container.

Advantages:

  • Minimal boilerplate: only one method and annotation per job
  • Automatic discovery: jobs are scanned and registered at startup without additional configuration
  • Clean separation between business logic and scheduling infrastructure

Example Job Handler

@Component
public class UserPointJobHandler {

    private static final Logger logger = LoggerFactory.getLogger(UserPointJobHandler.class);

    @XxlJob("dailyPointAwardJob")
    public ReturnT<String> execute(String param) {
        logger.info("Daily point award job started");
        try {
            // Business logic: award points to all active users
            List<User> activeUsers = userService.findActiveUsers();
            for (User user : activeUsers) {
                pointService.awardPoints(user.getId(), 10);
            }
            logger.info("Point award completed for {} users", activeUsers.size());
            return new ReturnT<>(ReturnT.SUCCESS_CODE, "Processed " + activeUsers.size() + " users");
        } catch (Exception e) {
            logger.error("Point award job failed", e);
            return new ReturnT<>(ReturnT.FAIL_CODE, e.getMessage());
        }
    }
}

The job method accepts an optional param string (configured in the admin console) and returns a ReturnT object indicating success or failure along with a message.

Register this executor application in the XXL-JOB admin console, then create a new job entry with:

  • Job Name: Daily Point Award
  • Job Group: your executor group
  • Handler: dailyPointAwardJob
  • Cron: 0 0 0 * * ? (midnight daily)
  • Route Strategy: FIRST (ensures only one node executes the job)

The platform handles shard routing, conflict prevention, and execution logging automatically.

Related Articles

Understanding Strong and Weak References in Java

Strong References Strong reference are the most prevalent type of object referencing in Java. When an object has a strong reference pointing to it, the garbage collector will not reclaim its memory. F...

Comprehensive Guide to SSTI Explained with Payload Bypass Techniques

Introduction Server-Side Template Injection (SSTI) is a vulnerability in web applications where user input is improper handled within the template engine and executed on the server. This exploit can r...

Implement Image Upload Functionality for Django Integrated TinyMCE Editor

Django’s Admin panel is highly user-friendly, and pairing it with TinyMCE, an effective rich text editor, simplifies content management significantly. Combining the two is particular useful for bloggi...

Leave a Comment

Anonymous

◎Feel free to join the discussion and share your thoughts.