• xxl-job分布式任务调度


    git地址: https://github.com/xuxueli/xxl-job

    一个分布式的任务调度框架,官网文档写的非常详细,只是简单的记录下。

    1. 部署admin项目

      admin项目是一个可视化管理控制的项目。

     1.下载

    到码云克隆项目:http://gitee.com/xuxueli0323/xxl-job

     2.到数据库执行脚本

    /xxl-job/doc/db/tables_xxl_job.sql

    3.编译源码

    xxl-job-admin:调度中心
    xxl-job-core:公共依赖
    xxl-job-executor-samples:执行器Sample示例(选择合适的版本执行器,可直接使用,也可以参考其并将现有项目改造成执行器)
        :xxl-job-executor-sample-springboot:Springboot版本,通过Springboot管理执行器,推荐这种方式;
        :xxl-job-executor-sample-spring:Spring版本,通过Spring容器管理执行器,比较通用;
        :xxl-job-executor-sample-frameless:无框架版本;
        :xxl-job-executor-sample-jfinal:JFinal版本,通过JFinal管理执行器;
        :xxl-job-executor-sample-nutz:Nutz版本,通过Nutz管理执行器;
        :xxl-job-executor-sample-jboot:jboot版本,通过jboot管理执行器;

    4.配置调度中心

    xxl-job-admin 是项目的配置中心。导入IDEA,maven环境配置好之后启动是非常方便的。

    1. 需要改一下数据库的连接信息

    2.启动主类

    3.启动后访问8080端口就可以

    4.登录  账号密码是  admin/123456

    5.界面如下:

     2. 配置项目执行器项目

       这个就是实际工作的项目。这个是xxl-job自带的项目。

    1.启动xxl-job-executor-sample-springboot 项目

    2. 控制台执行

    3. 启动后从admin管理项目运行一次

    到任务管理执行一次即可。

    4.查看启动日志

    2020-11-15 14:09:00 [com.xxl.job.core.thread.JobThread#run]-[130]-[Thread-39] 
    ----------- xxl-job job execute start -----------
    ----------- Param:
    2020-11-15 14:09:00 [com.xxl.job.executor.service.jobhandler.SampleXxlJob#demoJobHandler]-[39]-[Thread-39] XXL-JOB, Hello World.
    2020-11-15 14:09:00 [com.xxl.job.executor.service.jobhandler.SampleXxlJob#demoJobHandler]-[42]-[Thread-39] beat at:0
    2020-11-15 14:09:02 [com.xxl.job.executor.service.jobhandler.SampleXxlJob#demoJobHandler]-[42]-[Thread-39] beat at:1
    2020-11-15 14:09:04 [com.xxl.job.executor.service.jobhandler.SampleXxlJob#demoJobHandler]-[42]-[Thread-39] beat at:2
    2020-11-15 14:09:06 [com.xxl.job.executor.service.jobhandler.SampleXxlJob#demoJobHandler]-[42]-[Thread-39] beat at:3
    2020-11-15 14:09:08 [com.xxl.job.executor.service.jobhandler.SampleXxlJob#demoJobHandler]-[42]-[Thread-39] beat at:4
    2020-11-15 14:09:10 [com.xxl.job.core.thread.JobThread#run]-[176]-[Thread-39] 
    ----------- xxl-job job execute end(finish) -----------
    ----------- Result: handleCode=200, handleMsg = null
    2020-11-15 14:09:10 [com.xxl.job.core.thread.TriggerCallbackThread#callbackLog]-[197]-[xxl-job, executor TriggerCallbackThread] 
    ----------- xxl-job job callback finish.
    
    [Load Log Finish]

    3 .模仿上面项目自建任务在Springboot中运行

     1.新建项目cloud-xxl-job-8081

     2.修改pom

    <?xml version="1.0" encoding="UTF-8"?>
    <project xmlns="http://maven.apache.org/POM/4.0.0"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
        <parent>
            <artifactId>cloud</artifactId>
            <groupId>cn.qz.cloud</groupId>
            <version>1.0-SNAPSHOT</version>
        </parent>
        <modelVersion>4.0.0</modelVersion>
    
        <artifactId>cloud-xxl-job-8081</artifactId>
    
        <dependencies>
            <!-- xxl-job-core -->
            <dependency>
                <groupId>com.xuxueli</groupId>
                <artifactId>xxl-job-core</artifactId>
                <version>2.2.0</version>
            </dependency>
            <!--引入自己抽取的工具包-->
            <dependency>
                <groupId>cn.qz.cloud</groupId>
                <artifactId>cloud-api-commons</artifactId>
                <version>${project.version}</version>
            </dependency>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-web</artifactId>
            </dependency>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-actuator</artifactId>
            </dependency>
            <dependency>
                <groupId>org.projectlombok</groupId>
                <artifactId>lombok</artifactId>
                <optional>true</optional>
            </dependency>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-test</artifactId>
                <scope>test</scope>
            </dependency>
        </dependencies>
    </project>

    3. 新增application.properties

    # web port
    server.port=8081
    # no web
    #spring.main.web-environment=false
    # log config
    logging.config=classpath:logback.xml
    ### xxl-job admin address list, such as "http://address" or "http://address01,http://address02"
    xxl.job.admin.addresses=http://127.0.0.1:8080/xxl-job-admin
    ### xxl-job, access token
    xxl.job.accessToken=
    ### xxl-job executor appname
    xxl.job.executor.appname=xxl-job-executor-test
    ### xxl-job executor registry-address: default use address to registry , otherwise use ip:port if address is null
    xxl.job.executor.address=
    ### xxl-job executor server-info
    xxl.job.executor.ip=
    xxl.job.executor.port=9999
    ### xxl-job executor log-path
    xxl.job.executor.logpath=/data/applogs/xxl-job/jobhandler
    ### xxl-job executor log-retention-days
    xxl.job.executor.logretentiondays=30

    关于配置的详细解释如下:

    ### 调度中心部署跟地址 [选填]:如调度中心集群部署存在多个地址则用逗号分隔。执行器将会使用该地址进行"执行器心跳注册"和"任务结果回调";为空则关闭自动注册;
    xxl.job.admin.addresses=http://127.0.0.1:8080/xxl-job-admin
    ### 执行器通讯TOKEN [选填]:非空时启用;
    xxl.job.accessToken=
    ### 执行器AppName [选填]:执行器心跳注册分组依据;为空则关闭自动注册
    xxl.job.executor.appname=xxl-job-executor-sample
    ### 执行器注册 [选填]:优先使用该配置作为注册地址,为空时使用内嵌服务 ”IP:PORT“ 作为注册地址。从而更灵活的支持容器类型执行器动态IP和动态映射端口问题。
    xxl.job.executor.address=
    ### 执行器IP [选填]:默认为空表示自动获取IP,多网卡时可手动设置指定IP,该IP不会绑定Host仅作为通讯实用;地址信息用于 "执行器注册" 和 "调度中心请求并触发任务";
    xxl.job.executor.ip=
    ### 执行器端口号 [选填]:小于等于0则自动获取;默认端口为9999,单机部署多个执行器时,注意要配置不同执行器端口;
    xxl.job.executor.port=9999
    ### 执行器运行日志文件存储磁盘路径 [选填] :需要对该路径拥有读写权限;为空则使用默认路径;
    xxl.job.executor.logpath=/data/applogs/xxl-job/jobhandler
    ### 执行器日志文件保存天数 [选填] : 过期日志自动清理, 限制值大于等于3时生效; 否则, 如-1, 关闭自动清理功能;
    xxl.job.executor.logretentiondays=30

    4. 主启动类

    package cn.qz.cloud;
    
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    
    /**
     * @Author: qlq
     * @Description
     * @Date: 14:44 2020/11/15
     */
    @SpringBootApplication
    public class XXLJobMain8081 {
    
        public static void main(String[] args) {
            SpringApplication.run(XXLJobMain8081.class, args);
        }
    
    }

    5.业务类

      有两种方式。第一种是基于方法上面增加注解@XxlJob;第二种是类继承IJobHandler,然后通过手动注入到执行器容器。

    (1)  方法加注解 @XxlJob  实现

    package cn.qz.cloud.job;
    
    import com.xxl.job.core.biz.model.ReturnT;
    import com.xxl.job.core.handler.annotation.XxlJob;
    import com.xxl.job.core.log.XxlJobLogger;
    import lombok.extern.slf4j.Slf4j;
    import org.springframework.stereotype.Component;
    
    /**
     * @Author: qlq
     * @Description
     * @Date: 15:22 2020/11/15
     */
    @Slf4j
    @Component
    public class FirstJob {
    
        @XxlJob(value = "firstJob", init = "init", destroy = "destroy")
        public ReturnT<String> execute(String param) {
            XxlJobLogger.log("XXL-JOB, firstJob. param: {}", param);
            log.info("XXL-JOB, firstJob. param: {}", param);
            return ReturnT.SUCCESS;
        }
    
        public void init() {
            log.info("init");
        }
    
        public void destroy() {
            log.info("destory");
        }
    }

      XxlJobLogger.log是记录到xxl-job-admin 的日志收集器里面,可以从admin管理台查看;普通的log记录是记录到我们系统的日志搜集器里面。

    (2) 继承IJobHandler的方式

    package cn.qz.cloud.job;
    
    import com.xxl.job.core.biz.model.ReturnT;
    import com.xxl.job.core.handler.IJobHandler;
    import com.xxl.job.core.log.XxlJobLogger;
    import lombok.extern.slf4j.Slf4j;
    
    import java.util.concurrent.TimeUnit;
    
    /**
     * @Author: qlq
     * @Description
     * @Date: 15:22 2020/11/15
     */
    @Slf4j
    public class XXLClassJob extends IJobHandler {
    
        @Override
        public ReturnT<String> execute(String param) throws Exception {
            log.info("XXLClassJob execute, param: {}", param);
            XxlJobLogger.log("XXLClassJob execute, param: {}", param);
    
            for (int i = 0; i < 5; i++) {
                log.info("XXLClassJob start, i: {} ", i);
                XxlJobLogger.log("XXLClassJob start, i: {} ", i);
                TimeUnit.SECONDS.sleep(2);
            }
            return ReturnT.SUCCESS;
        }
    }

    (3) 配置类: 注意需要手动将job注入到执行器容器

    package cn.qz.cloud.config;
    
    import cn.qz.cloud.job.XXLClassJob;
    import com.xxl.job.core.executor.XxlJobExecutor;
    import com.xxl.job.core.executor.impl.XxlJobSpringExecutor;
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    import org.springframework.beans.factory.annotation.Value;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    
    /**
     * @Author: qlq
     * @Description
     * @Date: 17:02 2020/11/15
     */
    @Configuration
    public class XxlJobConfig {
        private Logger logger = LoggerFactory.getLogger(XxlJobConfig.class);
    
        static {
            // 手动通过如下方式注入到执行器容器。
            XxlJobExecutor.registJobHandler("XXLClassJob", new XXLClassJob());
        }
    
        @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() {
            logger.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;
        }
    }

    6. 启动主类

    20:46:27.096 logback [main] INFO  o.a.coyote.http11.Http11NioProtocol - Starting ProtocolHandler ["http-nio-8081"]
    20:46:27.238 logback [main] INFO  o.s.b.w.e.tomcat.TomcatWebServer - Tomcat started on port(s): 8081 (http) with context path ''
    20:46:27.252 logback [main] INFO  cn.qz.cloud.XXLJobMain8081 - Started XXLJobMain8081 in 20.195 seconds (JVM running for 23.668)
    20:46:37.301 logback [Thread-5] INFO  com.xxl.job.core.server.EmbedServer - >>>>>>>>>>> xxl-job remoting server start success, nettype = class com.xxl.job.core.server.EmbedServer, port = 9999
    20:47:00.694 logback [xxl-rpc, EmbedServer bizThreadPool-1961798941] INFO  c.x.job.core.executor.XxlJobExecutor - >>>>>>>>>>> xxl-job regist JobThread success, jobId:4, handler:com.xxl.job.core.handler.impl.MethodJobHandler@42ea7565[class cn.qz.cloud.job.FirstJob#execute]
    20:47:00.695 logback [Thread-8] INFO  cn.qz.cloud.job.FirstJob - init
    20:47:00.715 logback [xxl-rpc, EmbedServer bizThreadPool-1961798941] INFO  c.x.job.core.executor.XxlJobExecutor - >>>>>>>>>>> xxl-job regist JobThread success, jobId:5, handler:cn.qz.cloud.job.XXLClassJob@23706db8

    可以看到启动了一个内嵌的服务9999端口。通过netstat -ano 也可以查看9999端口,如果之后测试报错可以查看是否没有监听到某个端口。

    7.在xxl-job-admin 界面进行设置

    (1) 新建一个 执行器

     (2) 新建一个任务管理执行XXLClassJob 任务

    (3)新建一个任务执行firstJob

     (4) 任务管理 -》 选择一条任务之后执行一次  firstJob

    到IDEA查看日志如下:

    21:06:27.977 logback [xxl-rpc, EmbedServer bizThreadPool-1916408283] INFO  c.x.job.core.executor.XxlJobExecutor - >>>>>>>>>>> xxl-job regist JobThread success, jobId:4, handler:com.xxl.job.core.handler.impl.MethodJobHandler@523a7801[class cn.qz.cloud.job.FirstJob#execute]
    21:06:27.983 logback [Thread-8] INFO  cn.qz.cloud.job.FirstJob - init
    21:06:28.007 logback [Thread-8] INFO  cn.qz.cloud.job.FirstJob - XXL-JOB, firstJob. param: XXX

     然后可以到XxlJob-admin查看日志:

    2020-11-15 21:06:27 [com.xxl.job.core.thread.JobThread#run]-[124]-[Thread-8] 
    ----------- xxl-job job execute start -----------
    ----------- Param:XXX
    2020-11-15 21:06:28 [cn.qz.cloud.job.FirstJob#execute]-[20]-[Thread-8] XXL-JOB, firstJob. param: XXX
    2020-11-15 21:06:28 [com.xxl.job.core.thread.JobThread#run]-[164]-[Thread-8] 
    ----------- xxl-job job execute end(finish) -----------
    ----------- ReturnT:ReturnT [code=200, msg=null, content=null]
    2020-11-15 21:06:28 [com.xxl.job.core.thread.TriggerCallbackThread#callbackLog]-[191]-[xxl-job, executor TriggerCallbackThread] 
    ----------- xxl-job job callback finish.

     8. 简单的测下分布式环境控制哪个机器执行任务

    1. 再启动一个执行项目,项目端口8082;xxl.job.executor.port 改为9998

    2. 从admin查看机器地址有两个,如下:

     3. 编辑任务可以看到有好几种策略。这些策略是说从哪个机器执行上面的任务,类似于一个应该多实例部署,我们可以手动设置哪个实例执行任务。有点类似于负载均衡。

     4.我们改为轮询即可,可以通过执行日志查看到是两个机器替换着执行

    9. GLUE模式(Java)  简单使用

     上面的模式可以称为Bean模式,符合常见的开发思想。

     “GLUE模式(Java)”的执行代码托管到调度中心在线维护,相比“Bean模式任务”需要在执行器项目开发部署上线,更加简便轻量),可使用@Resource/@Autowire注入执行器里中的其他服务。前提是“调度中心”和“执行器”项目已经成功部署并启动。这种模式实现是利用groovy将类信息加载到JVM中。

    1.新建一个任务管理,模式选择GLUE

     2. 任务管理选择一条任务 操作-》 GLUE IDE,代码如下:

    package cn.qz.cloud.job;
    
    import com.xxl.job.core.biz.model.ReturnT;
    import com.xxl.job.core.handler.IJobHandler;
    import com.xxl.job.core.log.XxlJobLogger;
    import lombok.extern.slf4j.Slf4j;
    
    import java.util.concurrent.TimeUnit;
    
    /**
     * @Author: qlq
     * @Description
     * @Date: 15:22 2020/11/15
     */
    public class XXLClassJob2 extends IJobHandler {
    
        @Override
        public ReturnT<String> execute(String param) throws Exception {
              System.out.println("param : " + param);
            XxlJobLogger.log("XXLClassJob2 execute, param: {}", param);
    
            for (int i = 0; i < 5; i++) {
                XxlJobLogger.log("XXLClassJob2 Glue start, i: {} ", i);
                TimeUnit.SECONDS.sleep(2);
            }
            return ReturnT.SUCCESS;
        }
    }

    3.执行一次后可以到IDEA查看日志,同时查看执行日志如下:

    2020-11-15 21:42:59 [com.xxl.job.core.thread.JobThread#run]-[124]-[Thread-15] 
    ----------- xxl-job job execute start -----------
    ----------- Param:这是Glue参数
    2020-11-15 21:42:59 [com.xxl.job.core.handler.impl.GlueJobHandler#execute]-[26]-[Thread-15] ----------- glue.version:1605447731000 -----------
    2020-11-15 21:42:59 [sun.reflect.GeneratedMethodAccessor31#invoke]-[-1]-[Thread-15] XXLClassJob2 execute, param: 这是Glue参数
    2020-11-15 21:42:59 [sun.reflect.GeneratedMethodAccessor31#invoke]-[-1]-[Thread-15] XXLClassJob2 Glue start, i: 0 
    2020-11-15 21:43:01 [sun.reflect.GeneratedMethodAccessor31#invoke]-[-1]-[Thread-15] XXLClassJob2 Glue start, i: 1 
    2020-11-15 21:43:03 [sun.reflect.GeneratedMethodAccessor31#invoke]-[-1]-[Thread-15] XXLClassJob2 Glue start, i: 2 
    2020-11-15 21:43:05 [sun.reflect.GeneratedMethodAccessor31#invoke]-[-1]-[Thread-15] XXLClassJob2 Glue start, i: 3 
    2020-11-15 21:43:07 [sun.reflect.GeneratedMethodAccessor31#invoke]-[-1]-[Thread-15] XXLClassJob2 Glue start, i: 4 
    2020-11-15 21:43:09 [com.xxl.job.core.thread.JobThread#run]-[164]-[Thread-15] 
    ----------- xxl-job job execute end(finish) -----------
    ----------- ReturnT:ReturnT [code=200, msg=null, content=null]
    2020-11-15 21:43:09 [com.xxl.job.core.thread.TriggerCallbackThread#callbackLog]-[191]-[xxl-job, executor TriggerCallbackThread] 
    ----------- xxl-job job callback finish.

      至此简单的实现了分布式环境下的任务调度。当任务在多个实例部署的时候,可以在xxl-job的管理界面选择执行任务的机器。

  • 相关阅读:
    C# 枚举、字符串、值的相互转换
    What's New in v2010 vol 2.5
    Using Oracle's Parallel Execution Features
    [zhuan]asp.net程序性能优化的七个方面 (c#(或vb.net)程序改进)
    ORACLE常用网址
    html中的块元素(block element)和内联元素(inline element)
    软件构架师的特点
    窗体信息处理函数讲解
    [xue]软件项目经理所必需具备的素质
    Gulp系列文章入门Gulp
  • 原文地址:https://www.cnblogs.com/qlqwjy/p/13945470.html
Copyright © 2020-2023  润新知