公司成立派单组,来完成派单类需求任务。刚开始派单组没有人员,新任务到来,招聘人员A来完成。突然又来了一个新任务,发现派单组唯一的小伙伴A还在处理手头的活儿,于是再招聘一个小伙伴B,来完成新提交的任务。A和B先后完成了自己的任务后,这时候第三个任务来了,发现有空闲状态的小伙伴A和B,于是让A接受新任务。第四个任务持续没有到来,B伙伴一直处于闲置状态,公司为节省成本于是解雇了B。刚解雇B,第四个任务就来了,A抽不出身,于是只能重新招聘C来完成新任务。周而复始,员工和任务都是进进出出。
某一天,公司突然发现任务是可以分类的,无状态的随机下发(并非随机,事实上是谁先空闲分发给谁),总体完成效率可能并不高,于是想从派单组抽出一个人A(最先空闲的),专门给他指派一些关联任务,A先后完成了任务1,2,3,4后,公司决定释放这个人员A,A又回归原来的工作状态。后来又有同样类似的任务包,碰巧还是从派单组抽调出了A,但A正在进行手头任务的时候公司业务调整项目黄了,同样公司也可以释放人员A,手头的任务被取消,A又回归原来的工作状态。
在这个场景中,注意一点是所有的人员都是无状态的,公司在选调人的时候,永远只能选择最早空闲的(无则招新员工),为了公平体现,不能抽派具体指定的人员。这些人员的薪资待遇,工作态度,工作能力是完成一样的。
上面讲的这个工作场景,其实正是Reactor中ElasticScheduler实现的功能(ElasticScheduler优先选择最后空闲入队的,与上述恰好相反)。在下面的源码剖析中,可以结合着上述的工作场景来理解ElasticScheduler的工作机制。
Scheduler
public interface Scheduler extends Disposable {
//提交任务
Disposable schedule(Runnable task);
//抽调员工
Worker createWorker();
//---省略----//
interface Worker extends Disposable {
//员工执行任务
Disposable schedule(Runnable task);
//--省略--//
}
}
ElasticScheduler类实现了Scheduler,是一个调度器,在上面的场景中,可以理解成派单组,我们从创建派单组开始撸源码。
static final Supplier<Scheduler> ELASTIC_SUPPLIER =
() -> newElastic(ELASTIC, ElasticScheduler.DEFAULT_TTL_SECONDS, true);
public static Scheduler elastic() {
return cache(CACHED_ELASTIC, ELASTIC, ELASTIC_SUPPLIER);
}
static CachedScheduler cache(AtomicReference<CachedScheduler> reference, String key, Supplier<Scheduler> supplier) {
CachedScheduler s = reference.get();
if (s