How Xxl-Job Powers Lightweight Distributed Task Scheduling in Java
This article explains the core concepts, architecture, and implementation details of the lightweight distributed scheduling platform Xxl-Job, including its scheduler center, executor, job handlers, registration, task triggering, routing strategies, execution flow, and result callbacks, with a step‑by‑step demo and code examples.
Core Concepts
Xxl-Job consists of a Scheduler Center (a web service that triggers scheduled tasks) and one or more Executors (services that actually run the task logic). The Scheduler Center stores task definitions and schedules in a database and can run in cluster mode, sharing the same database among instances.
1. Scheduler Center
Provides a UI for managing task triggers and relies on a shared database for persistence. In a cluster, instances do not communicate directly; they coordinate through the database.
2. Executor
An Executor is a service instance that runs the actual job logic. Each Executor has a name (often the service name) and can host multiple tasks.
3. Job
A Job represents a specific piece of work. Multiple jobs can be defined within a single Executor.
The Scheduler Center controls when tasks are triggered, while the Executor executes the tasks, achieving a separation of trigger logic and execution.
Demo Setup
1. Build the Scheduler Center
Clone the source code:
https://github.com/xuxueli/xxl-job.git
Configure the database connection in
/doc/dband run the project (as a JAR or directly from the IDE). Access the admin console at
http://localhost:8080/xxl-job-admin/toLoginwith default credentials
admin/123456.
2. Add Executor and Task
Create an executor named
sanyou-xxljob-demoand a task named
TestJobwith a cron expression that runs every second.
3. Code Example
<code><dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<version>2.2.5.RELEASE</version>
</dependency>
<dependency>
<groupId>com.xuxueli</groupId>
<artifactId>xxl-job-core</artifactId>
<version>2.4.0</version>
</dependency>
</dependencies></code>Configure the executor bean:
<code>@Configuration
public class XxlJobConfiguration {
@Bean
public XxlJobSpringExecutor xxlJobExecutor() {
XxlJobSpringExecutor executor = new XxlJobSpringExecutor();
executor.setAdminAddresses("http://localhost:8080/xxl-job-admin");
executor.setAppname("sanyou-xxljob-demo");
executor.setPort(9999);
executor.setAccessToken("default_token");
executor.setLogPath("./");
return executor;
}
}</code>Define a job method using
@XxlJob:
<code>@Component
public class TestJob {
private static final Logger logger = LoggerFactory.getLogger(TestJob.class);
@XxlJob("TestJob")
public void testJob() {
logger.info("TestJob任务执行了。。。");
}
}</code>When the demo runs, the task prints the log message every second.
Executor Startup Details
The executor entry point is
XxlJobSpringExecutor, which implements
SmartInitializingSingleton. During bean initialization it performs three key actions:
Initialize JobHandlers by scanning Spring beans annotated with
@XxlJoband registering them in a local cache.
Create an HTTP server (based on Netty) on the configured port to receive requests from the Scheduler Center.
Start a registration thread that reports the executor’s name, IP, and port to the Scheduler Center.
JobHandler Types
MethodJobHandler – invokes a Java method via reflection.
GlueJobHandler – allows dynamic modification of Java code through the GLUE IDE.
ScriptJobHandler – executes scripts (e.g., shell, Python).
Task Triggering Mechanism
The Scheduler Center runs a scheduling thread that queries the
xxl_job_infotable for tasks whose next trigger time is within the next 5 seconds. It classifies tasks into three groups based on how far the trigger time is from the current time and applies the configured expiration strategy (ignore or fire immediately).
To ensure only one Scheduler instance triggers a task in a clustered environment, a database row lock is acquired with:
select * from xxl_job_lock where lock_name = 'schedule_lock' for update
If the lock is obtained, the instance proceeds with scheduling.
Fast/Slow Thread Pools
Triggering involves HTTP calls to executors, which can be slow. The Scheduler records the latency of each trigger; tasks that exceed 500 ms more than ten times in a minute are moved to a slow thread pool to avoid blocking faster tasks.
Executor Selection (Routing Strategies)
When multiple executor instances exist, the Scheduler chooses one based on the configured routing strategy (first, last, round‑robin, random, consistent hash, LFU, LRU, failover, busy‑overload, or shard‑broadcast). Shard‑broadcast splits the workload across all instances.
Executor Task Execution
Upon receiving a trigger request, the executor creates a
JobThreadfor the task. The thread pulls the job from an in‑memory queue, ensuring isolation between tasks. If the selected executor is already busy, the Scheduler’s blocking strategy (serial, discard, or cover) determines how to handle the new trigger.
Result Callback
After execution, the
JobThreadplaces the result into a queue. A dedicated
TriggerCallbackThreadbatches these results and sends them back to the Scheduler Center, which updates the task status and handles retries or downstream jobs.
Conclusion
Xxl-Job provides a simple yet powerful architecture for distributed task scheduling, with clear separation of scheduling and execution, flexible routing, and robust handling of latency and concurrency.
macrozheng
Dedicated to Java tech sharing and dissecting top open-source projects. Topics include Spring Boot, Spring Cloud, Docker, Kubernetes and more. Author’s GitHub project “mall” has 50K+ stars.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.