任务调度平台——定时调度实现方式

本文深入探讨了任务调度的概念,包括单机和分布式定时任务的管理,详细介绍了Java中实现定时任务的各种方式,如Thread.sleep、TimerTask、线程池、Quartz及Spring Boot内置调度。此外,还对比分析了Elastic-Job、XXL-JOB和Quartz等分布式调度框架的特点与应用场景。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

任务调度

1、作用
  • 单机定时执行任务;
  • 分布式定时任务:
    把分散的,可靠性差的定时执行任务纳入统一的平台,并实现集群管理调度
    和分布式部署的一种定时任务的管理方式。
2、任务调度场景
  • 每天注册新用户、登陆信息:定时发送到邮箱
  • 同步任务:多次尝试调用失败,补偿机制(日志+定时job)
  • 其他
3、java实现定时方式
  • Thread.sleep
  • TimeTask
  • 线程池:可定时线程
  • quartz: 定时调度框架
  • springboot内置定时任务调度

基本三种方式

  • 多线程
public class MulThreadTask {

    private  static int count = 0;

    public static void main(String[] args) {

        new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    Thread.sleep(1000);
                } catch (Exception e) {
                    e.printStackTrace();
                }
                System.out.println("print sequence:" + (count++));
            }
        }).start();

    }
}
  • TimerTask
public class TimeTask01 {

    static int count =0;

    @SuppressWarnings("AlibabaAvoidUseTimer")
    public static void main(String[] args) {

        TimerTask timerTask = new TimerTask() {
            @Override
            public void run() {
                System.out.println("sequence:" + (count++));
            }
        };


        Timer timer = new Timer();
        long initialDelay  = 0;
        long period = 1000;

        timer.scheduleAtFixedRate(timerTask, initialDelay, period);


    }

}

  • 线程池

public class ThreadPoolTask {

    private static int count = 0;

    public static void main(String[] args) {

        ScheduledExecutorService executorService = Executors.newSingleThreadScheduledExecutor();
        executorService.scheduleAtFixedRate(new Runnable() {
            @Override
            public void run() {
                System.out.println("sequence:" + (count++));
            }
        }, 1, 1,TimeUnit.SECONDS);
    }
}

Quartz

public class MyJob implements Job {
	public void execute(JobExecutionContext context) throws JobExecutionException {
		System.out.println("quartz MyJob date:" + new Date().getTime());
	}
}

//1.创建Scheduler的工厂
      SchedulerFactory sf = new StdSchedulerFactory();
      //2.从工厂中获取调度器实例
      Scheduler scheduler = sf.getScheduler();


      //3.创建JobDetail
      JobDetail jb = JobBuilder.newJob(MyJob.class)
              .withDescription("this is a ram job") //job的描述
              .withIdentity("ramJob", "ramGroup") //job 的name和group
              .build();

      //任务运行的时间,SimpleSchedle类型触发器有效
      long time=  System.currentTimeMillis() + 3*1000L; //3秒后启动任务
      Date statTime = new Date(time);

      //4.创建Trigger
          //使用SimpleScheduleBuilder或者CronScheduleBuilder
      Trigger t = TriggerBuilder.newTrigger()
                  .withDescription("")
                  .withIdentity("ramTrigger", "ramTriggerGroup")
                  //.withSchedule(SimpleScheduleBuilder.simpleSchedule())
                  .startAt(statTime)  //默认当前时间启动
                  .withSchedule(CronScheduleBuilder.cronSchedule("0/2 * * * * ?")) //两秒执行一次
                  .build();

      //5.注册任务和定时器
      scheduler.scheduleJob(jb, t);

      //6.启动 调度器
      scheduler.start();
}

分布式调度框架

1、elastic-job

elastic-job 是由当当网基于quartz 二次开发之后的分布式调度解决方案 , 由两个相对独立的子项目Elastic-Job-Lite和Elastic-Job-Cloud组成 。
.
Elastic-Job-Lite定位为轻量级无中心化解决方案,使用jar包的形式提供分布式任务的协调服务。
Elastic-Job-Cloud使用Mesos + Docker(TBD)的解决方案,额外提供资源治理、应用分发以及进程隔离等服务

特点

  • 基于quartz 定时任务框架为基础的,因此具备quartz的大部分功能
  • 使用zookeeper做协调,调度中心,更加轻量级
  • 支持任务的分片
  • 支持弹性扩容 , 可以水平扩展 , 当任务再次运行时,会检查当前的服务器数量,重新分片,分片结束之后才会继续执行任务
  • 失效转移,容错处理,当一台调度服务器宕机或者跟zookeeper断开连接之后,会立即停* 止作业,然后再去寻找其他空闲的调度服务器,来运行剩余的任务
    提供运维界面,可以管理作业和注册中心。

2、xxl-job

由个人开源的一个轻量级分布式任务调度框架 ,主要分为 调度中心和执行器两部分 , 调度中心在启动初始化的时候,会默认生成执行器的RPC代理
对象(http协议调用), 执行器项目启动之后, 调度中心在触发定时器之后通过jobHandle 来调用执行器项目里面的代码,核心功能和elastic-job差不多
,同时技术文档比较完善

在这里插入图片描述

3、quartz

quartz 的常见集群方案如下,通过在数据库中配置定时器信息, 以数据库悲观锁的方式达到同一个任务始终只有一个节点在运行,

XXLJOB

步骤:
① 部署: xxl-job-admin 作为注册中心
② 创建执行器(具体调度地址) 可以支持集群
③ 配置文件需要填写xxl-job注册中心地址
④ 每个具体执行job服务器需要创建一个netty连接端口号
⑤ 需要执行job的任务类,集成IJobHandler抽象类注册到job容器中
⑥ Execute方法中编写具体job任务

# web port
server.port=8084

# log config
logging.config=classpath:logback.xml

# xxl-job
### xxl-job admin address list, such as "http://address" or "http://address01,http://address02"
xxl.job.admin.addresses=http://127.0.0.1:8081/xxl-job-admin

### xxl-job executor address
xxl.job.executor.appname=test
xxl.job.executor.ip=192.168.1.3
xxl.job.executor.port=9999

### xxl-job log path
xxl.job.executor.logpath=/data/applogs/xxl-job/jobhandler/

### xxl-job, access token
xxl.job.accessToken=
@Configuration
@ComponentScan(basePackages = "com.xxl.job.executor.service.jobhandler")
public class XxlJobConfig {
    private Logger logger = LoggerFactory.getLogger(XxlJobConfig.class);


    @Value("${xxl.job.admin.addresses}")
    private String addresses;

    @Value("${xxl.job.executor.appname}")
    private String appname;

    @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.accessToken}")
    private String accessToken;

    @Bean(initMethod = "start", destroyMethod = "destroy")
    public XxlJobExecutor xxlJobExecutor() {
        logger.info(">>>>>>>>>>> xxl-job config init.");
        XxlJobExecutor xxlJobExecutor = new XxlJobExecutor();
        xxlJobExecutor.setIp(ip);
        xxlJobExecutor.setPort(port);
        xxlJobExecutor.setAppName(appname);
        xxlJobExecutor.setAdminAddresses(addresses);
        xxlJobExecutor.setLogPath(logpath);
        xxlJobExecutor.setAccessToken(accessToken);
        return xxlJobExecutor;
    }

}

@JobHander(value = "demoJobHandler")
@Service
public class DemoJobHandler extends IJobHandler {
	@Value("${xxl.job.executor.port}")
	private String port;

	@Override
	public ReturnT<String> execute(String... params) throws Exception {
		XxlJobLogger.log("XXL-JOB, Hello World." + port);
		System.out.println("XXL-JOB, Hello World." + port);
		for (int i = 0; i < 5; i++) {
			XxlJobLogger.log("beat at:" + i);
			// TimeUnit.SECONDS.sleep(2);
		}
		return ReturnT.SUCCESS;
	}

}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值