详解xxl-job任务调度平台的路由方式

3,132 阅读3分钟

一.xxl-job简介

xxl-job是一款轻量级的分布式任务调度平台,因为其开源,简单,易扩展等特点,被很多IT企业使用。我司的产品线也是使用了xxl-job作为任务调度平台,所以我最近仔细拜读了xxl-job的源码,受益匪浅,今天给大家分享下,任务调度平台的路由方式。

二.几种路由方式

详解xxl-job任务调度平台的路由方式

三.路由策略剖析

轮询:例如我们有5个执行的实例,从1到5依次执行一次,而后循环往复即可。 实现也非常简单,定义一个变量,执行一次加1,取模确定机器编号。 因为我们有多个job,每个job都要存一下执行次数,代码中使用 ConcurrentMap<Integer, Integer>来存储jobId和执行次数的映射关系。

随机:每次随机决定哪台机器执行。

一致性Hash:对每个机器的地址进行md5加密,取32位hash值,以hash值作为key,地址 作为value放入到TreeMap中。同样对jobId也进行Md5加密取hash值,利用TreeMap 的tailMap(jobHash)方法,获取到等于或大于jobHash的那部分Map视图,取视图的第一个key对应的value作为路由地址,如果视图为空,则取TreeMap的第一个值。

最不经常使用:在一段时间内,使用次数最少的机器会被选择出来。代码中设定的时间区间为一天,一个任务使用一个HashMap<String, Integer>来记录一天内机器使用的次数,一天之后,次数清零。每次选择机器的时候,按使用次数正序排列,取第一个机器执行任务。

最近最久未使用:充分利用LinkedHashMap按照插入先后顺序进行排列这一特点,
LinkedHashMap 保存了机器的插入顺序,算法每次都会循环尝试将机器地址放入到LinkedHashMap中,如果机器地址已经在Map中,不会放入。这样在用Iterator遍历LinkedHashMap时,先得到的记录肯定是最早插入的。我们看下代码:

//lruItem为LinkedHashMap类型,拿到第一条数据
String eldestKey = lruItem.entrySet().iterator().next().getKey();
//LinkedHashMap的put和get方法会将这个Entry放到双向链表的末尾
String eldestValue = lruItem.get(eldestKey);

使用过的,会放到双向链表的最后面,这样保证了每次使用的都是最久没用过的。
故障转移: 会逐个机器发送心跳,心跳正常的机器才会被选中
忙碌转移: 会逐个机器调用idleBeat接口,如果该任务正在机器中执行,或在队列中,那么就跳过该机器寻找不繁忙的机器执行任务。
LinkedHashMap 是HashMap的一个子类,保存了记录的插入顺序,在用Iterator遍历LinkedHashMap时,先得到的记录肯定是先插入的.

分片广播: 所有的机器都会触发任务,每个机器可以根据分片号,执行任务的一部分。

第一个和最后一个:这两种路由方式最简单,固定第一台机器或者最后面的机器执行,always you,认定你,吃定你。

image.png