本文目录导读:

我来为您详细介绍XXL-JOB的实战案例,从基础到进阶,覆盖常见业务场景。
XXL-JOB基础介绍
XXL-JOB是一个分布式任务调度平台,核心特点:
- 简单易用(通过Web页面管理任务)
- 动态定时任务(支持CRON表达式)
- 分布式调度(支持集群部署)
- 失败重试机制
- 任务分片处理
环境搭建案例
调度中心部署
-- 初始化数据库(执行官方提供的SQL脚本) xxl_job.sql -- 修改配置文件 application.properties server.port=8080 spring.datasource.url=jdbc:mysql://localhost:3306/xxl_job?useUnicode=true&characterEncoding=UTF-8 spring.datasource.username=root spring.datasource.password=root
执行器接入SpringBoot
<!-- pom.xml 引入依赖 -->
<dependency>
<groupId>com.xuxueli</groupId>
<artifactId>xxl-job-core</artifactId>
<version>2.4.0</version>
</dependency>
# application.yml
xxl:
job:
admin:
addresses: http://localhost:8080/xxl-job-admin
executor:
appname: xxl-job-executor-sample
ip:
port: 9999
logpath: /data/applogs/xxl-job/jobhandler
logretentiondays: 30
// 执行器配置类
@Configuration
public class XxlJobConfig {
@Value("${xxl.job.admin.addresses}")
private String adminAddresses;
@Value("${xxl.job.executor.appname}")
private String appName;
@Bean
public XxlJobSpringExecutor xxlJobExecutor() {
XxlJobSpringExecutor xxlJobSpringExecutor = new XxlJobSpringExecutor();
xxlJobSpringExecutor.setAdminAddresses(adminAddresses);
xxlJobSpringExecutor.setAppname(appName);
xxlJobSpringExecutor.setPort(9999);
xxlJobSpringExecutor.setLogPath("/data/applogs/xxl-job/jobhandler");
return xxlJobSpringExecutor;
}
}
实战案例
案例1:报表定时生成
业务场景:每天凌晨2点生成前一天的销售报表
@Component
public class ReportJobHandler {
@Resource
private SalesReportService reportService;
@Resource
private EmailService emailService;
@XxlJob("dailySalesReportJob")
public void dailySalesReport() throws Exception {
// 获取任务参数(调度中心配置)
String jobParam = XxlJobHelper.getJobParam();
// 1. 获取前一天日期
String yesterday = LocalDate.now().minusDays(1)
.format(DateTimeFormatter.ofPattern("yyyy-MM-dd"));
// 2. 查询销售数据
List<SalesData> salesDataList = reportService.getDailySales(yesterday);
// 3. 生成Excel报表
Workbook workbook = ExcelGenerator.generateSalesReport(salesDataList);
// 4. 发送邮件
String[] receivers = {"manager@company.com", "finance@company.com"};
emailService.sendReportEmail(receivers,
"业务报表-" + yesterday, workbook);
// 5. 记录日志
XxlJobHelper.log("报表生成成功,数据量:{}", salesDataList.size());
}
}
案例2:订单超时处理(分片任务)
业务场景:每5分钟处理超时未支付的订单,使用分片提高效率
@Component
public class OrderTimeoutJobHandler {
@Resource
private OrderService orderService;
@XxlJob("orderTimeoutHandleJob")
public void handleTimeoutOrders() {
// 获取分片参数
int shardIndex = XxlJobHelper.getShardIndex();
int shardTotal = XxlJobHelper.getShardTotal();
XxlJobHelper.log("开始处理超时订单,分片:{}/{}",
shardIndex, shardTotal);
// 根据分片查询需要处理的订单
// WHERE MOD(order_id, shardTotal) = shardIndex
List<Order> timeoutOrders = orderService
.getTimeoutOrdersForShard(shardIndex, shardTotal);
for (Order order : timeoutOrders) {
try {
// 处理订单超时
orderService.handleTimeoutOrder(order.getId());
} catch (Exception e) {
XxlJobHelper.log("订单{}处理失败:{}",
order.getId(), e.getMessage());
}
}
XxlJobHelper.log("分片{}处理完成,共处理{}个订单",
shardIndex, timeoutOrders.size());
}
}
案例3:数据同步任务
业务场景:同步用户数据到搜索引擎
@Component
public class DataSyncJobHandler {
@Resource
private UserService userService;
@Resource
private ElasticSearchService esService;
@XxlJob("userDataSyncJob")
public void syncUserData() {
// 获取增量同步游标
String cursor = getLastSyncCursor();
// 批量查询增量用户数据
List<User> users = userService.getIncrementalUsers(cursor);
if (users.isEmpty()) {
XxlJobHelper.log("无增量数据需要同步");
return;
}
// 批量同步到ES
esService.bulkUpsertUsers(users);
// 记录增量同步游标
String lastUserId = users.get(users.size() - 1).getId();
saveLastSyncCursor(lastUserId);
XxlJobHelper.log("数据同步完成,同步用户数:{}", users.size());
}
}
案例4:动态参数任务
业务场景:灵活执行数据清理任务,通过参数控制
@Component
public class DataCleanJobHandler {
@XxlJob("dataCleanJob")
public void cleanData() {
// 从调度中心获取任务参数
String jobParam = XxlJobHelper.getJobParam();
// 解析任务参数:{"days":30,"table":"log","batchSize":1000}
JSONObject paramObj = JSONObject.parseObject(jobParam);
int days = paramObj.getIntValue("days");
String table = paramObj.getString("table");
int batchSize = paramObj.getIntValue("batchSize");
// 计算清理截止时间
Date deadline = DateTime.now()
.minusDays(days)
.toDate();
int deletedCount = 0;
while (true) {
// 分批清理数据
boolean success = dataCleanService.cleanOldData(
table, deadline, batchSize);
if (success) {
deletedCount += batchSize;
// 防止任务执行时间过长
if (XxlJobHelper.getJobDuration() > 300000) {
XxlJobHelper.log("任务执行超时,提前结束");
break;
}
} else {
break;
}
}
XxlJobHelper.log("数据清理完成,共清理{}条数据", deletedCount);
}
}
案例5:任务阻塞和失败处理
@Component
public class ComplexJobHandler {
@XxlJob("complexJob")
public ReturnT<String> complexTask(String param) {
try {
// 业务处理前检查
if (!checkPreConditions()) {
return new ReturnT<>(ReturnT.FAIL_CODE,
"前置条件不满足,终止执行");
}
// 业务处理
doBusinessLogic();
// 可以通过抛出异常触发失败重试
// throw new RuntimeException("模拟任务失败");
return ReturnT.SUCCESS;
} catch (Exception e) {
XxlJobHelper.log("任务执行异常:{}", e);
// 失败重试最多3次
if (XxlJobHelper.getJobResult().getRetryCount() < 3) {
return new ReturnT<>(ReturnT.FAIL_RETRY_CODE,
"执行失败,等待重试");
}
return new ReturnT<>(ReturnT.FAIL_CODE,
"执行失败,超过重试次数");
}
}
private void doBusinessLogic() {
// 模拟业务处理
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
}
案例6:父子任务处理
业务场景:数据同步完成后再执行数据分析
@Component
public class ParentChildJobHandler {
@Resource
private JobClientUtils jobClientUtils;
// 父任务
@XxlJob("parentSyncJob")
public void parentJob() {
// 1. 执行数据同步
syncData();
// 2. 动态触发子任务
try {
jobClientUtils.triggerChildJob("childAnalyzeJob",
"syncData_completed", 1000);
} catch (Exception e) {
XxlJobHelper.log("触发子任务失败:{}", e);
}
}
@JobHandler("childAnalyzeJob")
public void childJob() {
// 执行数据分析
}
}
案例7:库存扣减任务
@Component
public class InventoryJobHandler {
@Resource
private InventoryService inventoryService;
@XxlJob("inventoryDailyCheckJob")
public void dailyInventoryCheck() {
XxlJobHelper.log("=== 库存日结任务开始 ===");
try {
// 1. 获取所有库存
List<Inventory> inventories = inventoryService.getAllInventory();
// 2. 生成库存快照
boolean snapshotSuccess = inventoryService.createInventorySnapshot();
// 3. 库存预警检查
List<String> warningProducts = new ArrayList<>();
for (Inventory inv : inventories) {
if (inv.getStock() < inv.getWarningThreshold()) {
warningProducts.add(inv.getProductId());
}
}
// 4. 发送预警通知
if (!warningProducts.isEmpty()) {
sendStockWarningEmail(warningProducts);
}
XxlJobHelper.log("=== 库存日结任务完成,预警商品数:{} ===",
warningProducts.size());
} catch (Exception e) {
XxlJobHelper.log("库存日结任务失败:{}", e);
throw new RuntimeException("库存日结失败", e);
}
}
}
最佳实践建议
调度中心配置参数
- 阻塞处理策略:建议使用"丢弃后续调度"
- 失败重试次数:建议2-3次
- 日志保留天数:建议7-30天
任务开发规范
@XxlJob("yourJobName") // 任务名称要规范,使用驼峰命名
public void yourJob() {
// 1. 记录任务开始
XxlJobHelper.log("任务开始执行");
// 2. 获取参数(如果有)
String param = XxlJobHelper.getJobParam();
// 3. 业务处理
try {
// 业务逻辑
} catch (Exception e) {
// 4. 异常处理
XxlJobHelper.log("任务执行异常:{}", e);
throw e; // 让调度中心知道任务失败
}
// 5. 记录任务结束
XxlJobHelper.log("任务执行成功");
}
性能优化建议
- 大数据量任务使用分片
- 耗时操作异步处理
- 批量操作设置合理批次大小
- 避免任务执行时间过长(建议不超过10分钟)
监控告警建议
- 配置任务失败告警邮件/短信
- 定期检查执行器健康状态
- 设置合理的任务执行超时时间
- 监控调度中心负载情况
这些案例涵盖了XXL-JOB的主要使用场景,希望能帮助您更好地理解和使用XXL-JOB,记得根据实际业务需求调整和完善相关实现。
版权声明:NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播