XXL-JOB 分布式任务调度平台部署
# 一、简介
XXL-JOB 是一个轻量级分布式任务调度平台,核心设计目标是开发迅速、学习简单、轻量级、易扩展。现已开放源代码,开箱即用。
# 特性
- 简单灵活:提供 Web 管理界面,支持动态修改任务状态、暂停/恢复任务
- 丰富路由策略:轮询、随机、一致性 HASH、分片广播等
- 故障转移:执行器心跳检测,自动故障转移
- 弹性扩容:执行器自动注册,动态扩容缩容
- 任务持久化:支持 MySQL 存储,任务数据持久化
# 架构
┌─────────────────┐ ┌─────────────────┐
│ XXL-JOB Admin │────▶│ MySQL 8.0 │
│ (调度中心) │ │ (数据存储) │
└────────┬────────┘ └─────────────────┘
│
▼ 注册/回调
┌─────────────────┐
│ XXL-JOB Exec │
│ (执行器) │
└─────────────────┘
1
2
3
4
5
6
7
8
9
10
2
3
4
5
6
7
8
9
10
# 二、环境要求
| 组件 | 版本 | 说明 |
|---|---|---|
| Docker | 20.10+ | 容器运行环境 |
| Docker Compose | 2.0+ | 服务编排 |
| MySQL | 8.0 | 数据存储 |
| 内存 | ≥ 700MB | Admin + MySQL 约占用 |
# 三、目录结构
/home/xxl-job/
├── docker-compose.yml # 服务编排配置
├── init-sql/
│ └── xxl_job.sql # 数据库初始化脚本
├── mysql-data/ # MySQL 数据目录
└── logs/ # Admin 日志目录
1
2
3
4
5
6
2
3
4
5
6
# 四、部署步骤
# 4.1 创建目录
mkdir -p /home/xxl-job/{init-sql,mysql-data,logs}
1
# 4.2 编写 Docker Compose 配置
# /home/xxl-job/docker-compose.yml
services:
xxl-job-mysql:
image: mysql:8.0
container_name: xxl-job-mysql
restart: unless-stopped
environment:
MYSQL_ROOT_PASSWORD: xxljob2026root
MYSQL_DATABASE: xxl_job
MYSQL_USER: xxljob
MYSQL_PASSWORD: xxljob2026secret
TZ: Asia/Shanghai
volumes:
- ./mysql-data:/var/lib/mysql
- ./init-sql:/docker-entrypoint-initdb.d
networks:
- xxl-job-network
command: --default-authentication-plugin=mysql_native_password --character-set-server=utf8mb4 --collation-server=utf8mb4_unicode_ci
healthcheck:
test: ["CMD", "mysqladmin", "ping", "-h", "localhost"]
interval: 10s
timeout: 5s
retries: 5
xxl-job-admin:
image: xuxueli/xxl-job-admin:2.4.0
container_name: xxl-job-admin
restart: unless-stopped
ports:
- "9080:8080"
environment:
- PARAMS=--spring.datasource.url=jdbc:mysql://xxl-job-mysql:3306/xxl_job?useUnicode=true&characterEncoding=UTF-8&autoReconnect=true&serverTimezone=Asia/Shanghai --spring.datasource.username=xxljob --spring.datasource.password=xxljob2026secret --xxl.job.accessToken=your-access-token
- JAVA_OPTS=-Xms256m -Xmx384m
volumes:
- ./logs:/data/applogs
networks:
- xxl-job-network
depends_on:
xxl-job-mysql:
condition: service_healthy
networks:
xxl-job-network:
driver: bridge
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
# 4.3 编写初始化 SQL 脚本
-- /home/xxl-job/init-sql/xxl_job.sql
-- XXL-JOB 数据库初始化脚本
SET NAMES utf8mb4;
-- 执行器信息表
CREATE TABLE IF NOT EXISTS `xxl_job_group` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`app_name` varchar(64) NOT NULL COMMENT '执行器AppName',
`title` varchar(12) NOT NULL COMMENT '执行器名称',
`address_type` tinyint(4) NOT NULL DEFAULT '0' COMMENT '执行器地址类型:0=自动注册、1=手动录入',
`address_list` text COMMENT '执行器地址列表,多地址逗号分隔',
`update_time` datetime DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
-- 任务信息表
CREATE TABLE IF NOT EXISTS `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`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
-- 执行日志表
CREATE TABLE IF NOT EXISTS `xxl_job_log` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`job_group` int(11) NOT NULL COMMENT '执行器主键ID',
`job_id` int(11) NOT NULL COMMENT '任务,主键ID',
`executor_address` varchar(255) DEFAULT NULL COMMENT '执行器地址',
`executor_handler` varchar(255) DEFAULT NULL COMMENT '执行器任务handler',
`executor_param` varchar(512) DEFAULT NULL COMMENT '执行器任务参数',
`executor_sharding_param` varchar(20) DEFAULT NULL COMMENT '执行器任务分片参数',
`executor_fail_retry_count` int(11) NOT NULL DEFAULT '0' COMMENT '失败重试次数',
`trigger_time` datetime DEFAULT NULL COMMENT '调度-时间',
`trigger_code` int(11) NOT NULL COMMENT '调度-结果',
`trigger_msg` text COMMENT '调度-日志',
`handle_time` datetime DEFAULT NULL COMMENT '执行-时间',
`handle_code` int(11) NOT NULL COMMENT '执行-状态',
`handle_msg` text COMMENT '执行-日志',
`alarm_status` tinyint(4) NOT NULL DEFAULT '0' COMMENT '告警状态',
PRIMARY KEY (`id`),
KEY `I_trigger_time` (`trigger_time`),
KEY `I_handle_code` (`handle_code`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
-- 日志报表
CREATE TABLE IF NOT EXISTS `xxl_job_log_report` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`trigger_day` datetime DEFAULT NULL,
`running_count` int(11) NOT NULL DEFAULT '0',
`suc_count` int(11) NOT NULL DEFAULT '0',
`fail_count` int(11) NOT NULL DEFAULT '0',
`update_time` datetime DEFAULT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `i_trigger_day` (`trigger_day`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
-- GLUE历史版本
CREATE TABLE IF NOT EXISTS `xxl_job_logglue` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`job_id` int(11) NOT NULL,
`glue_type` varchar(50) DEFAULT NULL,
`glue_source` mediumtext,
`glue_remark` varchar(128) NOT NULL,
`add_time` datetime DEFAULT NULL,
`update_time` datetime DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
-- 执行器注册表
CREATE TABLE IF NOT EXISTS `xxl_job_registry` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`registry_group` varchar(50) NOT NULL,
`registry_key` varchar(255) NOT NULL,
`registry_value` varchar(255) NOT NULL,
`update_time` datetime DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `i_g_k_v` (`registry_group`,`registry_key`,`registry_value`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
-- 用户表
CREATE TABLE IF NOT EXISTS `xxl_job_user` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`username` varchar(50) NOT NULL,
`password` varchar(50) NOT NULL,
`role` tinyint(4) NOT NULL COMMENT '角色:0-普通用户、1-管理员',
`permission` varchar(255) DEFAULT NULL COMMENT '权限',
PRIMARY KEY (`id`),
UNIQUE KEY `i_username` (`username`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
-- 锁表
CREATE TABLE IF NOT EXISTS `xxl_job_lock` (
`lock_name` varchar(50) NOT NULL,
PRIMARY KEY (`lock_name`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
-- 初始化数据
INSERT INTO `xxl_job_group`(`id`, `app_name`, `title`, `address_type`, `address_list`, `update_time`)
VALUES (1, 'xxl-job-executor-sample', '示例执行器', 0, NULL, NOW());
INSERT INTO `xxl_job_info`(`id`, `job_group`, `job_desc`, `add_time`, `update_time`, `author`, `schedule_type`, `schedule_conf`, `misfire_strategy`, `executor_route_strategy`, `executor_handler`, `executor_block_strategy`, `glue_type`)
VALUES (1, 1, '示例任务', NOW(), NOW(), 'admin', 'CRON', '0 0 0 * * ? *', 'DO_NOTHING', 'FIRST', 'demoJobHandler', 'SERIAL_EXECUTION', 'BEAN');
-- 用户:admin / 123456
INSERT INTO `xxl_job_user`(`id`, `username`, `password`, `role`, `permission`)
VALUES (1, 'admin', 'e10adc3949ba59abbe56e057f20f883e', 1, NULL);
INSERT INTO `xxl_job_lock` (`lock_name`) VALUES ('schedule_lock');
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
# 4.4 启动服务
cd /home/xxl-job
docker compose up -d
1
2
2
# 4.5 查看服务状态
docker ps --filter name=xxl-job
1
输出示例:
NAMES STATUS PORTS
xxl-job-admin Up 30 seconds 0.0.0.0:9080->8080/tcp
xxl-job-mysql Up 31 seconds (healthy) 3306/tcp
1
2
3
2
3
# 4.6 查看启动日志
docker logs xxl-job-admin --tail 20
1
成功标志:
Started XxlJobAdminApplication in X.XXX seconds
init xxl-job admin scheduler success.
1
2
2
# 五、访问与配置
# 5.1 访问地址
启动成功后,访问:http://服务器IP:9080/xxl-job-admin/
# 5.2 默认账号
| 用户名 | 密码 |
|---|---|
| admin | 123456 |
⚠️ 安全建议:生产环境请立即修改默认密码!
# 5.3 反向代理配置(可选)
如需通过域名访问,可使用 Nginx 或 Caddy 配置反向代理:
Nginx 示例:
server {
listen 443 ssl;
server_name job.example.com;
location /xxl-job-admin/ {
proxy_pass http://127.0.0.1:9080/xxl-job-admin/;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
}
1
2
3
4
5
6
7
8
9
10
2
3
4
5
6
7
8
9
10
Caddy 示例:
job.example.com {
reverse_proxy 127.0.0.1:9080
}
1
2
3
2
3
# 六、常用命令
# 6.1 服务管理
# 启动服务
cd /home/xxl-job && docker compose up -d
# 停止服务
cd /home/xxl-job && docker compose down
# 重启服务
cd /home/xxl-job && docker compose restart
# 查看服务状态
docker compose -f /home/xxl-job/docker-compose.yml ps
# 查看日志
docker logs xxl-job-admin --tail 100 -f
docker logs xxl-job-mysql --tail 50
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# 6.2 数据库操作
# 连接 MySQL
docker exec -it xxl-job-mysql mysql -uxxljob -pxxljob2026secret xxl_job
# 修改密码(MD5 值)
docker exec xxl-job-mysql mysql -uxxljob -pxxljob2026secret xxl_job \
-e "UPDATE xxl_job_user SET password='新密码的MD5值' WHERE username='admin';"
# 常用密码 MD5 映射
# 123456 -> e10adc3949ba59abbe56e057f20f883e
# admin -> 21232f297a57a5a743894a0e4a801fc3
1
2
3
4
5
6
7
8
9
10
2
3
4
5
6
7
8
9
10
# 6.3 备份与恢复
# 备份数据库
docker exec xxl-job-mysql mysqldump -uxxljob -pxxljob2026secret xxl_job > xxl_job_backup_$(date +%Y%m%d).sql
# 恢复数据库
docker exec -i xxl-job-mysql mysql -uxxljob -pxxljob2026secret xxl_job < xxl_job_backup_20260615.sql
1
2
3
4
5
2
3
4
5
# 七、资源监控
# 7.1 查看资源占用
# 容器资源统计
docker stats xxl-job-admin xxl-job-mysql --no-stream
# 系统内存
free -h
1
2
3
4
5
2
3
4
5
# 7.2 预估资源消耗
| 组件 | 内存占用 | 说明 |
|---|---|---|
| xxl-job-admin | 300-400 MB | 调度中心 |
| xxl-job-mysql | 300-400 MB | 数据库 |
| 合计 | 600-800 MB |
# 八、常见问题
# 8.1 容器启动失败
排查步骤:
# 查看容器状态
docker ps -a --filter name=xxl-job
# 查看详细日志
docker logs xxl-job-admin --tail 100
docker logs xxl-job-mysql --tail 100
# 检查端口占用
netstat -tlnp | grep 9080
1
2
3
4
5
6
7
8
9
2
3
4
5
6
7
8
9
# 8.2 数据库连接失败
检查 MySQL 是否就绪:
docker exec xxl-job-mysql mysqladmin ping -h localhost
1
# 8.3 忘记密码
重置为 123456:
docker exec xxl-job-mysql mysql -uxxljob -pxxljob2026secret xxl_job \
-e "UPDATE xxl_job_user SET password='e10adc3949ba59abbe56e057f20f883e' WHERE username='admin';"
1
2
2
# 九、安全加固建议
- 修改默认密码:生产环境必须修改 admin 密码
- 修改数据库密码:更换
docker-compose.yml中的 MySQL 密码 - 配置 AccessToken:设置复杂的
xxl.job.accessToken - 网络隔离:生产环境建议 Admin 不暴露公网,仅内网访问
- 配置 HTTPS:使用反向代理配置 SSL 证书
# 十、参考链接
- XXL-JOB 官方文档 (opens new window)
- XXL-JOB GitHub (opens new window)
- Docker Hub - xxl-job-admin (opens new window)
最后更新:2026-06-15
上次更新: 2026/6/16 18:20:08