xxl-job源码改造集成:适配opengauss数据、适配单点登录等

news/2024/5/18 22:40:44 标签: xxl-job, springboot, postgresql 集成, 登录 集成

目录

一、摘要

二、集成方案

三、集成步骤

springboot%E9%9B%86%E6%88%90xxl-job-toc" style="margin-left:40px;">3.1 springboot集成xxl-job

3.2 适配高斯数据库(postgresql)

3.3 页面集成

3.4 登录集成

3.5 接口集成

四、部署


一、摘要

        公司现在打算重构产品,将原来的quartz替换成xxl-job,主要因为quartz不能动态发布任务,而xxl-job开箱即用,还支持一系列新特性,有 动态编写任务、调度中心和执行器高可用(可集群部署)、任务路由策略多样、 弹性扩容、失败重试 等。

二、集成方案

        xxl-job架构分为管理端(调度中心)和客户端(各应用执行器),由调度中心调用各执行器执行任务,而且它有自己的用户和角色以及页面,目前只有mysql初始化脚本。因此公司产品集成xxl-job,主要有以下几点需要集成:

        1、数据库集成:公司的产品是需要适配mysql和opengauss,因此xxl-job也需要适配opengauss,改造方案为:初始化脚本需要有opengauss版本的SQL、接口与后台任务运行的不兼容的SQL用改成兼容通用语法或修改逻辑用mybatis plus兼容,实在不行的则配置DatabaseIdProvider并用databaseId区分两种数据库的SQL,数据源配置统一改成公司的数据源配置。

        2、页面集成:由于xxl-job页面风格不一致、且页面不支持配置任务执行时间段,这里任务管理页面还是采用原公司任务管理页面,然后再开发个任务源码编辑查看页。任务管理页面的菜单和按钮权限还是和以前权限管理设置一样,不同的角色和用户设置不同的任务管理菜单和按钮。

        3、登录集成:由于公司有自己的单点登录,因此需要将xxl-job的鉴权适配,改造方案为:登录拦截器改造,接口request里若没有符合单点登录的token则跳转公司登录页,若有token则给用户赋管理员权限。

        4、接口集成:调用quartz的接口全部改成调用xxl-job,任务运行的注解也改成xxl-job的注解。

三、集成步骤

springboot%E9%9B%86%E6%88%90xxl-job">3.1 springboot集成xxl-job

         这里先确定xxl-job的版本,看xxl-job在gitee和github的代码,人们对2.3.1的版本提的问题较少,且2.3.1也能满足需求,新特性都支持,这里选择2.3.1版本,然后下载下来。

   

        下载后,得到源码如下:

 

         可以看到,这里有三个模块:xxl-job-admin(调度中心)、xxl-job-core(执行器需添加的依赖)、xxl-job-executor-samples(执行器示例)。

        初始化数据库的SQL也有,具体如下:

        找个mysql数据库运行下初始化脚本,然后改改xxl-job-admin里的配置(数据源、端口)再启动,访问管理页面,默认情况为 ip:8080/xxl-job-admin,首次登录会跳转登录页,用amdin/123456登录后可以看到类似如下首页:

         执行器可以参考 xxl-job-executor-sample-springboot的示例来配置。主要是加入xxl-job-core依赖,声明好 ip、port、appname以及admin.addresses。注意的是,执行器的appname一定要在admin的执行器管理里进行添加,执行器才能连上admin(这个类似于先在调度中心申请一个凭证appname,后续执行器用凭证appname连上admin)。具体如下:

         测试可行后,原定时任务在系统管理模块,因此,系统管理模块需加入xxl-job-core依赖并进行配置作为执行器、项目里需新建定时任务管理模块(存放xxl-job-admin代码)作为调度中心。

        具体目录结构如下:

3.2 适配高斯数据库(postgresql)

        由于高斯数据库完全支持postgresql语法,所以根据xxl-job的mysql表结构编写pg的SQL,具体如下:

CREATE TABLE xxl_job_info (
  id serial constraint xxl_job_info_pkey primary key,
  job_group integer NOT NULL,
  job_desc varchar(255) NOT NULL,
  add_time timestamp DEFAULT NULL,
  update_time timestamp DEFAULT NULL,
  author varchar(64) DEFAULT NULL ,
  alarm_email varchar(255) DEFAULT NULL ,
  schedule_type varchar(50) NOT NULL DEFAULT 'NONE' ,
  schedule_conf varchar(128) DEFAULT NULL,
  misfire_strategy varchar(50) NOT NULL DEFAULT 'DO_NOTHING' ,
  executor_route_strategy varchar(50) DEFAULT NULL ,
  executor_handler varchar(255) DEFAULT NULL ,
  executor_param varchar(512) DEFAULT NULL ,
  executor_block_strategy varchar(50) DEFAULT NULL ,
  executor_timeout integer NOT NULL DEFAULT '0',
  executor_fail_retry_count integer NOT NULL DEFAULT '0' ,
  glue_type varchar(50) NOT NULL ,
  glue_source text ,
  glue_remark varchar(128) DEFAULT NULL ,
  glue_updatetime timestamp DEFAULT NULL ,
  child_jobid varchar(255) DEFAULT NULL ,
  trigger_status smallint NOT NULL DEFAULT '0' ,
  trigger_last_time bigint NOT NULL DEFAULT '0' ,
  trigger_next_time bigint NOT NULL DEFAULT '0'
);

comment on table xxl_job_info is '任务信息表';
comment on column xxl_job_info.id  is '主键';
comment on column xxl_job_info.job_group  is '执行器主键ID';
comment on column xxl_job_info.job_desc  is '任务描述';
comment on column xxl_job_info.add_time  is '任务创建时间';
comment on column xxl_job_info.update_time  is '任务更新时间';
comment on column xxl_job_info.author  is '作者';
comment on column xxl_job_info.alarm_email  is '报警邮件';
comment on column xxl_job_info.schedule_type  is '调度类型';
comment on column xxl_job_info.schedule_conf  is '调度配置,值含义取决于调度类型';
comment on column xxl_job_info.misfire_strategy  is '调度过期策略';
comment on column xxl_job_info.executor_route_strategy  is '执行器路由策略';
comment on column xxl_job_info.executor_handler  is '执行器任务handler';
comment on column xxl_job_info.executor_param is '执行器任务参数';
comment on column xxl_job_info.executor_block_strategy  is '阻塞处理策略';
comment on column xxl_job_info.executor_timeout  is '任务执行超时时间,单位秒';
comment on column xxl_job_info.executor_fail_retry_count  is '失败重试次数';
comment on column xxl_job_info.glue_type  is 'GLUE类型';
comment on column xxl_job_info.glue_source  is 'GLUE源代码';
comment on column xxl_job_info.glue_remark  is 'GLUE备注';
comment on column xxl_job_info.glue_updatetime  is 'GLUE更新时间';
comment on column xxl_job_info.child_jobid  is '子任务ID,多个逗号分隔';
comment on column xxl_job_info.trigger_status  is '调度状态:0-停止,1-运行';
comment on column xxl_job_info.trigger_last_time  is '上次调度时间';
comment on column xxl_job_info.trigger_next_time  is '下次调度时间';


CREATE TABLE xxl_job_log (
  id serial constraint xxl_job_log_pkey primary key,
  job_group integer NOT NULL,
  job_id integer NOT NULL,
  executor_address varchar(255) DEFAULT NULL,
  executor_handler varchar(255) DEFAULT NULL,
  executor_param varchar(512) DEFAULT NULL,
  executor_sharding_param varchar(20) DEFAULT NULL ,
  executor_fail_retry_count integer NOT NULL DEFAULT '0',
  trigger_time timestamp DEFAULT NULL,
  trigger_code integer NOT NULL,
  trigger_msg text,
  handle_time timestamp DEFAULT NULL,
  handle_code integer NOT NULL,
  handle_msg text ,
  alarm_status smallint NOT NULL DEFAULT '0'
) ;

CREATE INDEX I_trigger_time ON xxl_job_log (trigger_time);
CREATE INDEX I_handle_code ON xxl_job_log (handle_code);
comment on table xxl_job_log is '任务日志表';
comment on column xxl_job_log.id  is '主键';
comment on column xxl_job_log.job_group  is '执行器主键ID';
comment on column xxl_job_log.job_id  is '任务,主键ID';
comment on column xxl_job_log.executor_address  is '执行器地址,本次执行的地址';
comment on column xxl_job_log.executor_handler  is '执行器任务handler';
comment on column xxl_job_log.executor_param  is '执行器任务参数';
comment on column xxl_job_log.executor_sharding_param  is '执行器任务分片参数,格式如 1/2';
comment on column xxl_job_log.executor_fail_retry_count  is '失败重试次数';
comment on column xxl_job_log.trigger_time  is '调度-时间';
comment on column xxl_job_log.trigger_code  is '调度-结果';
comment on column xxl_job_log.trigger_msg  is '调度-日志';
comment on column xxl_job_log.handle_time  is '执行-时间';
comment on column xxl_job_log.handle_code  is '执行-状态';
comment on column xxl_job_log.handle_msg  is '执行-日志';
comment on column xxl_job_log.alarm_status  is '告警状态:0-默认、1-无需告警、2-告警成功、3-告警失败';


create or replace function upd_timestamp() returns trigger as
$$
begin
    new.update_time = current_timestamp;
    return new;
end
$$
    language plpgsql;


CREATE TABLE xxl_job_log_report (
  id serial constraint xxl_job_log_report_pkey primary key,
  trigger_day timestamp DEFAULT NULL,
  running_count integer NOT NULL DEFAULT '0',
  suc_count integer NOT NULL DEFAULT '0',
  fail_count integer NOT NULL DEFAULT '0',
  update_time timestamp DEFAULT NULL
);

CREATE UNIQUE INDEX i_trigger_day ON xxl_job_log_report (trigger_day);
comment on column  xxl_job_log_report.id  is '主键';
comment on column  xxl_job_log_report.trigger_day  is '调度-时间';
comment on column  xxl_job_log_report.running_count  is '运行中-日志数量';
comment on column  xxl_job_log_report.suc_count  is '执行成功-日志数量';
comment on column  xxl_job_log_report.fail_count  is '执行失败-日志数量';
comment on column  xxl_job_log_report.update_time  is '更新时间';


CREATE TABLE xxl_job_logglue (
  id serial constraint xxl_job_logglue_pkey primary key,
  job_id integer NOT NULL,
  glue_type varchar(50) DEFAULT NULL,
  glue_source text,
  glue_remark varchar(128) NOT NULL,
  add_time timestamp DEFAULT NULL,
  update_time timestamp DEFAULT NULL
);

create trigger t_xxl_job_logglue_update_time before update on xxl_job_logglue for each row execute procedure upd_timestamp();
comment on table xxl_job_logglue is '任务GLUE日志表';
comment on column xxl_job_logglue.id  is '主键';
comment on column xxl_job_logglue.job_id  is '任务,主键ID';
comment on column xxl_job_logglue.glue_type  is 'GLUE类型';
comment on column xxl_job_logglue.glue_source  is 'GLUE源代码';
comment on column xxl_job_logglue.glue_remark  is 'GLUE备注';
comment on column xxl_job_logglue.add_time  is '创建时间';
comment on column xxl_job_logglue.update_time  is '修改时间';

CREATE TABLE xxl_job_registry (
  id serial constraint xxl_job_registry_pkey primary key,
  registry_group varchar(50) NOT NULL,
  registry_key varchar(255) NOT NULL,
  registry_value varchar(255) NOT NULL,
  update_time timestamp DEFAULT NULL
);
CREATE INDEX i_g_k_v ON xxl_job_registry (registry_group,registry_key,registry_value);
comment on table xxl_job_registry is '任务注册表';
comment on column xxl_job_registry.id  is '主键';
comment on column xxl_job_registry.registry_group  is '注册分组';
comment on column xxl_job_registry.registry_key  is '注册键';
comment on column xxl_job_registry.registry_value  is '注册值';
comment on column xxl_job_registry.update_time  is '更新时间';


CREATE TABLE xxl_job_group (
  id serial constraint xxl_job_group_pkey primary key,
  app_name varchar(64) NOT NULL,
  title varchar(12) NOT NULL,
  address_type smallint NOT NULL DEFAULT '0',
  address_list text ,
  update_time timestamp DEFAULT NULL
);

comment on table xxl_job_group is '任务分组表';
comment on column xxl_job_group.id  is '主键';
comment on column xxl_job_group.app_name  is '执行器AppName';
comment on column xxl_job_group.title  is '执行器名称';
comment on column xxl_job_group.address_type  is '执行器地址类型:0=自动注册、1=手动录入';
comment on column xxl_job_group.address_list  is '执行器地址列表,多地址逗号分隔';


CREATE TABLE xxl_job_user (
  id serial constraint xxl_job_user_pkey primary key,
  username varchar(50) NOT NULL,
  password varchar(50) NOT NULL,
  role smallint NOT NULL,
  permission varchar(255) DEFAULT NULL
) ;


CREATE UNIQUE INDEX i_username ON xxl_job_user (username);
comment on table xxl_job_user is '任务用户表';
comment on column xxl_job_user.id  is '主键';
comment on column xxl_job_user.username  is '账号';
comment on column xxl_job_user.password  is '密码';
comment on column xxl_job_user.role  is '角色:0-普通用户、1-管理员';
comment on column xxl_job_user.permission  is '权限:执行器ID列表,多个逗号分割';


CREATE TABLE xxl_job_lock (
  lock_name varchar(50) NOT NULL,
  PRIMARY KEY (lock_name)
);

comment on table xxl_job_lock is '任务锁表';
comment on column xxl_job_lock.lock_name  is '锁名称';

INSERT INTO xxl_job_group( app_name, title, address_type, address_list, update_time) VALUES ('xxl-job-executor-sample', '示例执行器', 0, NULL, '2018-11-03 22:21:31' );
INSERT INTO xxl_job_info( 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', '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( username, password, role, permission) VALUES ( 'admin', 'e10adc3949ba59abbe56e057f20f883e', 1, NULL);
INSERT INTO xxl_job_lock ( lock_name) VALUES ( 'schedule_lock');

        接着xml文件里将“`”去除,具体如下:

        调整findDead逻辑,原SQL(<![CDATA[ < ]]> DATE_ADD(#{nowTime},INTERVAL -#{timeout} SECOND))不兼容pg语法, 如下:

        这句SQL是找出更新时间小于(当前时间-配置的超时时间)的注册组,查了下网上写法,都不怎么好,这里改用集成mybatis plus,用mybatis plus来进行查询。具体如下:

        另外,使用了mybatis plus,有些表会发生主键插入异常,具体解决办法如下:

        调整不等于判断,具体如下:

         将驼峰改成小写适配高斯数据库

         基本就以上这些了,连接pg数据库也能正常运行admin并新增执行器和任务运行,并能看到日志以及统计。

3.3 页面集成

        页面集成意味着客户无法看到admin管理页,只能看到原来的任务页,原页面如下:

        目前页面保持不变,页面的对应的菜单和按钮权限都不变,接口的url以及参数和返回值都不变,xxl-job-admin的管理页对用户不可见,我这里修改路径和端口,并不暴露给前端和nginx。由于管理页不可见,需要把新增执行器appname的sql写在初始化SQL里。

3.4 登录集成

        这里调整拦截器PermissionInterceptor和toLogin处理即可。具体如下:

         这里PermissionInterceptor拦截器去除needAdminUser判断,直接从request里获取token,获取不到或根据token查不到登录用户信息,则跳转toLogin,若能获取到用户登录信息,则给用户赋值xxl-job的管理员权限并保存到request的属性中即可。

         这里toLogin处理直接重定向公司的单点登录地址即可。

3.5 接口集成

        这里系统管理模块里原来任务controller保持不变,服务层原来调用quartz的逻辑全部换成xxl-job。具体如下:

         系统管理模块(执行器)保存时调用feign接口,进而调用xxl-job-admin的新增方法。这里通过任务参数关联系统管理的任务,后续执行器执行任务时,可以通过任务参数找到添加的任务配置,进而进行相应处理。任务注解就简单了,换用@XxlJob注解即可。剩下的任务业务逻辑各自按业务进行调整。

四、部署

        这里考虑高可用,所以系统管理模块(执行器)和任务管理模块(调度中心xxl-job-admin)都是集群部署。这里部署需要注意,所有机器的时间必须保持一致。调度中心连接同一个数据库多实例启动即可,执行器配在admin.address配置各调度中心的地址后多实例启动即可。

      


 


http://www.niftyadmin.cn/n/1009894.html

相关文章

C#异常总结

C#异常总结 定义Try语句异常类创建用户自定义异常搜索调用栈的示例异常抛出 定义 程序中的运行时错误&#xff0c;它违反一个系统约束或应用程序约束&#xff0c;或出现了在正常操作时未预料的情形。 Try语句 指明被异常保护的代码块&#xff0c;并提供代码以处理异常。try由…

分享一些关于 CSS Grid 基础入门知识

网格系统&#xff08;CSS Grid&#xff09;是CSS中最重要的特性之一。它能够以简单的方式将元素对齐到列和行中。CSS网格使得设计复杂且响应式的网页变得更加容易&#xff0c;无需使用浮动、表格或定位。它还具有许多更强大的功能&#xff0c;如果你多加练习&#xff0c;就能发…

Autosar MCAL-S32K324 MCU配置-基于EB

文章目录 McuGeneralConfigurationDefault Error DetectVersion Info APIMcu Get Ram State APIMcu Init Clock APIMcu No PLLMcu Enter Low-Power ModeMcu Loops TimeOut (1 -> 4294967295)Mcu Enable User Mode SupportMcu Perform Reset APIMcuCalloutBeforePerformReset…

十五、docker学习-docker核心docker数据卷

什么是数据卷 当我们在使用docker容器的时候&#xff0c;会产生一系列的数据文件&#xff0c;这些数据文件在我们删除docker容器时是会消失的&#xff0c;但是其中产生的部分内容我们是希望能够把它给保存起来另作用途的&#xff0c;Docker将应用与运行环境打包成容器发布&…

python接口自动化(八)--发送post请求的接口(详解)

简介 上篇介绍完发送get请求的接口&#xff0c;大家必然联想到发送post请求的接口也不会太难&#xff0c;被聪明的你又猜到了。答案是对的&#xff0c;虽然发送post请求的参考例子很简单&#xff0c;但是实际遇到的情况却是很复杂的&#xff0c;因为所有系统或者软件、网站都是…

06_Vue-router与综合练习

Vue-router 一.生命周期钩子函数 含义:在生命周期处理响应函数的别称 1.初始化 beforeCreat:创建对象时,没初始化data和methods created:实例已经创建好了,此时在里面发送ajax请求 2.挂载 beforeMount:还没与挂载到页面中 munted:模块已经挂载好了 3.更新 beforeUpda…

Java版企业工程项目管理系统源码-全面的工程项目管理+spring cloud

​ ​工程项目管理系统是指从事工程项目管理的企业&#xff08;以下简称工程项目管理企业&#xff09;受业主委托&#xff0c;按照合同约定&#xff0c;代表业主对工程项目的组织实施进行全过程或若干阶段的管理和服务。 如今建筑行业竞争激烈&#xff0c;内卷严重&#xff0c…

SpringBoot(五)SpringBoot事务

在实际开发项目时&#xff0c;程序并不是总会按照正常的流程去执行&#xff0c;有时候线上可能出现一些无法预知的问题&#xff0c;任何一步操作都有可能发生异常&#xff0c;异常则会导致后续的操作无法完成。此时由于业务逻辑并未正确的完成&#xff0c;所以在之前操作过数据…