From 1394a9fdb8200619eafff9d7223baaf993ef83cc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=B0=8F=E5=82=85=E5=93=A5?= <184172133@qq.com> Date: Sat, 4 Nov 2023 12:31:15 +0800 Subject: [PATCH] =?UTF-8?q?=E5=B0=8F=E5=82=85=E5=93=A5=EF=BC=8Cfeat?= =?UTF-8?q?=EF=BC=9Axxl-job=20=E5=88=86=E5=B8=83=E5=BC=8F=E4=BB=BB?= =?UTF-8?q?=E5=8A=A1=E8=B0=83=E5=BA=A6=E7=BB=84=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/dev-ops/environment/docker-compose.yml | 27 +++- docs/dev-ops/environment/sql/xxl_job.sql | 121 ++++++++++++++++++ pom.xml | 5 + xfg-frame-archetype-std-app/pom.xml | 4 + .../cn/bugstack/config/XxlJobAutoConfig.java | 71 ++++++++++ .../src/main/resources/application-dev.yml | 22 ++++ xfg-frame-archetype-std-trigger/pom.xml | 6 +- .../java/cn/bugstack/trigger/job/XXLJob.java | 20 +++ 8 files changed, 274 insertions(+), 2 deletions(-) create mode 100644 docs/dev-ops/environment/sql/xxl_job.sql create mode 100644 xfg-frame-archetype-std-app/src/main/java/cn/bugstack/config/XxlJobAutoConfig.java create mode 100644 xfg-frame-archetype-std-trigger/src/main/java/cn/bugstack/trigger/job/XXLJob.java diff --git a/docs/dev-ops/environment/docker-compose.yml b/docs/dev-ops/environment/docker-compose.yml index 816f0fe..2dd8372 100644 --- a/docs/dev-ops/environment/docker-compose.yml +++ b/docs/dev-ops/environment/docker-compose.yml @@ -28,7 +28,32 @@ services: depends_on: mysql: condition: service_healthy - # MySQL + + # http://127.0.0.1:9090/xxl-job-admin admin/123456 - 安装后稍等会访问即可 + # 官网镜像为 xuxueli/xxl-job-admin:2.4.0 但不支持ARM架构【需要自己打包】,所以找了一个 kuschzzp/xxl-job-aarch64:2.4.0 镜像支持 AMD/ARM + xxl-job-admin: + image: xuxueli/xxl-job-admin:2.4.0 + container_name: xxl-job-admin + restart: always + depends_on: + mysql: + condition: service_healthy + ports: + - "9090:9090" + links: + - mysql + volumes: + - ./data/logs:/data/applogs + - ./data/xxl-job/:/xxl-job + environment: + - SPRING_DATASOURCE_URL=jdbc:mysql://mysql:3306/xxl_job?serverTimezone=UTC&characterEncoding=utf8&autoReconnect=true&serverTimezone=Asia/Shanghai + - SPRING_DATASOURCE_USERNAME=root + - SPRING_DATASOURCE_PASSWORD=123456 + - SERVER_PORT=9090 + networks: + - my-network + + # MySQL 增加健康检测,避免 mysql: image: mysql:8.0.32 container_name: mysql diff --git a/docs/dev-ops/environment/sql/xxl_job.sql b/docs/dev-ops/environment/sql/xxl_job.sql new file mode 100644 index 0000000..a2cc4c2 --- /dev/null +++ b/docs/dev-ops/environment/sql/xxl_job.sql @@ -0,0 +1,121 @@ +# 获取地址:https://github.com/xuxueli/xxl-job/tree/master/doc/db +# XXL-JOB v2.4.1-SNAPSHOT +# Copyright (c) 2015-present, xuxueli. + +CREATE database if NOT EXISTS `xxl_job` default character set utf8mb4 collate utf8mb4_0900_ai_ci; +use `xxl_job`; + +SET NAMES utf8mb4; + +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`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; + +CREATE TABLE `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 '执行器任务分片参数,格式如 1/2', + `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 '告警状态:0-默认、1-无需告警、2-告警成功、3-告警失败', + PRIMARY KEY (`id`), + KEY `I_trigger_time` (`trigger_time`), + KEY `I_handle_code` (`handle_code`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; + +CREATE TABLE `xxl_job_log_report` ( + `id` int(11) NOT NULL AUTO_INCREMENT, + `trigger_day` datetime DEFAULT NULL COMMENT '调度-时间', + `running_count` int(11) NOT NULL DEFAULT '0' COMMENT '运行中-日志数量', + `suc_count` int(11) NOT NULL DEFAULT '0' COMMENT '执行成功-日志数量', + `fail_count` int(11) NOT NULL DEFAULT '0' COMMENT '执行失败-日志数量', + `update_time` datetime DEFAULT NULL, + PRIMARY KEY (`id`), + UNIQUE KEY `i_trigger_day` (`trigger_day`) USING BTREE +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; + +CREATE TABLE `xxl_job_logglue` ( + `id` int(11) NOT NULL AUTO_INCREMENT, + `job_id` int(11) NOT NULL COMMENT '任务,主键ID', + `glue_type` varchar(50) DEFAULT NULL COMMENT 'GLUE类型', + `glue_source` mediumtext COMMENT 'GLUE源代码', + `glue_remark` varchar(128) NOT NULL COMMENT 'GLUE备注', + `add_time` datetime DEFAULT NULL, + `update_time` datetime DEFAULT NULL, + PRIMARY KEY (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; + +CREATE TABLE `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 `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 `xxl_job_user` ( + `id` int(11) NOT NULL AUTO_INCREMENT, + `username` varchar(50) NOT NULL COMMENT '账号', + `password` varchar(50) NOT NULL COMMENT '密码', + `role` tinyint(4) NOT NULL COMMENT '角色:0-普通用户、1-管理员', + `permission` varchar(255) DEFAULT NULL COMMENT '权限:执行器ID列表,多个逗号分割', + PRIMARY KEY (`id`), + UNIQUE KEY `i_username` (`username`) USING BTREE +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; + +CREATE TABLE `xxl_job_lock` ( + `lock_name` varchar(50) NOT NULL COMMENT '锁名称', + 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, '2018-11-03 22:21:31' ); +INSERT INTO `xxl_job_info`(`id`, `job_group`, `job_desc`, `add_time`, `update_time`, `author`, `alarm_email`, `schedule_type`, `schedule_conf`, `misfire_strategy`, `executor_route_strategy`, `executor_handler`, `executor_param`, `executor_block_strategy`, `executor_timeout`, `executor_fail_retry_count`, `glue_type`, `glue_source`, `glue_remark`, `glue_updatetime`, `child_jobid`) VALUES (1, 1, '测试任务1', '2018-11-03 22:21:31', '2018-11-03 22:21:31', 'XXL', '', 'CRON', '0 0 0 * * ? *', 'DO_NOTHING', 'FIRST', 'demoJobHandler', '', 'SERIAL_EXECUTION', 0, 0, 'BEAN', '', 'GLUE代码初始化', '2018-11-03 22:21:31', ''); +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'); + +commit; \ No newline at end of file diff --git a/pom.xml b/pom.xml index 9707eee..7301d74 100644 --- a/pom.xml +++ b/pom.xml @@ -131,6 +131,11 @@ snakeyaml 1.33 + + com.xuxueli + xxl-job-core + 2.4.0 + diff --git a/xfg-frame-archetype-std-app/pom.xml b/xfg-frame-archetype-std-app/pom.xml index 4cf6c37..2932a86 100644 --- a/xfg-frame-archetype-std-app/pom.xml +++ b/xfg-frame-archetype-std-app/pom.xml @@ -102,6 +102,10 @@ org.yaml snakeyaml + + com.xuxueli + xxl-job-core + diff --git a/xfg-frame-archetype-std-app/src/main/java/cn/bugstack/config/XxlJobAutoConfig.java b/xfg-frame-archetype-std-app/src/main/java/cn/bugstack/config/XxlJobAutoConfig.java new file mode 100644 index 0000000..88d24c1 --- /dev/null +++ b/xfg-frame-archetype-std-app/src/main/java/cn/bugstack/config/XxlJobAutoConfig.java @@ -0,0 +1,71 @@ +package cn.bugstack.config; + +import com.xxl.job.core.executor.impl.XxlJobSpringExecutor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +@Slf4j +@Configuration +public class XxlJobAutoConfig { + + @Value("${xxl.job.admin.addresses}") + private String adminAddresses; + + @Value("${xxl.job.accessToken}") + private String accessToken; + + @Value("${xxl.job.executor.appname}") + private String appname; + + @Value("${xxl.job.executor.address}") + private String address; + + @Value("${xxl.job.executor.ip}") + private String ip; + + @Value("${xxl.job.executor.port}") + private int port; + + @Value("${xxl.job.executor.logpath}") + private String logPath; + + @Value("${xxl.job.executor.logretentiondays}") + private int logRetentionDays; + + @Bean + public XxlJobSpringExecutor xxlJobExecutor() { + log.info(">>>>>>>>>>> xxl-job config init."); + + XxlJobSpringExecutor xxlJobSpringExecutor = new XxlJobSpringExecutor(); + xxlJobSpringExecutor.setAdminAddresses(adminAddresses); + xxlJobSpringExecutor.setAppname(appname); + xxlJobSpringExecutor.setAddress(address); + xxlJobSpringExecutor.setIp(ip); + xxlJobSpringExecutor.setPort(port); + xxlJobSpringExecutor.setAccessToken(accessToken); + xxlJobSpringExecutor.setLogPath(logPath); + xxlJobSpringExecutor.setLogRetentionDays(logRetentionDays); + + return xxlJobSpringExecutor; + } + + /********************************************************************************************** + * 针对多网卡、容器内部署等情况,可借助 "spring-cloud-commons" 提供的 "InetUtils" 组件灵活定制注册IP; + * + * 1、引入依赖: + * + * org.springframework.cloud + * spring-cloud-commons + * ${version} + * + * + * 2、配置文件,或者容器启动变量 + * spring.cloud.inetutils.preferred-networks: 'xxx.xxx.xxx.' + * + * 3、获取IP + * String ip_ = inetUtils.findFirstNonLoopbackHostInfo().getIpAddress(); + **********************************************************************************************/ + +} diff --git a/xfg-frame-archetype-std-app/src/main/resources/application-dev.yml b/xfg-frame-archetype-std-app/src/main/resources/application-dev.yml index 38f3d51..95db537 100644 --- a/xfg-frame-archetype-std-app/src/main/resources/application-dev.yml +++ b/xfg-frame-archetype-std-app/src/main/resources/application-dev.yml @@ -52,6 +52,28 @@ dubbo: scan: base-packages: cn.bugstack.api +# xxl-job https://www.xuxueli.com/xxl-job/#%E6%AD%A5%E9%AA%A4%E4%B8%80%EF%BC%9A%E8%B0%83%E5%BA%A6%E4%B8%AD%E5%BF%83%E9%85%8D%E7%BD%AE%EF%BC%9A +xxl: + job: + # 验证信息 官网Bug https://github.com/xuxueli/xxl-job/issues/1951 + accessToken: default_token + # 注册地址 + admin: + addresses: http://localhost:9090/xxl-job-admin + # 注册执行器 + executor: + # 执行器注册 [选填]:优先使用该配置作为注册地址,为空时使用内嵌服务 ”IP:PORT“ 作为注册地址。从而更灵活的支持容器类型执行器动态IP和动态映射端口问题。 + address: + appname: xxl-job-executor-sample + # 执行器IP 配置为本机IP [选填]:默认为空表示自动获取IP,多网卡时可手动设置指定IP,该IP不会绑定Host仅作为通讯实用;地址信息用于 "执行器注册" 和 "调度中心请求并触发任务"; + ip: + # 执行器端口号 [选填]:小于等于0则自动获取;默认端口为9999,单机部署多个执行器时,注意要配置不同执行器端口; + port: 9999 + # 执行器运行日志文件存储磁盘路径 [选填] :需要对该路径拥有读写权限;为空则使用默认路径; + logpath: ./data/applogs/xxl-job/jobhandler + # 执行器日志文件保存天数 [选填] : 过期日志自动清理, 限制值大于等于3时生效; 否则, 如-1, 关闭自动清理功能; + logretentiondays: 30 + # 日志 logging: level: diff --git a/xfg-frame-archetype-std-trigger/pom.xml b/xfg-frame-archetype-std-trigger/pom.xml index 4db8b62..58ae619 100644 --- a/xfg-frame-archetype-std-trigger/pom.xml +++ b/xfg-frame-archetype-std-trigger/pom.xml @@ -26,7 +26,6 @@ org.apache.commons commons-lang3 - org.apache.dubbo dubbo @@ -35,6 +34,11 @@ org.apache.dubbo dubbo-spring-boot-starter + + com.xuxueli + xxl-job-core + + diff --git a/xfg-frame-archetype-std-trigger/src/main/java/cn/bugstack/trigger/job/XXLJob.java b/xfg-frame-archetype-std-trigger/src/main/java/cn/bugstack/trigger/job/XXLJob.java new file mode 100644 index 0000000..1559fef --- /dev/null +++ b/xfg-frame-archetype-std-trigger/src/main/java/cn/bugstack/trigger/job/XXLJob.java @@ -0,0 +1,20 @@ +package cn.bugstack.trigger.job; + +import com.xxl.job.core.handler.annotation.XxlJob; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Component; + +/** + * XXL-Job + */ +@Slf4j +@Component +public class XXLJob { + + @XxlJob("demoJobHandler") + public void doJob() { + // 可以在任务中,调用一些业务方法逻辑的实现,如定时扫描超时未支付订单为关单处理,恢复库存 + log.info("执行任务 - XXL-Job - 01"); + } + +} -- GitLab