分布式任务调度

1 任务调度

定时JOB,在什么时间进行执行代码任务。

1.1 使用线程方式

public static void main(String[] args) {
		Runnable runnable = new Runnable() {
			@Override
			public void run() {
				while (true) {
					try {
						Thread.sleep(1000);
						count++;
						System.out.println(count);
					} catch (Exception e) {
						// TODO: handle exception
					}
				}
			}
		};
		Thread thread = new Thread(runnable);
		thread.start();
	}

1.2 timerTask

public static void main(String[] args) {
		TimerTask timerTask = new TimerTask() {

			@Override
			public void run() {
				count++;
				System.out.println(count);
			}
		};
		Timer timer = new Timer();
		// 天数
		long delay = 0;
		// 秒数
		long period = 1000;
		timer.scheduleAtFixedRate(timerTask, delay, period);
	}

1.3 线程池

	public static void main(String[] args) {
		Runnable runnable = new Runnable() {
			public void run() {
				// task to run goes here
				System.out.println("Hello !!");
			}
		};
		ScheduledExecutorService service = Executors.newSingleThreadScheduledExecutor();
		// 第二个参数为首次执行的延时时间,第三个参数为定时执行的间隔时间
		service.scheduleAtFixedRate(runnable, 1, 1, TimeUnit.SECONDS);
	}

1.4 quartz

依赖:

        
            org.quartz-scheduler
            quartz
            2.2.1
        
        
            org.quartz-scheduler
            quartz-jobs
            2.2.1
        

任务:

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

启动类:

    public static void main(String[] args) throws SchedulerException {
        //1、创建scheduler的工厂
        StdSchedulerFactory stdSchedulerFactory = new StdSchedulerFactory();
        //2、从工厂中获取调度器实例
        Scheduler scheduler = stdSchedulerFactory.getScheduler();
        //3、创建JobDetail
        JobDetail jobDetail = JobBuilder.newJob(JobTask.class)
                .withDescription("this is a quartz job")
                .withIdentity("quartzJob", "quartzGroup")
                .build();
        //任务运行的时间、simpleSchedule类型触发器有效
        long time=System.currentTimeMillis()+5*1000;//5秒后
        Date startTime=new Date(time);
        //创建trigger
        //使用SimpleScheduleBuilder或者CronScheduleBuilder
        Trigger trigger = TriggerBuilder.newTrigger()
                .withDescription("quartz trigger")
                .withIdentity("quartzTrigger", "quartzTriggerGroup")
                .startAt(startTime)
                .withSchedule(CronScheduleBuilder.cronSchedule("0/2 * * * * ?"))
                .build();
        //5、注册任务和定时器
        scheduler.scheduleJob(jobDetail,trigger);
        //启动
        scheduler.start();
    }

2 分布式任务调度

虽然以上是可以实现任务调度,但是一般情况下这个应用是要部署在多个tomcat服务器上的,那么又怎么保证幂等性(对于一个job,不可能每台服务器都让他执行一次嘛,这不就重复执行了吗)呢。

1、使用分布式锁,保证只有一台服务器在执行

2、添加配置文件标识,两台服务器的配置文件不同,根据配置文件不同进行任务的调度,缺点是,那这就不支持集群 了。

3、数据库唯一标识,比如根据某一字段为TRUE标识可以执行,执行时改为FALSE,执行完后再改为TRUE,缺点是经常操作数据库,效率低

4、使用分布式任务调度平台XXLJOB

总的来说传统的任务调度有很多缺点:

1、没有补偿机制(比如某个任务调度失败后,只能等待下次调度或者人工调度)

2、不支持集群

3、不支持路由策略

4、统计(每个服务或者项目都有自己的任务调度,肯定是要统计一些成功啊失败什么的,传统调度的话只能自己管理自己的,可是这种任务调度的话最好是采用集中管理比较好)

5、管理平台(没有提供一个集中管理所有任务调度的平台)

6、报警邮箱(比如说重试N次以后,都不成功那就发疯邮件吧)、状态监控(运行、结束、等待)

而以上这些在分布式调度平台XXLJOB都有支持。

2.1 XXL-JOB执行原理

分布式任务调度_第1张图片

首先对于任何一个客户端的任务,需要注册到xxl-job的admin平台,然后admin将任务分发到各个执行器去执行,这里选择每个执行器的原理类似负载均衡策略。

实战演练一下:

1、首先下载XXL-JOB

2、使用开发工具eclipse或者idea导入该项目

3、找到master/doc下的数据库文件导入数据库比如xx-job

4、修改配置文件xxl-job-admin.properties中数据库的链接地址和密码,这里如果有自己搭建邮箱服务器也可填写邮箱服务器等信息

5、将该项目部署到tomcat服务器进行启动,访问http://127.0.0.1:8081/,输入密码用户名(默认admin,123456)

6、在web页面中新建执行器以及任务

7、根据他提供的一些例子比如spring boot的,导入他的依赖以及配置文件这些信息到自己的项目中

8、填写好admin部署的项目地址,这点很重要,指定执行器名称、ip、端口、以及日志文件路径

9、记住XxlJobConfig这个配置文件一定要导入

10、新建一个Handler类似这样

/**
 * 任务Handler的一个Demo(Bean模式)
 *
 * 开发步骤: 1、继承 “IJobHandler” ; 2、装配到Spring,例如加 “@Service” 注解; 3、加 “@JobHander”
 * 注解,注解value值为新增任务生成的JobKey的值;多个JobKey用逗号分割; 4、执行日志:需要通过 "XxlJobLogger.log"
 * 打印执行日志;
 *
 * @author xuxueli 2015-12-19 19:43:36
 */
@JobHander(value = "demoJobHandler")//这个对应admin中的对应执行器中的任务的名称
@Service
public class DemoJobHandler extends IJobHandler {
	@Value("${xxl.job.executor.port}")
	private String port;

	@Override
	public ReturnT 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;
	}

}

启动项目后即可。这个是一个分布式job调度平台,可以试着启动多个项目然后添加到同一个执行器中执行,按照他的规则填好集群中的ip即可。

你可能感兴趣的:(xxl-job,Java)