项目
spring boot
问题
1:项目中的定时任务可以动态修改运行的时间。
2:项目部署在多台服务器上,且项目中有定时任务,导致如果两台服务器以相同的方式部署后定时任务会在同一时间在两台服务器上一起运行。而需求是不对项目做多余的处理以相同的方式部署后,可以实现同一时间点只有一台服务器的定时任务运行。
思路
经某度指点:动态修改运行的时间可以继承SchedulingConfigurer实现1号传送门
。定时任务在多台服务器部署且需要运行一个的问题可以使用ShedLock项目实现2号传送门。但是在整合两个方案的时候由于某度信息的陈旧,导致两个问题总是不能同时解决,这也是突发奇想要写这篇文的缘由。
经过一番波折,翻看ShedLock的官方文档3号传送门,终于明白原来是由于ShedLock的版本问题导致。ShedLock支持两种模式的Spring集成。一种是定时方法的AOP代理(PROXY_METHOD),另一种使用TaskScheduler的代理(PROXY_SCHEDULER)
两种方式各有利弊,官方文档有说明。对于我的这两个问题,只适合V4.0.0之后新增的PROXY_METHOD这种代理模式。
好了,一切就都清楚了,剩下就是码代码的问题了。
代码
pom.xml 文件增加依赖,一定要使用shedlock 4.0 以后的版本:
<dependency>
<groupId>net.javacrumbs.shedlock</groupId>
<artifactId>shedlock-spring</artifactId>
<version>4.1.0</version>
</dependency>
<dependency>
<groupId>net.javacrumbs.shedlock</groupId>
<artifactId>shedlock-provider-jdbc-template</artifactId>
<version>4.1.0</version>
</dependency>
<!-- 以及其他 spring框架所需的数据源、Mybatis 等依赖 -->
.......
使用shedlock实现多台服务器部署定时任务只运行一个的代码:
@Component
public class CronJob{
@SchedulerLock(name = "scheduledTask", lockAtMostFor = "3000", lockAtLeastFor = "2000")
public void scheduledTask() {
System.out.println(new Date() + "scheduledTask执行1次");
}
}
继承SchedulingConfigurer实现动态修改定时的代码:
@Configuration
@EnableScheduling
public class CompleteScheduleConfig implements SchedulingConfigurer {
@Mapper
public interface CronMapper {
@Select("select cron from cron limit 1")
String getCron();
}
@Autowired
@SuppressWarnings("all")
private CronMapper cronMapper;
//自动装配定时任务的类
@Autowired
private CronJob cronJob;
/**
* 执行定时任务.
*/
@Override
public void configureTasks(ScheduledTaskRegistrar taskRegistrar) {
taskRegistrar.addTriggerTask(
//1.添加任务内容(Runnable)
() -> cronJob.scheduledTask(),
//2.设置执行周期(Trigger)
triggerContext -> {
//2.1 从数据库获取执行周期
String cron = cronMapper.getCron();
//2.2 合法性校验.
if (StringUtils.isEmpty(cron)) {
// Omitted Code ..
}
//2.3 返回执行周期(Date)
return new CronTrigger(cron).nextExecutionTime(triggerContext);
}
);
}
}
其他代码参照上面的传送门。
最后
注意:ShedLock不是分布式调度程序!!!