精华内容
下载资源
问答
  • schedule-job, 基于Spring Boot Quartz分布式任务调度系统
  • Spring boot + Quartz实现分布式定时任务

    千次阅读 2018-08-29 23:01:18
    在实际项目中经常会用到定时任务,且有些定时任务同时只能运行一个实例,下面介绍一下通过Spring boot + Quartz框架实现分布式定时任务。 1. 定时任务持久化到Mysql 2. 名称为JobA的定时任务每10秒执行一次@...

    在实际项目中经常会用到定时任务,且有些定时任务同时只能运行一个实例,下面介绍一下通过Spring boot + Quartz框架实现分布式定时任务。
    1. 定时任务持久化到Mysql
    2. 名称为JobA的定时任务每10秒执行一次@ScheduledJob(name = “JobA”, cronExp = “/10 * * * ?”)
    3. @DisallowConcurrentExecution同一个定时任务同一时间只能有一个执行,如果定时任务执行时间超过10秒,丢弃或等待(未验证)
    4. 此定时任务可以同时部署多个,支持Failover
    5. Quartz相关SQL请参考https://github.com/465919283/demo/blob/master/sql/quartz.sql

    quartz.properties
    
    org.quartz.scheduler.instanceName=spring-boot-quartz
    org.quartz.scheduler.instanceId=AUTO
    org.quartz.threadPool.threadCount=5
    org.quartz.jobStore.class=org.quartz.impl.jdbcjobstore.JobStoreTX
    org.quartz.jobStore.driverDelegateClass = org.quartz.impl.jdbcjobstore.StdJDBCDelegate
    org.quartz.jobStore.useProperties=false
    org.quartz.jobStore.tablePrefix=QRTZ_
    org.quartz.jobStore.isClustered=true
    import org.quartz.spi.JobFactory;
    import org.quartz.spi.TriggerFiredBundle;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.beans.factory.config.AutowireCapableBeanFactory;
    import org.springframework.beans.factory.config.PropertiesFactoryBean;
    import org.springframework.context.ApplicationContext;
    import org.springframework.context.ApplicationContextAware;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.core.io.ClassPathResource;
    import org.springframework.scheduling.quartz.SchedulerFactoryBean;
    import org.springframework.scheduling.quartz.SpringBeanJobFactory;
    import org.springframework.transaction.PlatformTransactionManager;
    @Configuration
    public class QuartzConfig {
    
        public static final String QUARTZ_PROPERTIES_PATH = "quartz.properties";
    
        @Autowired
        private DataSource dataSource;
        @Autowired
        private PlatformTransactionManager transactionManager;
    
    
        @Bean
        public JobFactory jobFactory(ApplicationContext applicationContext) {
            AutowiringSpringBeanJobFactory jobFactory = new AutowiringSpringBeanJobFactory();
            jobFactory.setApplicationContext(applicationContext);
            return jobFactory;
        }
    
        @Bean
        public SchedulerFactoryBean schedulerFactoryBean(JobFactory jobFactory) throws IOException {
            SchedulerFactoryBean factory = new SchedulerFactoryBean();
            factory.setAutoStartup(true);
            factory.setJobFactory(jobFactory);
            factory.setQuartzProperties(quartzProperties());
            //使用Spring boot中配置的数据源
            factory.setDataSource(dataSource);
            factory.setTransactionManager(transactionManager);
            return factory;
        }
    
        @Bean
        public Properties quartzProperties() throws IOException {
            PropertiesFactoryBean propertiesFactoryBean = new PropertiesFactoryBean();
            propertiesFactoryBean.setLocation(new ClassPathResource(QUARTZ_PROPERTIES_PATH));
            propertiesFactoryBean.afterPropertiesSet();
            return propertiesFactoryBean.getObject();
        }
    
        public static class AutowiringSpringBeanJobFactory extends SpringBeanJobFactory implements
                ApplicationContextAware {
    
            private transient AutowireCapableBeanFactory beanFactory;
    
            @Override
            public void setApplicationContext(final ApplicationContext context) {
                beanFactory = context.getAutowireCapableBeanFactory();
            }
    
            @Override
            protected Object createJobInstance(final TriggerFiredBundle bundle) throws Exception {
                final Object job = super.createJobInstance(bundle);
                beanFactory.autowireBean(job);
                return job;
            }
        }
    }
    import java.lang.annotation.ElementType;
    import java.lang.annotation.Retention;
    import java.lang.annotation.RetentionPolicy;
    import java.lang.annotation.Target;
    
    @Target(ElementType.TYPE)
    @Retention(RetentionPolicy.RUNTIME)
    public @interface ScheduledJob {
    
        String name();
    
        String group() default "DEFAULT_GROUP";
    
        String cronExp();
    }
    import org.quartz.CronScheduleBuilder;
    import org.quartz.Job;
    import org.quartz.JobBuilder;
    import org.quartz.JobDetail;
    import org.quartz.JobKey;
    import org.quartz.Scheduler;
    import org.quartz.SchedulerException;
    import org.quartz.Trigger;
    import org.quartz.TriggerBuilder;
    import org.springframework.beans.BeansException;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.beans.factory.config.BeanPostProcessor;
    import org.springframework.core.annotation.AnnotationUtils;
    import org.springframework.stereotype.Component;
    
    @Component
    public class ScheduleListener implements BeanPostProcessor {
    
        @Autowired
        private Scheduler scheduler;
    
        @Override
        public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
            return bean;
        }
    
        @Override
        public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
            ScheduledJob scheduledJob = AnnotationUtils.findAnnotation(bean.getClass(), ScheduledJob.class);
            if (scheduledJob != null && bean instanceof Job) {
                JobKey jobKey = new JobKey(scheduledJob.name(), scheduledJob.group());
    
                JobDetail jobDetail = JobBuilder.newJob(((Job) bean).getClass())
                        .withIdentity(jobKey)
                        .build();
    
                Trigger trigger = TriggerBuilder.newTrigger()
                        .withIdentity(scheduledJob.name() + "Trigger", scheduledJob.group())
                        .forJob(jobDetail)
                        .withSchedule(CronScheduleBuilder.cronSchedule(scheduledJob.cronExp()))
                        .build();
    
                try {
                    if (!scheduler.checkExists(jobKey)) {
                        scheduler.scheduleJob(jobDetail, trigger);
                    }
                } catch (SchedulerException e) {
                    e.printStackTrace();
                }
            }
            return bean;
        }
    }
    
    import org.quartz.DisallowConcurrentExecution;
    import org.quartz.Job;
    import org.quartz.JobExecutionContext;
    import org.quartz.JobExecutionException;
    import org.springframework.stereotype.Component;
    
    import com.primer.demo.task.ScheduledJob;
    
    @Component
    @ScheduledJob(name = "JobA", cronExp = "*/10 * * * * ?")
    @DisallowConcurrentExecution
    public class JobA implements Job {
    
        @Override
        public void execute(JobExecutionContext context) throws JobExecutionException {
            // TODO Auto-generated method stub
            System.out.println("JobA................");
        }
    }
    

    完整代码请参考https://github.com/465919283/demo

    展开全文
  • 集成了分布式任务调度框架Quartz ,任务存储于数据库。 使用SpringMVC作为路由控制,集成的SWagger2提供实时RESTful API文档。 数据持久层集成Mybatis框架。 使用自定义注释解@TargetDataSource实现了多数据源动态...
  • 集成了分布式任务调度框架 Quartz ,任务存储于数据库。 使用SpringMVC作为路由控制, 集成 Swagger2 提供实时 RESTful API文档。 数据持久层集成 Mybatis 框架。 使用自定义注解 @TargetDataSource 实现了多数据源...
  • Spring Boot Quartz 主要内容 Spring Scheduler 框架 Quartz 框架,功能强大,配置灵活 Quartz 集群 mysql 持久化定时任务脚本(tables_mysql.sql) 介绍 在工程中时常会遇到一些需求,例如定时刷新一下配置、隔一段...

    Spring Boot Quartz

    主要内容

    • Spring Scheduler 框架
    • Quartz 框架,功能强大,配置灵活
    • Quartz 集群
    • mysql 持久化定时任务脚本(tables_mysql.sql)

    介绍

    在工程中时常会遇到一些需求,例如定时刷新一下配置、隔一段时间检查下网络状态并发送邮件等诸如此类的定时任务。
    定时任务本质就是一个异步的线程,线程可以查询或修改并执行一系列的操作。由于本质是线程,在 Java 中可以自行编写一个线程池对定时任务进行控制,但这样效率太低了,且功能有限,属于重复造轮子。

    分布式任务调度应用场景

    Quartz的集群功能通过故障转移和负载平衡功能为您的调度程序带来高可用性和可扩展性。

    调度程序中会有很多定时任务需要执行,一台服务器已经不能满足使用,需要解决定时任务单机单点故障问题。

    用Quartz框架,在集群环境下,通过数据库锁机制来实现定时任务的执行;独立的 Quartz 节点并不与另一其的节点或是管理节点通信。

    Spring Scheduler 实现定时任务

    1.定义 Task 类

    /**
     * Spring Scheduled示例
     */
    @Component
    public class ScheduledTask {
    
        private static final SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        private Integer count0 = 1;
        private Integer count1 = 1;
        private Integer count2 = 1;
    
        @Scheduled(fixedRate = 5000)
        public void reportCurrentTime() throws InterruptedException {
            System.out.println(String.format("reportCurrentTime第%s次执行,当前时间为:%s", count0++, dateFormat.format(new Date())));
        }
    
        @Scheduled(fixedDelay = 5000)
        public void reportCurrentTimeAfterSleep() throws InterruptedException {
            System.out.println(String.format("reportCurrentTimeAfterSleep第%s次执行,当前时间为:%s", count1++, dateFormat.format(new Date())));
        }
    
        @Scheduled(cron = "0 0 1 * * *")
        public void reportCurrentTimeCron() throws InterruptedException {
            System.out.println(String.format("reportCurrentTimeCron第%s次执行,当前时间为:%s", count2++, dateFormat.format(new Date())));
        }
    }

    2.启动定时任务

    在Spring Boot的主类中加入@EnableScheduling注解,启用定时任务的配置

    @RunWith(SpringRunner.class)
    @SpringBootTest
    @Slf4j
    @EnableScheduling
    public class ScheduledTaskTests {
        @Test
        public void test() {
            log.info("启动了ScheduledTask定时作业");
            while (true) {
            }
        }
    }

    quartz实现分布式定时任务

    quartz 是一个开源的分布式调度库,它基于java实现。
    > 它有着强大的调度功能,支持丰富多样的调度方式,比如简单调度,基于cron表达式的调度等等。
    > 支持调度任务的多种持久化方式。比如支持内存存储,数据库存储,Terracotta server 存储。
    > 支持分布式和集群能力。
    > 采用JDBCJobStore方式存储时,针对事务的处理方式支持全局事务(和业务服务共享同一个事务)和局部事务(quarzt 单独管理自己的事务)
    > 基于plugin机制以及listener机制支持灵活的扩展。

    1.pom.xml配置

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-quartz</artifactId>
    </dependency>
    
    <!-- mysql -->
    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
    </dependency>
    
    <!-- orm -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-data-jpa</artifactId>
    </dependency>

    2.spring-quartz.properties集群配置

    #============================================================================
    # 配置JobStore
    #============================================================================
    # JobDataMaps是否都为String类型,默认false
    org.quartz.jobStore.useProperties=false
    
    # 表的前缀,默认QRTZ_
    org.quartz.jobStore.tablePrefix = QRTZ_
    
    # 是否加入集群
    org.quartz.jobStore.isClustered = true
    
    # 调度实例失效的检查时间间隔 ms
    org.quartz.jobStore.clusterCheckinInterval = 5000
    
    # 当设置为“true”时,此属性告诉Quartz 在非托管JDBC连接上调用setTransactionIsolation(Connection.TRANSACTION_READ_COMMITTED)。
    org.quartz.jobStore.txIsolationLevelReadCommitted = true
    
    # 数据保存方式为数据库持久化
    org.quartz.jobStore.class = org.quartz.impl.jdbcjobstore.JobStoreTX
    
    # 数据库代理类,一般org.quartz.impl.jdbcjobstore.StdJDBCDelegate可以满足大部分数据库
    org.quartz.jobStore.driverDelegateClass = org.quartz.impl.jdbcjobstore.StdJDBCDelegate
    
    #============================================================================
    # Scheduler 调度器属性配置
    #============================================================================
    # 调度标识名 集群中每一个实例都必须使用相同的名称
    org.quartz.scheduler.instanceName = ClusterQuartz
    # ID设置为自动获取 每一个必须不同
    org.quartz.scheduler.instanceId= AUTO
    
    #============================================================================
    # 配置ThreadPool
    #============================================================================
    # 线程池的实现类(一般使用SimpleThreadPool即可满足几乎所有用户的需求)
    org.quartz.threadPool.class=org.quartz.simpl.SimpleThreadPool
    
    # 指定线程数,一般设置为1-100直接的整数,根据系统资源配置
    org.quartz.threadPool.threadCount = 5
    
    # 设置线程的优先级(可以是Thread.MIN_PRIORITY(即1)和Thread.MAX_PRIORITY(这是10)之间的任何int 。默认值为Thread.NORM_PRIORITY(5)。)
    org.quartz.threadPool.threadPriority = 5

    3.定义两个job

    • QuartzJob.java
    //持久化
    @PersistJobDataAfterExecution
    //禁止并发执行(Quartz不要并发地执行同一个job定义(这里指一个job类的多个实例))
    @DisallowConcurrentExecution
    @Slf4j
    public class QuartzJob extends QuartzJobBean {
        @Override
        protected void executeInternal(JobExecutionContext context) throws JobExecutionException {
            String taskName = context.getJobDetail().getJobDataMap().getString("name");
            log.info("---> Quartz job {}, {} <----", new Date(), taskName);
        }
    }
    • QuartzJob2.java
    @PersistJobDataAfterExecution
    @DisallowConcurrentExecution
    @Slf4j
    public class QuartzJob2 extends QuartzJobBean {
    
        @Override
        protected void executeInternal(JobExecutionContext context) throws JobExecutionException {
            String taskName = context.getJobDetail().getJobDataMap().getString("name");
            log.info("---> Quartz job 2 {}, {} <----", new Date(), taskName);
        }
    }

    4.初始化触发器等信息,这里通过Listener初始化

    @Slf4j
    public class StartApplicationListener implements ApplicationListener<ContextRefreshedEvent> {
        @Autowired
        SchedulerConfig schedulerConfig;
        public static AtomicInteger count = new AtomicInteger(0);
        private static String TRIGGER_GROUP_NAME = "test_trriger";
        private static String JOB_GROUP_NAME = "test_job";
    
        @Override
        public void onApplicationEvent(ContextRefreshedEvent event) {
            // 防止重复执行
            if (event.getApplicationContext().getParent() == null && count.incrementAndGet() <= 1) {
                initMyJob();
            }
        }
    
        public void initMyJob() {
            Scheduler scheduler = null;
            try {
                scheduler = schedulerConfig.scheduler();
    
                TriggerKey triggerKey = TriggerKey.triggerKey("trigger1", TRIGGER_GROUP_NAME);
                CronTrigger trigger = (CronTrigger) scheduler.getTrigger(triggerKey);
                if (null == trigger) {
                    Class clazz = QuartzJob.class;
                    JobDetail jobDetail = JobBuilder.newJob(clazz).withIdentity("job1", JOB_GROUP_NAME).build();
                    CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule("0/10 * * * * ?");
                    trigger = TriggerBuilder.newTrigger().withIdentity("trigger1", TRIGGER_GROUP_NAME)
                            .withSchedule(scheduleBuilder).build();
                    scheduler.scheduleJob(jobDetail, trigger);
                    log.info("Quartz 创建了job:...:{}", jobDetail.getKey());
                } else {
                    log.info("job已存在:{}", trigger.getKey());
                }
    
                TriggerKey triggerKey2 = TriggerKey.triggerKey("trigger2", TRIGGER_GROUP_NAME);
                CronTrigger trigger2 = (CronTrigger) scheduler.getTrigger(triggerKey2);
                if (null == trigger2) {
                    Class clazz = QuartzJob2.class;
                    JobDetail jobDetail2 = JobBuilder.newJob(clazz).withIdentity("job2", JOB_GROUP_NAME).build();
                    CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule("0/15 * * * * ?");
                    trigger2 = TriggerBuilder.newTrigger().withIdentity("trigger2", TRIGGER_GROUP_NAME)
                            .withSchedule(scheduleBuilder).build();
                    scheduler.scheduleJob(jobDetail2, trigger2);
                    log.info("Quartz 创建了job:...:{}", jobDetail2.getKey());
                } else {
                    log.info("job已存在:{}", trigger2.getKey());
                }
                scheduler.start();
            } catch (Exception e) {
                log.info(e.getMessage());
            }
        }
    }

    5.启动定时器

    启动两个Application,分别是示例中的DemoQuartzApplication和DemoQuartzApplication2,会发现,两个Job会分别在两个应用执行。

    当手动停止一个应用的时候,另一个应用会自动接管所有任务并继续执行,如果任务太多,我们可以再开一台服务即可。实现了调度任务的高可用性和可扩展性

    运行效果如图:
    执行结果

    资料

    转载于:https://www.cnblogs.com/tqlin/p/11064519.html

    展开全文
  • 项目基于 jdk1.8 采用 Spring Boot 框架集成了分布式任务调度框架 Quartz ,任务存储于数据库。 使用SpringMVC作为路由控制, 集成 Swagger2 提供实时 RESTful API文档。 数据持久层集成 Mybatis 框架。 使用...

    项目基于 jdk1.8 采用 Spring Boot 框架

    集成了分布式任务调度框架 Quartz ,任务存储于数据库。
    使用SpringMVC作为路由控制, 集成 Swagger2 提供实时 RESTful API文档。
    数据持久层集成 Mybatis 框架。
    使用自定义注解 @TargetDataSource 实现了多数据源动态切换,支持数据库读写分离。
    HTTP JOB 接口调用使用 OkHttp3 替代了 HttpClient 。
    Thrift JOB 接口调用实现了 Thrift client 池化管理。
    集成了 Spring data redis,提供缓存服务

    https://github.com/lvhao/schedule-job

    展开全文
  • 动态管理了定时任务的添加、修改、删除等操作,可扩展性强
  • 基于quartz分布式定时计划任务插件,即插即用 脚本目录:src/main/db/ #功能支持 高可用: 1.集群系统保证单机执行计划任务 2.执行任务机器不可用后自动切换机器 负载均衡: 设计思路:使用分布式服务发现组件实现...

    plugin-quartz

    基于quartz分布式定时计划任务插件,即插即用
    脚本目录:src/main/db/

    #功能支持

    • 高可用:
      • 集群系统保证单机执行计划任务
      • 执行任务机器不可用后自动切换机器
    • 负载均衡:
      设计思路:使用分布式服务发现组件实现分布式集群负载均衡
      例如有(A、B)、(C、D)2个分布式集群系统
      A、B: 集成plugin-quartz插件,作为分布式系统计划任务API,调用C、D系统的服务执行计划任务逻辑
      C、D: 实现任务业务逻辑

    #依赖框架及版本

    • spring-boot-1.5.9.RELEASE
    • quartz-2.2.3
    • quartz-jobs-2.2.3

    #数据库版本

    • mysql-5.7.21

    #使用方法

    • 项目直接引入plugin-quartz插件依赖
    • 计划任务类继承以下两个抽象类(根据实际业务情况二选一)并实现execute(JobDataMap jobDataMap)和setParamsList(List list)方法即可
      1.BaseStatefulTask:(标记有状态job基类,同一任务不会同时执行多个job实例)
      2.BaseStatelessTask:(标记无状态job基类,同一任务会同时执行多个job实例)
      3.method execute: 定制开发计划任务逻辑实现
      4.method setParamsList: 设置计划任务参数,可以在execute方法中拿到参数,主要用于手动执行计划任务使用
    • 配置项
      quartz:
      defaultJobcron: 0 0 0 1 * ? //默认初始化计划任务的运行时间
      defaultGroupName: taskGroup //默认的计划任务组名

    #重要类介绍

    • AbstractBaseTask: 计划任务实现核心类,并增加了运行日志记录
    • AutowireTask: 用于启动扫描所有继承BaseTask的子类,并初始化计划任务信息到quartz相关表中
    • QuartzController: 提供api接口用于通过页面对计划任务做实时CRU操作

    #存在问题

    • 计划任务运行日志目前不支持分库分表,日志量会非常大

    #优化改进

    • 针对日志问题的分库分表方案:
      • 提供基于sharding-jdbc的分库分表支持.----侵入性比较强
      • 基于mycat实现日志表(qrtz_exe_log)分库分表.----无侵入性
    • 欢迎giter们提供更多更好的点子来共同改进插件.

    #代码地址

    https://github.com/97573122/plugin-quartz

    展开全文
  • springboot整合quartz实现分布式定时任务集群 文章参考1:https://blog.csdn.net/fyfguuug/article/details/79358159 文章参考2:https://blog.csdn.net/qq_41866572/article/details/80061853 文章参考3:...
  • 分布式定时任务Spring Boot + Quartz实现 最近在工作中使用Spring Boot自带的@Scheduled执行定时任务,但是当我的应用部署在多台机器上时,发现使用@SchedulerLock来控制单节点执行定时任务有点问题,所以决定更换...
  • org.springframework.boot groupId > < artifactId > spring-boot-starter-parent artifactId > < version > 1.4.1.RELEASE version > < relativePath /> parent > < properties > < ...
  • 一、摘要阅读完本文大概需要 10 分钟,本文主要分享内容如下:springboot + quartz + mysql 实现持久化分布式调度集群环境任务调度测试二、Quartz 集群架构Quartz 是 Java 领域最著名的开源任务调度工具。...
  • 项目使用springboot,一直是单机版,所以也就一直... 所以本文正是在了解到quartz可以实现分布式定时任务后,对quart做了简单的使用,并整理成博客,以前也有用过springquartz的整合,通过xml与properties配置文件,但...
  • 如果仅仅只是使用定时任务,可以使用Spring的schedule实现,方便,代码量少,只需引入必要依赖及一个简单的注解即可,类似 @Scheduled(cron = "0 0 1 * * ?") public void schedule1 () { logger.info("=== 定时...
  • 自定义并发_百度搜索spring-boot @Async 的使用、自定义Executor的配置方法 - CSDN博客定制并发类(九)实现一个自定义的Lock类 | 并发编程网 – ifeve.com115. Spring Boot 定时任务升级篇(集群/分布式下的定时...
  • 之前曾写过一个springboot 1x整合Quartz 动态创建定时任务 该篇文章参考 SpringBoot2.0新特性 - Quartz自动化配置集成 目录 Springboot2.x 整合quartz 创建测试Job 实现任务调度中心 多实例任务调度解决方案 1. ...
  • Quartz提供两种基本作业存储类型: RAMJobStore :RAM也就是内存,默认情况下Quartz会将任务调度存在内存中,这种方式性能是最好的,因为内存的速度是最快的。不好的地方就是数据缺乏持久性,但程序崩溃或者重新...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 2,976
精华内容 1,190
关键字:

bootquartzspring分布式

spring 订阅