Spring Boot(十)集成xxl-job:从零构建分布式任务调度中心

张开发
2026/4/17 4:48:31 15 分钟阅读

分享文章

Spring Boot(十)集成xxl-job:从零构建分布式任务调度中心
1. 为什么需要分布式任务调度在传统的单体应用中我们通常使用简单的定时任务框架比如Spring自带的Scheduled就能满足需求。但随着业务发展系统逐渐演变为分布式架构这种简单的定时任务方式就会暴露出很多问题单点故障如果运行定时任务的节点宕机整个任务就会中断重复执行多节点部署时同一个任务可能被多个节点同时触发缺乏监控无法直观查看任务执行状态和日志扩展困难新增任务需要修改代码重新部署我去年就遇到过这样的问题一个电商项目中的订单超时取消功能在单机环境下运行良好但上了集群后经常出现重复取消订单的情况。后来我们调研了多种方案最终选择了xxl-job它完美解决了这些问题。2. xxl-job核心架构解析xxl-job采用经典的调度中心执行器架构设计这种设计让系统具备了良好的扩展性和高可用性。2.1 调度中心Admin调度中心是整个系统的大脑主要职责包括任务调度触发任务路由管理调度日志收集监控报警调度中心支持集群部署通过DB锁保证集群环境下调度的一致性。在实际项目中我们通常会部署2-3个调度中心实例来保证高可用。2.2 执行器Executor执行器是实际执行业务逻辑的组件特点包括支持多种语言Java、Python等自动注册到调度中心内置负载均衡策略故障转移机制执行器通过心跳机制与调度中心保持通信当有新任务触发时调度中心会根据负载均衡策略选择合适的执行器节点。3. 环境准备与数据库配置3.1 基础环境要求在开始集成前请确保你的开发环境满足以下条件JDK 1.8Maven 3.0MySQL 5.7Spring Boot 2.x我推荐使用Docker来快速搭建MySQL环境这样可以避免本地安装的麻烦docker run --name xxl-job-mysql -e MYSQL_ROOT_PASSWORDroot -p 3306:3306 -d mysql:5.73.2 数据库初始化xxl-job需要专用的数据库来存储任务和日志信息。从官网下载的源码包中包含了初始化SQL脚本-- 位置/xxl-job/doc/db/tables_xxl_job.sql CREATE TABLE xxl_job_info ( id int(11) NOT NULL AUTO_INCREMENT, job_group int(11) NOT NULL COMMENT 执行器主键ID, job_desc varchar(255) NOT NULL, add_time datetime DEFAULT NULL, update_time datetime DEFAULT NULL, author varchar(64) DEFAULT NULL COMMENT 作者, alarm_email varchar(255) DEFAULT NULL COMMENT 报警邮件, schedule_type varchar(50) NOT NULL DEFAULT NONE COMMENT 调度类型, schedule_conf varchar(128) DEFAULT NULL COMMENT 调度配置值含义取决于调度类型, misfire_strategy varchar(50) NOT NULL DEFAULT DO_NOTHING COMMENT 调度过期策略, executor_route_strategy varchar(50) DEFAULT NULL COMMENT 执行器路由策略, executor_handler varchar(255) DEFAULT NULL COMMENT 执行器任务handler, executor_param varchar(512) DEFAULT NULL COMMENT 执行器任务参数, executor_block_strategy varchar(50) DEFAULT NULL COMMENT 阻塞处理策略, executor_timeout int(11) NOT NULL DEFAULT 0 COMMENT 任务执行超时时间单位秒, executor_fail_retry_count int(11) NOT NULL DEFAULT 0 COMMENT 失败重试次数, glue_type varchar(50) NOT NULL COMMENT GLUE类型, glue_source mediumtext COMMENT GLUE源代码, glue_remark varchar(128) DEFAULT NULL COMMENT GLUE备注, glue_updatetime datetime DEFAULT NULL COMMENT GLUE更新时间, child_jobid varchar(255) DEFAULT NULL COMMENT 子任务ID多个逗号分隔, trigger_status tinyint(4) NOT NULL DEFAULT 0 COMMENT 调度状态0-停止1-运行, trigger_last_time bigint(13) NOT NULL DEFAULT 0 COMMENT 上次调度时间, trigger_next_time bigint(13) NOT NULL DEFAULT 0 COMMENT 下次调度时间, PRIMARY KEY (id) ) ENGINEInnoDB DEFAULT CHARSETutf8mb4;执行完脚本后你会看到8张表被创建这些表分别用于存储执行器信息、任务配置、调度日志等。4. 调度中心部署与配置4.1 获取源码与编译推荐直接从GitHub获取最新稳定版本git clone https://github.com/xuxueli/xxl-job.git cd xxl-job mvn clean package -Dmaven.test.skiptrue编译完成后在xxl-job-admin/target目录下可以找到可部署的war包。4.2 关键配置详解找到application.properties配置文件这些配置项需要特别注意# 数据库配置 spring.datasource.urljdbc:mysql://localhost:3306/xxl_job?useUnicodetruecharacterEncodingUTF-8 spring.datasource.usernameroot spring.datasource.passwordroot spring.datasource.driver-class-namecom.mysql.jdbc.Driver # 邮件报警配置 spring.mail.hostsmtp.163.com spring.mail.port25 spring.mail.usernameyourmail163.com spring.mail.passwordyourpassword spring.mail.properties.mail.smtp.authtrue # 调度中心Token用于与执行器通信安全 xxl.job.accessTokendefault_token_123456 # 国际化配置 xxl.job.i18nzh_CN # 日志保留天数 xxl.job.logretentiondays30在实际部署时一定要修改数据库连接信息和邮件配置。我曾经因为忘记配置邮件报警导致任务失败时没有收到通知耽误了问题排查。4.3 启动与访问启动调度中心非常简单java -jar xxl-job-admin-2.3.0.jar启动成功后访问http://localhost:8080/xxl-job-admin使用默认账号admin/123456登录。5. Spring Boot集成执行器5.1 添加依赖在Spring Boot项目的pom.xml中添加xxl-job依赖dependency groupIdcom.xuxueli/groupId artifactIdxxl-job-core/artifactId version2.3.0/version /dependency5.2 配置执行器在application.yml中添加配置xxl: job: admin: addresses: http://127.0.0.1:8080/xxl-job-admin executor: appname: xxl-job-executor-sample address: ip: port: 9999 logpath: /data/applogs/xxl-job/jobhandler logretentiondays: 30 accessToken: default_token_123456注意appname是执行器的唯一标识调度中心通过它来识别不同的执行器集群port是执行器启动的端口确保不被其他应用占用accessToken需要与调度中心配置一致5.3 创建任务处理器xxl-job提供了两种任务开发方式推荐使用注解方式Component public class SampleXxlJob { XxlJob(demoJobHandler) public ReturnTString demoJobHandler(String param) throws Exception { // 业务逻辑 System.out.println(XXL-JOB, Hello World.); return ReturnT.SUCCESS; } XxlJob(longTimeJobHandler) public ReturnTString longTimeJobHandler(String param) throws Exception { for (int i 0; i 5; i) { System.out.println(处理中... i); TimeUnit.SECONDS.sleep(2); } return ReturnT.SUCCESS; } }每个被XxlJob注解的方法都会自动注册为任务处理器。方法名就是任务标识在调度中心创建任务时需要指定。6. 任务管理与调度6.1 创建执行器在调度中心管理界面进入执行器管理点击新增填写AppName与配置文件中一致名称填写有意义的描述注册方式选择自动注册保存后执行器会自动注册上来。如果看不到执行器检查网络连接和token配置。6.2 创建任务创建任务时需要注意这些关键参数路由策略选择FIRST第一个、ROUND轮询等Cron表达式可以使用在线工具生成运行模式BEAN模式对应注解方式JobHandler填写注解中定义的方法名阻塞处理策略单机串行、丢弃后续等6.3 任务监控调度中心提供了完善的监控功能任务列表查看执行状态调度日志记录每次执行详情执行报表统计成功率等指标我曾经利用这些监控数据发现了一个定时任务的性能问题某个报表生成任务在数据量大时经常超时通过分析日志发现是SQL查询效率低下优化后执行时间从5分钟降到了30秒。7. 高级特性与最佳实践7.1 分片广播任务对于需要处理大量数据的任务可以使用分片广播XxlJob(shardingJobHandler) public ReturnTString shardingJobHandler(String param) throws Exception { // 分片参数 ShardingUtil.ShardingVO shardingVO ShardingUtil.getShardingVo(); // 业务逻辑 System.out.println(分片编号 shardingVO.getIndex() 总分片数 shardingVO.getTotal()); return ReturnT.SUCCESS; }7.2 父子任务通过child_jobid字段可以配置任务依赖关系父任务执行成功后会自动触发子任务。7.3 最佳实践根据我的项目经验总结以下几点建议任务ID尽量使用有意义的名称方便后续维护为每个任务配置合理的超时时间和重试次数重要任务一定要配置邮件报警长时间运行的任务需要支持分片处理定期清理过期的调度日志避免数据库膨胀

更多文章