任务调度中心实现(二)节点竞争拉取任务的方式

流程图:

任务调度工作流程图

  

1、任务详情表、任务计划表、任务计划表、任务执行记录表设计。

任务情况表 折叠原码

DROP TABLE IF EXISTS `APP_TASK_DESC`;

CREATE TABLE `APP_TASK_DESC` (

  `id` bigint(10) NOT NULL AUTO_INCREMENT COMMENT 'id',

  `schedule_type` varchar(20) NOT NULL COMMENT 'cron、simple两种模式',

  `task_name` varchar(50) NOT NULL COMMENT '应用任务名称',

  `task_type` varchar(200) NOT NULL COMMENT '任务类型,比如归档任务为DATAFILER',

  `is_deleted` TINYINT(3) NOT NULL COMMENT '删除标识,有效:0,已删除:1',

  `status`  TINYINT(3) NOT NULL COMMENT '启停标识 启动:0,停止:1',

  `param_json` VARCHAR(500) COMMENT '不同任务需要的参数json,如数据归档需要制定数据表id',

  `task_json` VARCHAR(500) COMMENT 'task_type为DAG时需要任务list的json,根据顺序依次执行',

  `modified_user_id` bigint(20) unsigned NOT NULL COMMENT '修改用户ID',

  `modified_time` datetime(6) NOT NULL COMMENT '修改时间',

  `creation_user_id` bigint(20) unsigned NOT NULL COMMENT '创建用户ID',

  `creation_time` datetime(6) NOT NULL COMMENT '创建时间',

  PRIMARY KEY (`id`)

) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

任务计划表 折叠原码

DROP TABLE IF EXISTS `TASK_PLAN`;

CREATE TABLE `TASK_PLAN` (

  `id` bigint(10) NOT NULL AUTO_INCREMENT COMMENT 'id',

  `task_id` varchar(20) NOT NULL COMMENT 'cron、simple两种模式',

  `task_name` varchar(50) NOT NULL COMMENT '应用任务名称',

  `task_type` varchar(200) NOT NULL COMMENT '任务类型,比如归档任务为DATAFILER',

  `next_time` datetime(6) NOT NULL COMMENT '下次执行时间',

  `modified_user_id` bigint(20) unsigned NOT NULL COMMENT '修改用户ID',

  `modified_time` datetime(6) NOT NULL COMMENT '修改时间',

  `creation_user_id` bigint(20) unsigned NOT NULL COMMENT '创建用户ID',

  `creation_time` datetime(6) NOT NULL COMMENT '创建时间',

  PRIMARY KEY (`id`)

) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

任务执行记录表 折叠原码

DROP TABLE IF EXISTS `TASK_LOG`;

CREATE TABLE `TASK_LOG` (

  `id` bigint(10) NOT NULL AUTO_INCREMENT COMMENT 'id',

  `task_id` bigint(10) NOT NULL COMMENT 'task id',

  `task_name` varchar(50) NOT NULL COMMENT '应用任务名称',

  `task_type` varchar(200) NOT NULL COMMENT '任务类型,比如归档任务为DATAFILER',

  `start_time` DATETIME NOT NULL COMMENT '任务开始时间',

  `end_time` DATETIME NOT NULL COMMENT '任务结束时间',

  `execute_status` INT COMMENT '执行状态:成功、异常',

  `execute_message` VARCHAR(500) COMMENT '异常信息',

  `ip` VARCHAR(20) NOT NULL COMMENT '执行任务的ip',

  `result_json` VARCHAR(20) NOT NULL COMMENT '任务执行结果的重要信息比如归档路径等',

  `modified_user_id` bigint(20) unsigned NOT NULL COMMENT '修改用户ID',

  `modified_time` datetime(6) NOT NULL COMMENT '修改时间',

  `creation_user_id` bigint(20) unsigned NOT NULL COMMENT '创建用户ID',

  `creation_time` datetime(6) NOT NULL COMMENT '创建时间',

  PRIMARY KEY (`id`)

) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

失败待重试任务表 折叠原码

DROP TABLE IF EXISTS `ERROR_TASK_DESC`;

CREATE TABLE `ERROR_TASK_DESC` (

  `id` bigint(10) NOT NULL AUTO_INCREMENT COMMENT 'id',

  `task_id` bigint(10) NOT NULL AUTO_INCREMENT COMMENT '原任务id',

  `schedule_type` varchar(20) NOT NULL COMMENT 'cron、simple两种模式',

  `task_type` varchar(200) NOT NULL COMMENT '任务类型,比如归档任务为DATAFILER',

  `error_param_json` VARCHAR(500) COMMENT '不同任务需要的参数json,如数据归档需要制定数据表id',

  `modified_user_id` bigint(20) unsigned NOT NULL COMMENT '修改用户ID',

  `modified_time` datetime(6) NOT NULL COMMENT '修改时间',

  `creation_user_id` bigint(20) unsigned NOT NULL COMMENT '创建用户ID',

  `creation_time` datetime(6) NOT NULL COMMENT '创建时间',

`next_time` datetime(6) NOT NULL COMMENT '下次执行时间',

 `repeat_count` INT NOT NULL COMMENT '重复次数',

  PRIMARY KEY (`id`)

) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

 

2、参数介绍。

1)、task_type.任务类型。对于开发好的不同后端逻辑的任务。比如:任务归档的任务类型为DATAFILER.task_type要与对应job的实现对应。

TaskType示例 折叠原码

/**

 *

 * @author back

 *

 */

public enum TaskType {

 

    DATAFILER(DataFilerJob.class);

    Class<? extends AbstractJob> jobClass;

    int nodeUse;

    TaskType(Class<? extends AbstractJob> jobClass){

        this.jobClass = jobClass;

    }

    public Class<? extends AbstractJob> getJobClass() {

        return jobClass;

    }

}

上面的TaskType中用到了自定义Job。Job初步设计如下:

AbstractJob 折叠原码

package com.back.task;

 

import com.back.model.AppTask;

import com.back.model.TaskLog;

 

/**

 * 这里思考对于任务记录操作能否统一处理

 * 如果能够统一处理,代表也可以在这里加控制。做一个是否持久化任务痕迹的配置

 * @author Administrator

 *

 */

public abstract class AbstractJob implements Job<TaskLog> {

 

    private AppTask task;

    private TaskLog log;

     

    public AbstractJob(AppTask task){

        this.task = task;

    }

    /**

     * 对于call内部逻辑中的异常 ,自定义一个异常,单独记录一个message

     * 在这里的catch后 拿到message 后在after()逻辑中落库

     * 这里是为了完成比如归档任务中任务分为两个(或多个)阶段,message可以帮助我们记录哪些阶段成功,在哪个阶段失败。

     */

    @Override

    public TaskLog execute() {

        before();

        try{

            call();

        }catch(Exception e){

             

        }

        after();

        return log;

    }

 

    //前置逻辑

    private void before() {

         

    }

 

    public abstract void call();

 

    //这里完成任务记录落库逻辑

    private void after() {

         

    }

}


2)、schedule_type调度类型。暂时支持SIMPLE、CRON两种。SIMPLE是每隔多长时间触发一次的(可指定开始何时触发)。CRON是填写CRON表达式触发。

    3)、参数param_json。当schedule_type为SIMPLE时paramJson中存在interval(代表执行周期)和timeunit(代表时间单位:day、hour、minute、second) CRON是填写CRON表达式触发,需要参数cronExpression。

不同任务需要的差异化参数都存在这个json中。

3、集群下任务执行设计。

1)每个节点的线程通过update的原子性进行任务竞争,可通过配置修改每次竞争得到的任务数量。

 

任务竞争线程实现思路 折叠原码

/**

 * 利用Mysql Update来竞争改变competeStatus的状态和node_id

 * @author back

 *

 */

public class TaskCompeteHandler extends Thread{

 

    public static AtomicBoolean status = new AtomicBoolean(true);

    private static final long TASK_COMPETE_INTERVAL = 500;

    long startMills = System.currentTimeMillis();

    private static final String DEFAULT_THREAD_NAME = "TaskCompeteHandler";

    @Override

    public void run() {

        Thread.currentThread().setName(DEFAULT_THREAD_NAME);

        while(status.get() && !Thread.currentThread().isInterrupted()) {

            if(System.currentTimeMillis() - startMills >= TASK_COMPETE_INTERVAL){

                updateTask();

                startMills = System.currentTimeMillis();

            }  

             

        }

    }

     

    /**

     * 从mysql update 查询任务状态为开启的、当前时间大于或等于任务中下一次执行时间 的、task_type属于当前节点用途的、compete_status = 1任务 。

     * 将node_id=ignite.localNode.id和compete_status = 0 写入

     * 这里后面考虑update时每次udpate固定条数 where id in (select ..... order by next_time desc limit 10)

     */

    private void updateTask(){

         

        Date current = new Date();

        String currentId = ConfigUtils.ignite.cluster().localNode().id().toString();

        /**

         * update application_task set compete_status = 0 , node_id = currentId where

         * is_deleted = 0 and status = 0 and compete_status = 1 and next_time <= current

         *

         */

    }

}

2)任务拉取线程。

任务拉取线程实现思路 折叠原码

public class ExecuteTaskHandler extends Thread{

 

    public static AtomicBoolean status = new AtomicBoolean(true);

    private static final long PULL_TASK_INTERVAL = 500;

    long startMills = System.currentTimeMillis();

    private static final String DEFAULT_THREAD_NAME = "PullTaskHandler";

    IgniteComputeManager manager;

    public ExecuteTaskHandler(){

        manager = CommonUtils.getInstance(IgniteComputeManager.class);

    }

    @Override

    public void run() {

        Thread.currentThread().setName(DEFAULT_THREAD_NAME);

        while(status.get() && !Thread.currentThread().isInterrupted()) {

            if(System.currentTimeMillis() - startMills >= PULL_TASK_INTERVAL){

                sendTask();

                startMills = System.currentTimeMillis();

            }  

             

        }

    }

    private void sendTask() {

        Date currentDate = new Date();

        String currentId = ConfigUtils.ignite.cluster().localNode().id().toString();

        /**

         * select * from application_task where is_deleted = 0 and status = 0 and

         * next_time <= currentDate and node_id = currentId

         */

         

        List<AppTask>  tasks = null;

        for (AppTask task : tasks) {

            //1、sendTask 至本地线程池

             

            //2、下次执行时间

            task.setNextTime(TaskDateUtils.getNextDate(task, task.getNextTime()));

            //恢复竞争标识

            task.setCompeteStatus(1);

            //这个操作可以不做,因为通过竞争标识已经可以控制

            task.setNodeId(null);

        }

        //batchUpdate

    }

}

 

3)节点退出集群时,将退出节点id对应的任务(竞争状态为可执行的任务)恢复竞争状态

4)存在任务维护线程。定期检查是否存在到达执行时间但是长时间未执行任务,恢复竞争状态,从新竞争执行任务。

 

4、增删改查、启停任务。

1)

 任务新增:在Mysql中新增一条app_task_desc记录,前段有可能指定时间,则next_time为指定时间,若没有指定时间当前时间写入next_time。同时任务计划表新增竞争转状态为待竞争的任务。

  任务修改:mysql修改对应属性即可,其中next_time改为当前时间写入库中。

 任务的启停在任务表中修改状态即可。

2)项目启动。在master节点调度未删除且状态为有效的任务

5、对于脚本任务等部分节点才能生效的任务。

1)配置文件中配置节点用途。schedule.node.use = “DATAFILER,.....”  。既可以得到在这个节点不能执行的taskType 拉取任务时放入查询条件中。

 

6、应用任务的基础功能

1)在web提供手动触发任务。请求被分到哪个节点就在哪个节点上执行即可。

2)开发一个新类型任务的步骤。

1、继承AbstractJob ,实现自己的逻辑。

2、TaskType新增枚举,并建立与自定义Job的联系

1、统一监管报送平台功能介绍 1.1 背景分析 随着中国经济的飞速发展,近年来中国的金融行业也处在飞速的发展阶段, 银行的改制、分支机构的扩张、异地分行的开设、村镇银行的兴起、财务公司的 成立等,均可以看出中国的金融行业的发展已经进入到了前所未有的阶段。然而 随着金融行业的飞速发展,中国的监管当局也不断加大对各金融机构的监管力度, 中国的三大监管机构银监会、人民银行和外管局也都需要金融机构按照不同的要 求、方式等报送报表或数据,通过这些报表和数据的进一步分析结果来对金融机 构制定不同的监管策略。 从目前情形来看,各金融机构,尤其是商业银行,为应对三大监管机构的监 管要求所需要报送的内容给商业银行的业务人员带来了繁重的工作压力。在这种 情况下,就需要有一套统一的监管报送平台来完成这些报表、数据的自动化生成 工作,使用这种自动化的方式代替传统的手工填报的方式。这样既减轻了业务人 员的工作压力,也保证了所报送的报表、数据的准确性。因此,对金融机构来说, 建立一套统一的监管报送平台是非常必要的。 在本方案中主要包括以下两个主要的报送模块:银监会 1104 报送、人民银 行大集中报送。中软融鑫公司利用公司自有的产品“统一监管报送平台”来实现
<think>好的,我现在需要处理用户关于XXL-JOB任务调度使用指南的查询。首先,用户已经提供了四个引用资料,我需要仔细阅读这些引用内容,提关键信息,然后按照用户的要求组织回答结构。 首先,用户要求回答结构清晰,分步骤解决问题,并保证真实可靠。根据引用内容,引用1提到通过Docker安装XXL-JOB管理端和集成执行器的示例。引用2补充了部署到Docker并与Spring Boot整合的步骤,以及配置任务和调用执行器的过程。引用3是安装配置的简要指南,而引用4详细说明了如何新增任务,特别是Cron和JobHandler的设置,以及测试任务的方法。 接下来,我需要将信息整合成步骤指南。根据引用,安装部署部分应该包括Docker安装管理端,这在引用1、2、3中都有涉及。然后,执行器的集成部分,引用1和2提到在Java项目中使用Spring Boot集成。任务配置部分,引用4详细说明了新增任务时的关键字段,如Cron和JobHandler,以及测试任务的方法。调度中心管理可能包括任务启动、日志查看,这在引用4中提到调度日志,引用3提到管理平台的基本功能。 然后,注意事项部分,引用4提到JobHandler需要与注解保持一致,引用2和3可能涉及高可用和日志监控。最后,引用官方文档作为附录,如引用2的附录部分。 在生成相关问题的时候,需要根据用户提供的示例,围绕安装、集成、配置、监控等方面提问。例如,如何安装管理端,如何集成执行器,如何配置Cron表达式,如何监控任务执行等。 需要注意的是,所有数学公式和代码块需要正确使用LaTeX格式,但当前内容中没有涉及数学公式,代码块部分需要检查是否正确。例如,用户提供的示例中有Python代码,但XXL-JOB相关可能涉及Java或Docker命令,需要正确展示。 最后,确保回答中的引用标识正确添加,每个步骤末尾自然地加上对应的引用标记,如[^1]、[^2]等。检查是否有遗漏的关键点,比如执行器注解的使用、调度中心的访问等,确保覆盖用户需要的使用指南。</think>### XXL-JOB 任务调度使用指南 #### 1. **安装与部署** **管理端部署(Docker环境)** 通过 Docker 快速部署 XXL-JOB 管理端,步骤如下: ```bash # 镜像 docker pull xuxueli/xxl-job-admin:2.3.1 # 运行容器(需配置数据库) docker run -e PARAMS="--spring.datasource.url=jdbc:mysql://[数据库地址] --spring.datasource.username=[用户名] --spring.datasource.password=[密码]" -p 8080:8080 -d xuxueli/xxl-job-admin:2.3.1 ``` 部署成功后,访问 `http://localhost:8080/xxl-job-admin` 进入调度中心[^3]。 --- #### 2. **执行器集成(以 Spring Boot 为例)** **步骤 1:添加依赖** 在 `pom.xml` 中引入执行器依赖: ```xml <dependency> <groupId>com.xuxueli</groupId> <artifactId>xxl-job-core</artifactId> <version>2.3.1</version> </dependency> ``` **步骤 2:配置执行器** 在 `application.yml` 中配置调度中心地址和执行器参数: ```yaml xxl: job: admin: addresses: http://localhost:8080/xxl-job-admin executor: appname: xxl-job-demo port: 9999 ``` **步骤 3:定义任务处理器** 使用 `@XxlJob` 注解标记任务方法,需与调度中心配置的 `JobHandler` 名称一致: ```java @Component public class DemoJobHandler { @XxlJob("demoJobHandler") public void execute() { // 任务逻辑代码 } } ``` [^4] --- #### 3. **任务配置** 1. **新增任务** - 登录调度中心,进入任务管理页面,点击**新增**。 - 关键字段说明: - **Cron**:任务执行周期表达式,例如 `0 0/5 * * * ?` 表示每5分钟执行一次。 - **JobHandler**:需与代码中 `@XxlJob` 注解值一致(如 `demoJobHandler`)。 - 填写其他参数(路由策略、重试次数等)后保存[^4]。 2. **测试与启动** - 新增后,在操作列点击**执行一次**,验证任务逻辑。 - 测试成功后,点击**启动**启用任务调度[^4]。 --- #### 4. **调度中心管理** - **任务监控**:通过**调度日志**查看任务执行状态、耗时和结果。 - **动态调整**:支持在线修改任务参数(如 Cron 表达式)并实时生效。 - **失败告警**:配置邮件或钉钉通知,及时处理失败任务[^4]。 --- #### 5. **注意事项** 1. **JobHandler 一致性**:确保代码中的注解值与调度中心配置完全匹配。 2. **执行器高可用**:多节点部署执行器时,调度中心会自动路由任务。 3. **日志与调试**:建议开启执行器日志,便于排查任务逻辑问题。 --- #### 附录:XXL-JOB 官方文档 详细配置参考:[XXL-JOB 官方文档](https://www.xuxueli.com/xxl-job/)。 --- §§ 1. 如何配置 XXL-JOB 的邮件告警功能? 2. 执行器多节点部署时如何实现负载均衡? 3. XXL-JOB 的 Cron 表达式有哪些特殊语法? 4. 如何通过 XXL-JOB 实现分片广播任务
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值