广告公司网站制作,想建书画网站怎么做的,alexa,博客移动端网站模板一、引言 作者的平台项目最近需要实现一个功能#xff0c;用户可选择这个任务什么时候执行#xff0c;执行频率是什么#xff1f; 这其实就是一个定时任务#xff0c;只不过需要动态的#xff0c;让用户自由选择。
二、原生实现 要实现这样的功能#xff0c;可以直接依赖…一、引言 作者的平台项目最近需要实现一个功能用户可选择这个任务什么时候执行执行频率是什么 这其实就是一个定时任务只不过需要动态的让用户自由选择。
二、原生实现 要实现这样的功能可以直接依赖现有的中间件比如作者就是使用qConfigqSchedule实现的。但是在这之前作者是想要原生的去实现毕竟要调研很麻烦另外各位读者使用框架不一定支持。 那么我们看看原生的需要怎么实现。首先需要定一下方案一般的定时任务要么通过消息mq、netty、http等通知要么直接客户端起一个线程不断轮训随时通知需要执行的任务代码 既然做原生的不依赖任何外部那就本地起个定时线程不断跑看哪些任务需要跑了把他们丢进线程池 1、首先用户可选的话就要让用户可以填一个cron表达式或者直接在配置文件里面加好各种选项比如1分钟一次、30分钟一次、一小时一次等等展示给用户的是文字配置文件里面文字是描述实际上的key是cron表达式。
SCHEDULE_LIST[{code: 0 */15 * ? * *, name: 每15分钟运行一次},
{code: 0 0 * ? * *, name: 每小时运行一次},
{code: 0 0 0 ? * *, name: 每天运行一次},
{code: FALSE, name: 不执行}] 2、在任务表里面要有个字段放这个cron表达式 3、启动一个定时任务
Scheduled(fixedRate 1000*60) public void schedule() {handle();} 4、在定时任务里面把需要执行的数据扔到线程池 这里需要注意由于定时轮训的通知机制和处理速度不管原生还是使用中间件都是有可能导致一定误差的这个误差可以做成配置作者认为几万的数据量的话也就是前后三秒左右 所以这里还需要没有五秒以内的定时任务正常也没有哪些任务需要那么高的频率一般都是一分钟以上的 public void handle() {
// 查询所有任务数据
ListTask tasks queryTask();
for (Task task : tasks) {doHandle(task);
}
}public void doHandle(Task task) {String cronExpression task.getCron();Date now new Date();CronExpression cron new CronExpression(cronExpression);Date nextExecutionTime cron.getNextValidTimeAfter(now);Date previousExecutionTime cron.getPreviousValidTimeBefore(now);Date fiveSecondsBefore new Date(now.getTime() - 5000);Date fiveSecondsAfter new Date(now.getTime() 5000);if ((nextExecutionTime.after(fiveSecondsBefore) nextExecutionTime.before(fiveSecondsAfter))|| (previousExecutionTime.after(fiveSecondsBefore) previousExecutionTime.before(fiveSecondsAfter))) {doExecute(task);}
}
三、优化 这里也能看到上面还是有一些优化空间的比如以下几点
1、查询耗时 查数据库的任务再去判断是否执行数量量不大还好多了的话真是又占内存要耗时间可以做一层缓存把任务的id和cron表达式存储在本地然后由快速的做内存遍历投入到线程池之后再去查明细 就是io会高一点但是同一个时间执行的任务本身就不会很多除非做的是集团那种规模的定时任务几十万那种基本没必要因为能用中间件各位读者自己就用了直接看第四章好了
2、批量执行 判断这个任务的cron是否可以执行是非常快的所以没必要一个个判断再投入线程池完全可以20个一批投进去根据执行情况调整批次数量
ListListTask batches Lists.partition(tasks, batchSize);for (ListTask batch : batches) {doHandle(batch);
} 四、依赖框架 作者使用的是QSchedule和QConfig的组合主要是把定时任务给放在配置中心之后需要qschedule去拉取然后生成对应的定时任务。 QSchedule是集团内部使用的定时任务和集团的配置中心紧密结合用起来很方便配置好之后代码加个注解就行了JobList.t就是配置中心文件的名字
QScheduleList(jobList.t)public void scheduleHandle(Parameter parameter) {handleSchedule(parameter.getJobName());} 不过QSchedule没开源QConfig倒是开源了https://github.com/qunarcorp/qconfig 实现原理也不复杂就是注解的切面拉取配置文件再发给服务端生成定时任务服务端每次通知客户端都会把名称、拓展信息相关的都带过来根据名称再去数据库拉取要执行的任务。 减少了判断和多次的数据库io而且定时任务有管理机制可用性高。
五、总结 最小成本的快速实现需要根据自身环境有成型的框架就直接用没有自己写一个也不复杂。