微服务定时任务并发 微服务中的定时任务_定时任务


Spring Boot详解(3)定时任务mp.weixin.qq.com

微服务定时任务并发 微服务中的定时任务_springboot是单线程_02


定时任务:我们在项目中,会使用定时任务去执行一些业务上或者是项目数据的备份和更新的操作,那么我们在微服务架构中怎么使用定时任务呢?又有多少种定时任务的实现方式呢?而定时任务的原理又是什么呢?


1. Timer 和 ScheduledExecutorService

Timer是jdk中提供的一个定时器工具,使用的时候会在主线程之外起一个单独的线程执行指定的计划任务,可以指定执行一次或者反复执行多次。但是不能指定时间运行,所以使用在使用场景上较为局限!


import


ScheduledExecutorService的主要作用就是可以将定时任务与线程池功能结合使用。


public


2.Spring 配置定时任务

在Spring中,通过Spring的配置文件进行注入定时任务的配置类,注入定时任务的执行类,通过标签定义。


<description>
        定时任务


代码实现


@Service


同样,我们也可以使用注解的形式来实现定时任务。


@Component


3.SpringBoot 实现定时任务

  • 基于注解@Schedule

默认是单线程的,任务的执行时间受上一个任务的执行时间影响。


@Component


通过不同的corn表达式,我们可以定义各种任务的执行时间


0


  • 基于接口的定时任务(SchedulingConfiguration)

导入依赖


<parent>


添加数据库记录,在数据库中配置定时任务表达式


DROP DATABASE IF EXISTS `socks`;
CREATE DATABASE `socks`;
USE `SOCKS`;
DROP TABLE IF EXISTS `cron`;
CREATE TABLE `cron`  (
  `cron_id` varchar(30) NOT NULL PRIMARY KEY,
  `cron` varchar(30) NOT NULL  
);
INSERT INTO `cron` VALUES ('1', '0/5 * * * * ?');


创建定时器,这里我们使用的是TriggerTask,目的是来循环执行我们在数据库中配置的执行周期,执行定时任务!


@Componen


多线程定时任务,基于注解实现!


//@Component注解用于对那些比较中立的类进行注释;


这种方式可以使每个任务的执行不受上一个或其他任务执行的状态所影响,在项目中我们在执行一些周期性间隔的任务时,可以配置为多线程的任务形式,但是我们要考虑到每个线程的执行时间,不要造成定时任务占用过多的线程,导致系统可用性降低!

4.使用quartz实现定时任务

Quartz设计者做了一个设计选择来从调度分离开作业。Quartz中的触发器用来告诉调度程序作业什么时候触发。框架提供了一把触发器类型,但两个最常用的是SimpleTrigger和CronTrigger。SimpleTrigger为需要简单打火调度而设计。典型地,如果你需要在给定的时间和重复次数或者两次打火之间等待的秒数打火一个作业,那么SimpleTrigger适合你。另一方面,如果你有许多复杂的作业调度,那么或许需要CronTrigger。
    CronTrigger是基于Calendar-like调度的。当你需要在除星期六和星期天外的每天上午10点半执行作业时,那么应该使用CronTrigger。正如它的名字所暗示的那样,CronTrigger是基于Unix克隆表达式的。

导入依赖:


<dependency>


由于我们使用的是spring-boot框架,其目的是做到零配置文件,所以我们不使用xml文件的配置文件来定义一个定时器,而是使用向spring容器暴露bean的方式


@Configuration


MethodInvokingJobDetailFactoryBean:此工厂主要用来制作一个jobDetail,即制作一个任务。由于我们所做的定时任务根本上讲其实就是执行一个方法。所以用这个工厂比较方便。

      注意:其setTargetObject所设置的是一个对象而不是一个类。

CronTriggerBean:定义一个触发器。

      注意:setCronExpression:是一个表达式,如果此表达式不合规范,即会抛出异常。

SchedulerFactoryBean:主要的管理的工厂,这是最主要的一个bean。quartz通过这个工厂来进行对各触发器的管理。

  4.对quartz的封装

    由上面代码可以看出来,此处我们设置的是一个固定的cronExpression,那么,做为项目中使用的话,我们一般是需要其动态设置比如从数据库中取出来。

    其实做法也很简单,我们只需要定义一个Trigger来继承CronTriggerBean。顶用其setCronExpression方法即可。

    那么另外一个问题,如果我们要定义两个定时任务则会比较麻烦,需要先注入一个任务工厂,在注入一个触发器。

    为了减少这样的配置,我们定义了一个抽象的超类来继承CronTriggerBean。


public


其init()方法,来为这个触发器绑定任务。其任务为一个Job类型的,也就是说其执行的任务为实现了Job接口的类,这个任务会有一个execute()方法,来执行任务题。


public


为了给触发器添加任务,我们需要在子类中调用init()方法,由于spring容器注入时是使用的空参的构造函数,所以我们在此构造函数中调用init()方法。


@Component


此时我们只需要在配置类中加入一个配置就可以了。


@Bean