临近年关,招聘的和找工作的却忙的热火朝天,互相拿捏着。
今朝不同往昔,卖惨成为主流旋律,也加剧了从业人员的焦虑。很多人,工作了十来年没碰过算法,如今却不得不像蹲自习室一样,捧起大头书死命去看。
呜呼哀哉。
最近和不少参加面试的小伙伴交流了一下,发现出现了一个比较高频的算法题。不同于链表、树、动态规划这些有规律可循的算法题,加权轮询算法有很多小的技巧,在实际应用中也比较多。最平滑的Nginx轮询算法,如果你没有见过的话,那自然是永远无法写出来的。
所谓的加权轮询算法,其实就是Weighted Round Robin,简称wrr。在我们配置Nginx的upstream的时候,带权重的轮询,其实就是wrr。
upstream backend {
ip_hash;
server 192.168.1.232 weight=4;
server 192.168.1.233 weight=3;
server 192.168.1.234 weight=1;
}
复制代码
1. 核心数据结构
为了方便编码,对于每一个被调度的单元来说,我们抽象出一个叫做Element的类。其中,peer
指的是具体的被调度资源,比如IP地址,而weight
指的是这个资源的相关权重。
public class Element {
protected String peer;
protected int weight;
public Element(String peer, int weight){
this.peer = peer;
this.weight = weight;
}
}
复制代码
那么我们具体的调度接口,将直接返回peer的地址。
public interface IWrr {
String next();
}
复制代码
我们将在代码中直接测试IWrr接口的调度情况。比如,分配7、2、1权重的三个资源,其测试代码如下。
Element[] elements = new Element[]{
new Element("A", 7),
new Element("B", 2),
new Element("C", 1),
};
int count = 10;
IWrr wrr = new WrrSecurityLoopTreeMap(elements);
for (int i = 0; i < count; i++) {
System.out.print(wrr.next() + ",");
}
System.out.println();
复制代码
上面的代码调用了10次接口,我们希望代码实现,将以7,2,1的比例进行调度。