一、介绍
在本调度平台中,将以job为单位进行优先级设定,为什么要进行优先级设定呢?
举个例子: 一小时前用户A下发了100个病毒检测应用程序的任务,而现在突然想尽快检测新拥有的50个应用,但之前的100个检测任务并未完全执行完,如果不设置优先级,则新下发的50个任务进行排队,等待上一次100个应用程序检测完成后再进行检测。
如果设置了优先级,则每个节点会获取优先级高的任务,再提交给引擎进行检测,这样就实现了所谓“插队”的功能。
二、新调度平台优先级队列设计思路:
任务下发的队列图如下,我们对其中的两条priorityTaskQueue以及distributeTaskQueue进行了优先级化。需要注意的是,两条队列实现优先级的方法并不相同,前者使用的是java自带的“PriorityBlockingQueue”,而后者使用的是activemq的优先级方法。在下文我们会分别对两种方法的实现进行讲解。
三、实现
1、优先级标识
在YYSchedule中,我们自定义了任务类Task,在这个类中,有一个参数JobPriority,这个参数就是任务的优先级。
其中JobPriority是通过thrift生成,核心代码如下:
public enum JobPriority implements org.apache.thrift.TEnum {
HIGHER(9),
HIGH(6),
MEDIUM(4),
LOW(2),
LOWER(0);
}
之所以设置0 2 4 6 9这五个值,是为了和JMS的优先级对应。
2、priorityTaskQueue的优先级实现
priorityTaskQueue使用的是java自带的“PriorityBlockingQueue”,其存储的是自定义类Task:
private PriorityBlockingQueue<Task> priorityTaskQueue = new PriorityBlockingQueue<Task>();
使用PriorityBlockingQueue有一个前提:PriorityBlockingQueue里面存储的对象必须是实现Comparable接口。队列通过这个接口的compare方法确定对象的priority。
规则是:当前和其他对象比较,如果compare方法返回负数,那么在队列里面的优先级就比较高。也就是说,值越小优先级越大,注意这个与平时的习惯是相反的。
因此我们在Task.java这个javaBean中实现了Comparable,并实现了compareTo方法,代码如下:
@Override
public int compareTo(Task task) {
if (task != null && task.getTaskId() != 0L && task.getTaskId().equals(taskId)) {
return 0;
}
if (taskPriority.getValue() == task.getTaskPriority().getValue()) {
return -(Long.valueOf(loadedTime).compareTo(task.getLoadedTime()));
}
return -(Integer.valueOf(taskPriority.getValue()).compareTo(task.getTaskPriority().getValue()));
}
通过这种方法,我们便可以实现priorityTaskQueue的优先级。
3、distributeTaskQueue的优先级实现(activemq)
在spring集成activemq时,jmsTemplate提供了setPriority方法,最高为9,最低为0,数值越高优先级越高。
但需要注意的是,若想使用优先级功能,必须先设置ExplicitQosEnabled为true,也就是jmsTemplate.setExplicitQosEnabled(true);
具体实现代码请见我的另一篇博客:《调度平台YYSchedule-细节-activemq的使用》