官网:https://www.xuxueli.com/xxl-job/

环境配置

假设目前已配置好如下环境:

Windows:JDK、Git、IDEA、Maven、Python

Linux:JDK、Kettle

gitee仓库地址

https://gitee.com/xuxueli0323/xxl-job

克隆仓库

# 默认克隆最新版本,只支持jdk17
git clone https://gitee.com/xuxueli0323/xxl-job.git
# 指定克隆版本,2.5.0支持jdk8
git clone -b 2.5.0 https://gitee.com/xuxueli0323/xxl-job.git

执行sql文件

克隆项目后,找到xxl-job\doc\db\tables_xxl_job.sql,在数据库执行即可。

注:目前xxl-job 2.5.0版的tables_xxl_job.sql是mysql语法,若需要支持其他数据库,需要自己改一下sql文件语法,并且在项目pom.xml中引入其他数据库的驱动等。

修改配置

调度中心和执行器说明

xxl-job分调度中心执行器,其中对比说明如下表:

对比维度调度中心 (Admin)执行器 (Executor)
核心角色调度大脑 - 任务调度指挥中心执行终端 - 任务具体执行节点
主要职责 1. 任务调度决策
2. 任务管理(增删改查)
3. 调度触发
4. 执行器管理
5. 日志监控
1. 任务实际执行
2. 业务逻辑处理
3. 心跳注册
4. 执行结果反馈
功能定位管理控制层 - 负责"何时执行"和"分配给谁"业务执行层 - 负责"如何执行"
部署方式独立部署,通常一个项目只需一个调度中心(支持集群)集成部署,每个需要执行任务的服务都需部署执行器
数据存储依赖数据库(MySQL等),存储任务配置、日志等不依赖数据库(除非业务需要),本地内存运行
通信方向主动调用 → 向执行器发送调度请求被动响应 ← 接收调度请求并返回结果
集群模式中心化集群:多个调度中心实例共用同一个数据库,通过数据库锁避免重复调度分布式集群:多个执行器实例注册到同一个调度中心,负载均衡执行任务
典型配置 端口:8080(默认)
数据库:MySQL
Web界面:提供管理控制台
端口:9999(默认)
AppName:执行器名称(唯一标识)
注册地址:自动/手动注册
工作流程 1. 解析任务Cron表达式
2. 到达触发时间
3. 选择合适的执行器
4. 发送HTTP请求调用任务
5. 记录执行日志
1. 启动时向调度中心注册
2. 接收调度请求
3. 通过反射调用本地JobHandler
4. 执行业务代码
5. 返回执行结果
关键配置 spring.datasource.url
spring.datasource.username
spring.datasource.password
spring.datasource.driver-class-name
xxl.job.accessToken
xxl.job.i18n
xxl.job.admin.addresses
xxl.job.admin.accessToken
xxl.job.executor.appname
xxl.job.executor.port
调度中心

目前演示克隆的是xxl-job 2.5.0版本,并且数据库也是mysql。

使用IDEA打开xxl-job项目,打开xxl-job-admin/src/main/resources/application.properties,如下,需修改数据库配置信息等。

### web【启动端口】
server.port=8080
server.servlet.context-path=/xxl-job-admin
### actuator
management.server.base-path=/actuator
management.health.mail.enabled=false
### 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://192.168.88.199:3306/xxl_job_8?useUnicode=true&characterEncoding=UTF-8&autoReconnect=true&serverTimezone=Asia/Shanghai&useSSL=false
spring.datasource.username=root
spring.datasource.password=123456
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【可选,默认token,需与执行器的保持一致】
xxl.job.accessToken=default_token
### xxl-job, access token
xxl.job.timeout=3
### xxl-job, i18n (default is zh_CN, and you can choose "zh_CN", "zh_TC" and "en")【可选,默认语言是简体中文,zh_TC:繁体中文,en:英文】【或者通过启动的时候进行指定】
xxl.job.i18n=zh_CN
## xxl-job, triggerpool max size
# 快速线程池的最大线程数,默认为200。
xxl.job.triggerpool.fast.max=200
# 慢速线程池的最大线程数,默认为100
xxl.job.triggerpool.slow.max=100
### xxl-job, log retention days
# 日志默认过期天数
xxl.job.logretentiondays=30

至少要修改### xxl-job, datasource的数据库连接信息,也就是执行sql文件的数据库信息。

执行器

打开xxl-job-executor-samples/xxl-job-executor-sample-springboot/src/main/resources/application.properties,需修改如下配置信息等。

### xxl-job admin address list, such as "http://address" or "http://address01,http://address02"【指定部署调度中心的地址,比如将调度中心部署在192.168.88.199这台服务器】
xxl.job.admin.addresses=http://192.168.88.199:8080/xxl-job-admin
### xxl-job, access token【可选,默认token,需与调度中心的保持一致】
xxl.job.admin.accessToken=default_token

修改完配置后,可以直接在IDEA分别启动调度中心执行器查看是否正常,即xxl-job-admin/src/main/java/com/xxl/job/admin/XxlJobAdminApplication.javaxxl-job-executor-samples/xxl-job-executor-sample-springboot/src/main/java/com/xxl/job/executor/XxlJobExecutorApplication.java

使用Maven进行打包

因为后期在服务器上进行部署是执行jar包的方式,故以上配置完,即可进行打包,直接在IDEA中进行打包。

在这里插入图片描述

或者在终端输入mvn package命令来进行打包。

打包完成后,找到打包的jar包,分两个,一个是调度中心,一个是执行器

在这里插入图片描述

在这里插入图片描述

部署服务

因为目前需要进行搭建服务,计划将调度中心部署在Linux服务器上,执行器在Linux和Windows上各自部署一个。

说明IP地址
调度中心IP192.168.88.199
执行器IP(Linux)192.168.88.199
执行器IP(Windows)10.181.176.27

注:执行器可配置一到多个,看自己需求。

将jar包使用FinalShell上传到Linux,

在这里插入图片描述

启动服务

Linux上需要进行启动调度中心执行器,采用后台运行。

cd /usr/local/xxl-job
# 1. 启动调度中心
nohup java -jar xxl-job-admin-2.5.0.jar > admin.log 2>&1 &
# 1. 启动调度中心(或指定显示语言为繁体中文)
# nohup java -jar xxl-job-admin-2.5.0.jar --xxl.job.i18n=zh_TC > admin.log 2>&1 &
# 2. 启动执行器  
nohup java -jar xxl-job-executor-sample-springboot-2.5.0.jar > executor.log 2>&1 &
# 若8080端口未开放,则进行如下处理
# 查看开放的端口:
firewall-cmd --zone=public --list-ports
# 开放指定端口:
firewall-cmd --zone=public --add-port=8080/tcp --permanent
# 立即生效:
firewall-cmd --reload

在这里插入图片描述

Windows需进行启动执行器,同样采用后台运行。

进入xxl-job-executor-samples\xxl-job-executor-sample-springboot\target目录下,打开PowerShell,直接执行如下命令:

# 在PowerShell中运行
Start-Process -WindowStyle Hidden -FilePath "java" -ArgumentList "-jar xxl-job-executor-sample-springboot-2.5.0.jar" -RedirectStandardOutput "executor.log" -RedirectStandardError "error.log"

在这里插入图片描述

关闭服务

Linux关闭调度中心执行器

# 查看进程(精确过滤)
ps -ef | grep xxl-job
# 强制结束
kill -9 进程ID

在这里插入图片描述

Windows关闭执行器

# 在PowerShell中运行,查看进程ID
Get-CimInstance Win32_Process -Filter "name='java.exe'" | Where-Object { $_.CommandLine -like "*xxl-job-executor-sample-springboot-2.5.0.jar*" }
# 强制结束
Stop-Process -Id 进程ID -Force

在这里插入图片描述

管理控制台

以上启动服务器后,即可进入管理控制台,在本地浏览器访问http://192.168.88.199:8080/xxl-job-admin/toLogin

默认账号:admin

默认密码:123456

在这里插入图片描述

ip地址为启动调度中心所在服务器地址

点击登录即可查看

在这里插入图片描述

注:以上运行报表信息为之前配置的,若第一次使用,则此处相关数据为空。

配置执行器

登录管理控制台后,第一步就是配置执行地址,因为部署了2个执行器,故此处需要进行配置。

点击【新增】
在这里插入图片描述

同理再新增一个windows的执行器,

在这里插入图片描述

2个执行器均配置完成如下:

在这里插入图片描述

任务管理

Linux执行器相关任务

为测试功能是否正常,点击任务管理->新增,此处测试运行模式为GLUE(Shell)是否正常,点击保存。

在这里插入图片描述

点击操作的GLUE IDE,进行编辑

在这里插入图片描述

注:默认新增任务的状态是STOP,若需要使CRON表达式生效来定时执行任务的话需要点击操作的启动使其变为RUNNING;若只想运行一次,则点击操作的执行一次即可。

Shell脚本如下:

在这里插入图片描述

进行保存即可。

测试为使用xxl-job的Linux执行器通过Shell来执行kettle-job,以上是局部Shell脚本,完整脚本在下文

Windows执行器相关任务

同理,点击任务管理->新增,此处测试运行模式为GLUE(PowerShell)是否正常,点击保存。

在这里插入图片描述

同理,点击操作的GLUE IDE,进行编辑

在这里插入图片描述

再新增运行模式为GLUE(Python)任务,点击保存。

在这里插入图片描述

同理,点击操作的GLUE IDE,进行编辑

在这里插入图片描述

测试为使用xxl-job的Windows执行器通过PowerShell或Python来执行exe,以上是局部脚本,完整脚本在下文。

任务类型为GLUE(PowerShell)会存在中文乱码情况:执行程式路径若存在中文则会找不到,并且输出的内容也会乱码,故此处测试需将脚本改为纯英文;

任务类型为GLUE(Python)来解决中文乱码情况:执行程式路径若存在中文正常执行,并且输出的内容也正常显示。

调度日志

任务配置完成后,点击三个任务的操作->执行一次即可启动执行一次任务。启动后,点击调度日志即可查看任务执行结果。

Linux执行器任务调度日志

查看执行结果:

在这里插入图片描述

点击操作->执行日志查看具体日志:

在这里插入图片描述

kettle-job功能是往目标表插入数据,为测试xxl-job的失败重试机制,故该目标表进行删除,所以执行结果一定会失败,从而测试重试机制,如下重试了一次,同样失败。

在这里插入图片描述

现在恢复创建该目标表,再次点击执行一次任务,查看调度日志:

在这里插入图片描述

查看执行日志:

在这里插入图片描述

Windows执行器任务调度日志

查看执行结果:

在这里插入图片描述

执行该exe是会显示一个时间弹窗:

在这里插入图片描述

点击操作->执行日志查看具体日志:
在这里插入图片描述

同理查看运行模式为GLUE(Python)任务的执行日志:

在这里插入图片描述

使用Python来执行exe,能解决中文乱码问题

执行状态说明

在xxl-job中,判断任务执行是否成功的标准如下,故下文的所有脚本均可以针对该规则来实现失败重试机制。

# 0代表成功,非0代表失败,若失败会触发xxl-job的自动失败重试
exit 0

执行Kettle

执行作业脚本

#!/bin/bash
source /etc/profile
KETTLE_HOME=/usr/local/kettle/data-integration
KETTLE_LOG=/usr/local/kettle/kettle_run_log
UPDATE=$(date "+%F-%H-%M-%S")
JOBNAME="job1"
# 定义完整的日志文件路径
LOG_FILE="$KETTLE_LOG/${UPDATE}_$JOBNAME.log"
# 确保日志目录存在
mkdir -p "$KETTLE_LOG"
# 执行 Kettle 作业并捕获退出码
# 注意:使用子shell来执行,这样可以捕获整个管道的退出状态
set -o pipefail  # 确保管道中任意命令失败都返回非0
# 执行 Kettle 并记录日志
bash "$KETTLE_HOME/kitchen.sh" \
-rep=repo_ssh \
-user=admin \
-pass=admin \
-dir=/ETL \
-job="$JOBNAME" \
-level=Detailed 2>&1 | tee "$LOG_FILE"
# 获取退出状态
EXIT_CODE=$?
echo "Kettle 退出代码: $EXIT_CODE"
echo "日志文件: $LOG_FILE"
# 检查日志中是否包含 ERROR(忽略大小写)
if grep -qi "ERROR" "$LOG_FILE"; then
echo "⚠️ 警告:Kettle日志中发现 ERROR 关键字!"
# 显示部分错误日志
echo "=== 发现的错误日志片段 ==="
grep -i "ERROR" "$LOG_FILE" | head -10
exit 1
# 再检查退出代码,若不等于0则判定失败
elif [ $EXIT_CODE -ne 0 ]; then
echo "❌ Kettle 执行失败,退出码: $EXIT_CODE"
exit $EXIT_CODE
else
echo "✅ 未发现 ERROR,任务成功"
exit 0
fi

执行转换脚本

#!/bin/bash
source /etc/profile
KETTLE_HOME=/usr/local/kettle/data-integration
KETTLE_LOG=/usr/local/kettle/kettle_run_log
UPDATE=$(date "+%F-%H-%M-%S")
TRANSNAME="trans1"
# 定义完整的日志文件路径
LOG_FILE="$KETTLE_LOG/${UPDATE}_$TRANSNAME.log"
# 确保日志目录存在
mkdir -p "$KETTLE_LOG"
# 执行 Kettle 作业并捕获退出码
# 注意:使用子shell来执行,这样可以捕获整个管道的退出状态
set -o pipefail  # 确保管道中任意命令失败都返回非0
# 执行 Kettle 并记录日志
bash "$KETTLE_HOME/pan.sh" \
-rep=repo_ssh \
-user=admin \
-pass=admin \
-dir=/ETL \
-trans="$TRANSNAME" \
-level=Detailed 2>&1 | tee "$LOG_FILE"
# 获取退出状态
EXIT_CODE=$?
echo "Kettle 退出代码: $EXIT_CODE"
echo "日志文件: $LOG_FILE"
# 检查日志中是否包含 ERROR(忽略大小写)
if grep -qi "ERROR" "$LOG_FILE"; then
echo "⚠️ 警告:Kettle日志中发现 ERROR 关键字!"
# 显示部分错误日志
echo "=== 发现的错误日志片段 ==="
grep -i "ERROR" "$LOG_FILE" | head -10
exit 1
# 再检查退出代码,若不等于0则判定失败
elif [ $EXIT_CODE -ne 0 ]; then
echo "❌ Kettle 执行失败,退出码: $EXIT_CODE"
exit $EXIT_CODE
else
echo "✅ 未发现 ERROR,任务成功"
exit 0
fi

执行EXE脚本

使用PowerShell

因为xxl-job执行Powershell脚本会导致中文乱码,故目前修改为全英文。

Powershell脚本:

# PowerShell script for XXL-Job
# Change to $true if administrator privileges are required
$UseAdmin = $false
$exePath = "C:\Users\Aiw\Desktop\py-exe\dist\time_popup2.exe"
# Check if the executable file exists
if (!(Test-Path $exePath)) {
Write-Output "Error: Program file not found"
exit 1
}
try {
if ($UseAdmin) {
Write-Output "Executing with administrator privileges..."
$process = Start-Process powershell.exe -ArgumentList "-Command", "Start-Process '$exePath' -Wait; exit `$LASTEXITCODE" -Verb RunAs -Wait -PassThru
} else {
Write-Output "Executing with normal privileges..."
$process = Start-Process -FilePath $exePath -Wait -PassThru -NoNewWindow
}
Write-Output "Execution completed, exit code: $($process.ExitCode)"
exit $process.ExitCode
} catch {
Write-Output "Execution failed: $_"
exit 1
}

使用Pythhon

使用Python来解决xxl-job执行Powershell脚本导致中文乱码问题,支持中文路径并且中文输出。

#!/usr/bin/env python3
import os
import subprocess
import sys
# 是否使用管理员权限
USE_ADMIN = False
# 执行的程式路径
EXE_PATH = r"C:\Users\Aiw\Desktop\py-exe中文路径测试\dist\time_popup2.exe"
# 设置输出编码为utf-8
sys.stdout.reconfigure(encoding='utf-8')
# 主逻辑
print(f"程式文件: {EXE_PATH}")
if not os.path.exists(EXE_PATH):
print("错误: 程式文件不存在!")
sys.exit(1)
try:
if USE_ADMIN:
print("使用管理员权限执行。")
cmd = f'Start-Process "{EXE_PATH}" -Verb RunAs -Wait'
result = subprocess.run(["powershell", "-Command", cmd],
capture_output=True, text=True, encoding='gbk')
else:
print("使用普通权限执行。")
result = subprocess.run([EXE_PATH],
capture_output=True, text=True, encoding='gbk')
print(f"执行完成,退出码: {result.returncode}")
# 直接返回程序的退出码
sys.exit(result.returncode)
except Exception as e:
print(f"执行失败: {e}")
sys.exit(1)