【Ribbon】负载均衡策略

这是我参与更文挑战的第12天,活动详情查看:更文挑战

一、前言

内置负载均衡策略,如图:

2020-11-3015-11-37.png

Ribbon 作为一款优秀的客户端负载均衡框架,内置了很多经典实用的算法,可以直接拿来用。

这里介绍几个比较常用的:

IRule 是算法的接口。

AbstractLoadBalancerRule 是实现了 IRule 接口的抽象类,所有内置的算法都是继承 AbstractLoadBalancerRule 来实现的。

  1. RoundRobinRule 是轮询的算法,如果有 A、B 两个实例,那么该算法的逻辑是选择 A,再选择B,再选择A,轮询下去。

  2. RandomRule 是随机算法,这个就比较简单了,在服务列表中随机选取。

  3. BestAvailableRule 选择一个最小的并发请求 server

    如果有 A、B 两个实例,当 A 有 4 个请求正在处理中,B 有 2 个请求正在处理中,下次选择的时候会选择 B,因为 B 处理的数量是最少的,认为它压力最小,这种场景适合于服务所在机器的配置都相同的情况下,否则不太适用。

  4. WeightedResponseTimeRule 算法

    原理是根据请求的响应时间计算权重,如果响应时间越长,那么对应的权重越低,权重越低的服务器,被选择的可能性就越低。

    在某些场景下,服务器的性能不一致,如果采用轮询算法或随机算法的话,无法充分的利用服务器的资源,某些服务器处理的快,应该多分配一些请求,某些服务器处理的慢,就可以少分配一些请求。

二、自定义负载均衡算法

实现步骤:

  1. 实现 Irule 接口 或 继承 AbstractLoadBalancerRule
  2. 实现 choose 方法
  3. 指定 Ribbon 的算法类
// 1. 实现 Irule 接口
public class MyRule implements IRule {
    ILoadBalancerr balancer;
    public MyRule() {
    }
    public MyRule(ILoadBalancer balancer) {
        this.balancer = balancer;
    }

    // 2. 实现 choose 方法
    public Server choose(Object key) {
        List<Server> servers = balancer.getAllServers();
        return servers.get(0);
    } 
}

// 3. 指定 Ribbon 的算法类
ILoadBalancer balancer = new BaseLoadBalancer();
balancer.setRule(new MyRule(balancer));
List<Server> servers = new ArrayList<Server>();
servers.add(new Server("localhost", 8080));
servers.add(new Server("localhost", 8088));
balancer.addServers(servers);

for(int i = 0; i < 10; i++) {
    Server server = balancer.chooseServer(null);
    System.out.println(server);
}
复制代码

三、使用场景

  1. 定制跟业务更匹配的策略

这点是在开发过程中相关度比较大的,就是某些场景可能更适合轮询算法,但是单纯的轮询算法可能不是你想要的,这个时候就需要在轮询的基础上,加上一些你自己的逻辑,组成一个新的算法,让 Ribbon 使用这个算法来进行服务实例的选择。

  1. 灰度发布

灰度发布是能够平滑过渡的一种发布方式,在发布过程中,先发布一部分应用,让指定的用户使用刚发布的应用,等到测试没有问题后,再将其他的全部应用发布。如果新发布的有问题,只需要将这部分恢复即可,不用恢复所有的应用。

  1. 多版本隔离

多版本隔离跟灰度发布类似,为了兼容或者过度,某些应用会有多个版本,这个时候如何保证 1.0 版本的客户端不会调用到 1.1 版本的服务,就是我们需要考虑的问题。

  1. 故障隔离

当线上某个实例发生故障后,为了不影响用户,一般都会先留存证据,比如:线程信息、JVM 信息等,然后将这个实例重启或直接停止。
然后线下根据一些信息分析故障原因,如果我能做到故障隔离,就可以直接将出问题的实例隔离,不让正常的用户请求访问到这个出问题的实例,只让指定的用户访问,这样就可以单独用特定的用户来对这个出问题的实例进行测试、故障分析等。

上面这 4 种场景在实际工作中是非常有用的,特别是在面试过程中,如果你能详细的说出怎么去实现这些场景,绝对是大的加分项。

那么这 4 个场景跟 Ribbon 有什么关系呢?

首先能自定义负载均衡算法,也就表示我们可以控制 Ribbon 的服务选择,Ribbon 选择出的服务信息是要进行接口交互的,比如说我想要实现故障隔离,就得不让正常的请求调用到这个出问题的实例,在策略中将这个出问题的实例过滤,这样选择出来的实例就不会是出故障的那个。