Master Distributed Task Scheduling with XXL‑Job: Step‑by‑Step Guide and Code Walkthrough

This article introduces the lightweight open‑source XXL‑Job framework, walks through server and executor setup, demonstrates three task creation methods, explains how to trigger and monitor jobs, and highlights the dynamic‑proxy and asynchronous design that enable high‑throughput distributed scheduling in Spring Boot applications.

Top Architect
Top Architect
Top Architect
Master Distributed Task Scheduling with XXL‑Job: Step‑by‑Step Guide and Code Walkthrough

Project Introduction

xxl-job is a lightweight open‑source distributed scheduling framework with a management console and executor nodes. The admin side configures tasks and views logs, while the executor runs the task logic.

Practical Steps

1. Server Deployment

Download the project from https://github.com/xuxueli/xxl-job, execute the SQL script doc/db/table_xxl_job.sql to create the required tables, copy the admin files into a new Spring Boot project, and configure the database connection in application.properties. After building, start the application and open http://localhost:8080/xxl-job-admin/ (default admin/123456).

2. Executor Configuration

Create a new module, add xxl-job-core dependency, adjust logback.xml, and provide two configuration files (e.g., application-9998.properties and application-9999.properties) with different server.port and xxl.job.executor.port values to simulate two executor instances.

Define a @Configuration class that creates a XxlJobSpringExecutor bean using the properties.

3. Task Development

Three common task types are demonstrated:

Method‑annotation task (add @XxlJob on a Spring bean method).

API‑based task (implement JobHandler and register it).

Shard‑broadcast task (use ShardStrategy to run on all executors).

4. Task Execution

Create a job with a round‑robin routing strategy, set a cron expression, and specify the handler name (e.g., myJobAnnotationHandler). Trigger the job manually to see the execution result and logs.

5. Task Logs

Logs are stored in the admin console, showing execution details, parameters, and any errors.

Design Highlights

The framework uses a dynamic‑proxy pattern to hide communication details. Interfaces ExecutorBiz and AdminBiz define operations, while XxlRpcReferenceBean generates a proxy that performs remote calls.

All executor messages are processed asynchronously: incoming tasks are placed into a LinkedBlockingQueue, and worker threads consume them, reducing Netty thread load and improving throughput.

Asynchronous results are wrapped so that the caller sees a synchronous API. The scheduler blocks on a XxlRpcFutureResponse until the executor returns the result, using a UUID request ID to match responses to waiting threads.

public static ReturnT<String> runExecutor(TriggerParam triggerParam, String address) {
    ReturnT<String> runResult = null;
    try {
        ExecutorBiz executorBiz = XxlJobScheduler.getExecutorBiz(address);
        // synchronous result after async processing
        runResult = executorBiz.run(triggerParam);
    } catch (Exception e) {
        logger.error(">>> xxl-job trigger error, please check if the executor[{}] is running.", address, e);
        runResult = new ReturnT<>(ReturnT.FAIL_CODE, ThrowableUtil.toString(e));
    }
    StringBuilder sb = new StringBuilder(I18nUtil.getString("jobconf_trigger_run") + ":");
    sb.append("<br>address:").append(address);
    sb.append("<br>code:").append(runResult.getCode());
    sb.append("<br>msg:").append(runResult.getMsg());
    runResult.setMsg(sb.toString());
    return runResult;
}
// Proxy invocation for synchronous call
if (CallType.SYNC == callType) {
    XxlRpcFutureResponse futureResponse = new XxlRpcFutureResponse(invokerFactory, xxlRpcRequest, null);
    try {
        client.asyncSend(finalAddress, xxlRpcRequest);
        XxlRpcResponse xxlRpcResponse = futureResponse.get(timeout, TimeUnit.MILLISECONDS);
        if (xxlRpcResponse.getErrorMsg() != null) {
            throw new XxlRpcException(xxlRpcResponse.getErrorMsg());
        }
        return xxlRpcResponse.getResult();
    } catch (Exception e) {
        logger.info(">>> xxl-rpc, invoke error, address:{}, XxlRpcRequest{}", finalAddress, xxlRpcRequest);
        throw (e instanceof XxlRpcException) ? e : new XxlRpcException(e);
    } finally {
        futureResponse.removeInvokerFuture();
    }
}
// Future response handling
public void setResponse(XxlRpcResponse response) {
    this.response = response;
    synchronized (lock) {
        done = true;
        lock.notifyAll();
    }
}

public XxlRpcResponse get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException {
    if (!done) {
        synchronized (lock) {
            try {
                if (timeout < 0) {
                    lock.wait();
                } else {
                    long timeoutMillis = (unit == TimeUnit.MILLISECONDS) ? timeout : TimeUnit.MILLISECONDS.convert(timeout, unit);
                    lock.wait(timeoutMillis);
                }
            } catch (InterruptedException e) {
                throw e;
            }
        }
    }
    if (!done) {
        throw new XxlRpcException("xxl-rpc, request timeout at:" + System.currentTimeMillis() + ", request:" + request.toString());
    }
    return response;
}
Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

Distributed SchedulingSpring BootXXL-JOBasynchronous processingtask executionDynamic Proxy
Top Architect
Written by

Top Architect

Top Architect focuses on sharing practical architecture knowledge, covering enterprise, system, website, large‑scale distributed, and high‑availability architectures, plus architecture adjustments using internet technologies. We welcome idea‑driven, sharing‑oriented architects to exchange and learn together.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.