关于xxl-job的一些使用小感悟

xxl-job作为任务调度的工具,可以实现任务调度到不同机器处理,查看任务处理的耗时和日志,并且可以通过扩充executor数量的方式,实现任务的并发,可以说是一个比较简单的且易上手的调度工具。

xxl-job分为两部分,xxl-job-admin表示调度任务的组件,负责管理执行器(executor)、任务管理及调度日志,第二部分就是executor,可以在多个节点部署,单节点可以部署1个或者多个。

项目地址:github.com/xuxueli/xxl...

部署步骤

  • 1 在mysql数据库中导入数据表,可以新建schema,也可以添加自有的schema,其中doc/db/tables_xxl_job.sql在github项目中
mysql 复制代码
mysql -uroot -p
CREATE DATABASE xxl_job DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;
# 下载源码下的doc下
mysql -uroot -p xxl_job < doc/db/tables_xxl_job.sql
# 依赖jdk17
sudo apt install openjdk-17-jdk
# 创建xxl用户
CREATE USER 'xxl'@'localhost' IDENTIFIED BY 'root@123';
GRANT ALL PRIVILEGES ON xxl_job.* TO 'xxl'@'localhost';
FLUSH PRIVILEGES;
  • 2 启动xxl-job-admin,可以使用默认配置,也可以通过添加properties和logback.xml,默认的用户名和密码为admin/12345
shell 复制代码
user=test
PRO_PATH=/home/${user}/xxl/conf
APP_PATH=/home/${user}/xxl/app
LOG_PATH=/home/${user}/xxl/logs
SERVICE_PATH=/etc/systemd/system
BASE_APP_PATH=/home/${user}
mkdir -p ${PRO_PATH}
mkdir -p ${APP_PATH}
mkdir -p ${LOG_PATH}

generate_admin_properties(){
cat <<EOF > ${PRO_PATH}/logback-admin.xml
<?xml version="1.0" encoding="UTF-8"?>
<configuration debug="false" scan="true" scanPeriod="1 seconds">

    <contextName>logback</contextName>
    <property name="log.path" value="${LOG_PATH}/server/xxl-job-admin.log"/>

    <appender name="console" class="ch.qos.logback.core.ConsoleAppender">
        <encoder>
            <pattern>%d{HH:mm:ss.SSS} %contextName [%thread] %-5level %logger{36} - %msg%n</pattern>
        </encoder>
    </appender>

    <appender name="file" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <file>${log.path}</file>
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <fileNamePattern>${log.path}.%d{yyyy-MM-dd}.zip</fileNamePattern>
        </rollingPolicy>
        <encoder>
            <pattern>%date %level [%thread] %logger{36} [%file : %line] %msg%n
            </pattern>
        </encoder>
    </appender>

    <root level="info">
        <appender-ref ref="console"/>
        <appender-ref ref="file"/>
    </root>

</configuration>
EOF

cat <<EOF > ${PRO_PATH}/application-admin.properties
### web
server.port=8080
server.servlet.context-path=/xxl-job-admin

### actuator
management.server.base-path=/actuator
management.health.mail.enabled=false
logging.config=file:${PRO_PATH}/logback-admin.xml
### resources
spring.mvc.servlet.load-on-startup=0
spring.mvc.static-path-pattern=/static/**
spring.web.resources.static-locations=classpath:/static/

### freemarker
spring.freemarker.templateLoaderPath=classpath:/templates/
spring.freemarker.suffix=.ftl
spring.freemarker.charset=UTF-8
spring.freemarker.request-context-attribute=request
spring.freemarker.settings.number_format=0.##########
spring.freemarker.settings.new_builtin_class_resolver=safer

### mybatis
mybatis.mapper-locations=classpath:/mybatis-mapper/*Mapper.xml

### datasource-pool
spring.datasource.type=com.zaxxer.hikari.HikariDataSource
spring.datasource.hikari.minimum-idle=10
spring.datasource.hikari.maximum-pool-size=30
spring.datasource.hikari.auto-commit=true
spring.datasource.hikari.idle-timeout=30000
spring.datasource.hikari.pool-name=HikariCP
spring.datasource.hikari.max-lifetime=900000
spring.datasource.hikari.connection-timeout=10000
spring.datasource.hikari.connection-test-query=SELECT 1
spring.datasource.hikari.validation-timeout=1000

### xxl-job, datasource
spring.datasource.url=jdbc:mysql://localhost:3306/hdmap?useUnicode=true&characterEncoding=UTF-8&autoReconnect=true&serverTimezone=Asia/Shanghai
spring.datasource.username=root
spring.datasource.password=root123
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver

### xxl-job, email
spring.mail.host=smtp.qq.com
spring.mail.port=25
spring.mail.username=xxx@qq.com
spring.mail.from=xxx@qq.com
spring.mail.password=xxx
spring.mail.properties.mail.smtp.auth=true
spring.mail.properties.mail.smtp.starttls.enable=true
spring.mail.properties.mail.smtp.starttls.required=true
spring.mail.properties.mail.smtp.socketFactory.class=javax.net.ssl.SSLSocketFactory

### xxl-job, access token
xxl.job.accessToken=default_token

### xxl-job, timeout
xxl.job.timeout=3

### xxl-job, i18n (default is zh_CN, and you can choose "zh_CN", "zh_TC" and "en")
xxl.job.i18n=zh_CN

## xxl-job, triggerpool max size
xxl.job.triggerpool.fast.max=200
xxl.job.triggerpool.slow.max=100

### xxl-job, log retention days
xxl.job.logretentiondays=30
EOF

}
启动脚本 复制代码
generate_admin_service(){
JAVA_OPTS="-Xms2048m -Xmx2048m -Dlogback.configurationFile=${PRO_PATH}/logback-admin.xml"
cat <<EOF | sudo tee ${SERVICE_PATH}/xxl-job-admin.service  > /dev/null
[Unit]
Description=xxl-job-admin
After=network.target

[Service]
# 启动用户(推荐非 root)
User=${user}
Group=${user}

# 程序目录
WorkingDirectory=${APP_PATH}

# 启动命令,可以通过 ENV_PROFILE 控制 dev/prod
#Environment=""
#Environment="PROFILE=dev"
ExecStart=/usr/bin/java ${JAVA_OPTS} \
  -jar ${APP_PATH}/xxl-job-admin-3.1.1.jar  --spring.config.location=${PRO_PATH}/application-admin.properties

# 停止命令
ExecStop=/bin/kill -s TERM $MAINPID

# 日志输出
#StandardOutput=append:${LOG_PATH}/admin/xxl-job-admin.out
#StandardError=append:${LOG_PATH}/admin/xxl-job-admin.err

# 自动重启策略
Restart=on-failure
RestartSec=5

[Install]
WantedBy=multi-user.target
EOF
}
  • 3 选择机器启动xxl-job-executor,注意设置xxl.job.executor.appname、xxl.job.admin.addresses
shell 复制代码
# 传入参数: 8081 9981 xxl-job-executor-test
generate_executor_properties(){
  executor_server_port=$1
  executor_xxl_port=$2
  xxl_app_name=$3

  handler="testHandler"
cat <<EOF > ${PRO_PATH}/logback-${executor_xxl_port}.xml
<?xml version="1.0" encoding="UTF-8"?>
<configuration debug="false" scan="true" scanPeriod="1 seconds">

    <contextName>logback</contextName>
    <property name="log.path" value="${LOG_PATH}/server/xxl-job-executor-${executor_xxl_port}.log"/>

    <appender name="console" class="ch.qos.logback.core.ConsoleAppender">
        <encoder>
            <pattern>%d{HH:mm:ss.SSS} %contextName [%thread] %-5level %logger{36} - %msg%n</pattern>
        </encoder>
    </appender>

    <appender name="file" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <file>${log.path}</file>
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <fileNamePattern>${log.path}.%d{yyyy-MM-dd}.zip</fileNamePattern>
        </rollingPolicy>
        <encoder>
            <pattern>%date %level [%thread] %logger{36} [%file : %line] %msg%n
            </pattern>
        </encoder>
    </appender>

    <root level="info">
        <appender-ref ref="console"/>
        <appender-ref ref="file"/>
    </root>

</configuration>
EOF

cat <<EOF > ${PRO_PATH}/application-executor-${executor_xxl_port}.properties
# web port
server.port=${executor_server_port}
# no web
#spring.main.web-environment=false

# log config
#logging.config=classpath:logback.xml
logging.config=file:${PRO_PATH}/logback-${executor_xxl_port}.xml


### xxl-job admin address list, such as "http://address" or "http://address01,http://address02"
xxl.job.admin.addresses=http://127.0.0.1:8080/xxl-job-admin
### xxl-job, access token
xxl.job.admin.accessToken=default_token
### xxl-job timeout by second, default 3s
xxl.job.admin.timeout=3

### xxl-job executor appname
xxl.job.executor.appname=${xxl_app_name}
### xxl-job executor registry-address: default use address to registry , otherwise use ip:port if address is null
xxl.job.executor.address=
### xxl-job executor server-info
xxl.job.executor.ip=
xxl.job.executor.port=${executor_xxl_port}
### xxl-job executor log-path
xxl.job.executor.logpath=${LOG_PATH}/xxl-job-bxn/jobhandler
### xxl-job executor log-retention-days
xxl.job.executor.logretentiondays=30
xxl.job.handlers=${handler}
EOF
}

启动脚本

shell 复制代码
generate_executor_service(){
JAVA_OPTS="-Xms512m -Xmx1024m -Dlogback.configurationFile=${PRO_PATH}/logback-${executor_xxl_port}.xml"

executor_xxl_port=$1
cat <<EOF | sudo tee ${SERVICE_PATH}/xxl-job-executor-${executor_xxl_port}.service > /dev/null
[Unit]
Description=xxl-job-executor-${executor_xxl_port}
After=network.target

[Service]
# 启动用户(推荐非 root)
User=${user}
Group=${user}

# 程序目录
WorkingDirectory=${APP_PATH}

# 启动命令,可以通过 ENV_PROFILE 控制 dev/prod
#Environment=""
#Environment="PROFILE=dev"
ExecStart=/usr/bin/java ${JAVA_OPTS} \
  -jar ${APP_PATH}/xxl-job-executor-3.1.1.jar  --spring.config.location=${PRO_PATH}/application-executor-${executor_xxl_port}.properties

# 停止命令
ExecStop=/bin/kill -s TERM $MAINPID

# 日志输出
#StandardOutput=append:${LOG_PATH}/executor/xxl-job-executor-${executor_xxl_port}.out
#StandardError=append:${LOG_PATH}/executor/xxl-job-executor-${executor_xxl_port}.err

# 自动重启策略
Restart=on-failure
RestartSec=5

[Install]
WantedBy=multi-user.target
EOF

}
  • 4 在xxl-job-admin中配置执行器,执行器的名称与xxl.job.executor.appname一致,这样就可以通过启动executor实现自动注册

  • 5 在xxl-job-admin中选择执行器配置任务管理,选择非定时类型,然后jobHandler中设置executor中对应的handler,路由策略选择轮询。

  • 6 通过脚本调用,实现任务调度。

python 复制代码
import requests

admin_url = "http://localhost:8080/xxl-job-admin"  # 修改为你的 Admin 地址
username = "admin"
password = "123456"

session = requests.Session()
login_resp = session.post(
    f"{admin_url}/login",
    data={"userName": username, "password": password}
)

if login_resp.status_code == 200 and "XXL_JOB_LOGIN_IDENTITY" in session.cookies:
    print("✅ 登录成功")
else:
    print("❌ 登录失败")

params = {
    "start": 0,
    "length": 10,
    "jobGroup": 1,  # 替换为你实际的 jobGroup ID
    "triggerStatus": 0,
    "jobDesc": "",
    "executorHandler": "",
    "author": ""
}
job_list_resp = session.get(f"{admin_url}/jobinfo/pageList", params=params)
print("任务列表:", job_list_resp.json())

params = {
    "start": 0,
    "length": 10
}
#job_group_list_resp = session.get(f"{admin_url}/jobgroup/pageList", params=params)
#print("任务列表:", job_group_list_resp.json())

trigger_resp = session.get(f"{admin_url}/jobinfo/trigger", params={
    "id": 4,            # 任务 ID
    "executorParam": "{'id':'1','uuid':'ssddxxx-ssshajka'}",  # 传递给 executor 的参数
    "addressList": ""   # 可选指定机器 IP
})

if trigger_resp.status_code == 200:
    print("✅ 成功触发任务")
else:
    print("❌ 触发失败:", trigger_resp.text)
相关推荐
京东零售技术6 小时前
理论到实战,高可用架构踩坑说明书
后端
SimonKing6 小时前
你的图片又被别人“白嫖”了?用这篇Java防盗链攻略说再见!
java·后端·程序员
Olaf_n6 小时前
SpringBoot中的监听机制
后端
Olaf_n6 小时前
SpringBoot启动流程
后端
DS小龙哥7 小时前
基于STM32设计的智能盲人辅助导航系统设计
后端
DS小龙哥7 小时前
基于华为云设计的智能宠物喂养管理系统
后端
David爱编程7 小时前
synchronized 的可重入性:避免死锁的隐藏武器
java·后端
二闹7 小时前
Python字符串格式化:谁才是真正的硬汉?
后端·python
Livingbody7 小时前
零代码实践自然语言处理 - 文本分类任务实现,以qwen模型和OpenAI SDK为例
后端