【夯实Spring Cloud】Spring Cloud中自定义Ribbon负载均衡策略

版权声明:尊重博主原创文章,转载请注明出处 https://blog.csdn.net/eson_15/article/details/86578207

本文属于【夯实Spring Cloud】系列文章,该系列旨在用通俗易懂的语言,带大家了解和学习Spring Cloud技术,希望能给读者带来一些干货。系列目录如下:

【夯实Spring Cloud】Dubbo沉睡5年,Spring Cloud开始崛起!
【夯实Spring Cloud】Spring Cloud中基于maven的分布式项目框架的搭建
【夯实Spring Cloud】Spring Cloud中的Eureka服务注册与发现详解
【夯实Spring Cloud】Spring Cloud中如何完善Eureka中的服务信息
【夯实Spring Cloud】Spring Cloud中使用Eureka集群搭建高可用服务注册中心
【夯实Spring Cloud】Spring Cloud中的Eureka和Zookeeper的区别在哪?
【夯实Spring Cloud】Spring Cloud中使用Ribbon实现负载均衡详解(上)
【夯实Spring Cloud】Spring Cloud中使用Ribbon实现负载均衡详解(下)
【夯实Spring Cloud】Spring Cloud中自定义Ribbon负载均衡策略
【夯实Spring Cloud】Spring Cloud中使用Feign实现负载均衡详
【夯实Srping Cloud】Spring Cloud中使用Hystrix实现断路器原理详解(上)
【夯实Srping Cloud】Spring Cloud中使用Hystrix实现断路器原理详解(下)
【夯实Spring Cloud】Spring Cloud中使用Zuul实现路由网关详解
【夯实Spring Cloud】Spring Cloud分布式配置中心详解
【夯实Spring Cloud】未完待续


在前两篇文章中,对 Ribbon 的使用做了详细的介绍,但是使用的是 Ribbon 自带的负载均衡策略,那么 Ribbon 是否可以根据实际情况,自定义负载均衡策略呢?答案是肯定的,这一篇文章主要来介绍一下 Ribbon 如何自定义负载均衡策略。

1. 主启动类处理

还是使用上一节的客户端代码,先回忆一下相关内容:三个订单服务提供者,服务名称叫:MICROSERVICE-ORDER,端口分别为 8001、8002 和 8003。Eureka 集群三个服务,端口分别为 7001、7002 和 7003。

上一节主要是使用 Ribbon 的轮询和随机策略,来测试负载均衡。这一节我们自定义一个策略。首先要在启动类中添加 @RibbonClient 注解,如下:

@SpringBootApplication
@EnableEurekaClient
@RibbonClient(name = "MICROSERVICE-ORDER", configuration = MyRuleConfig.class)
public class OrderConsumer {

    public static void main(String[] args) {
        SpringApplication.run(OrderConsumer.class, args);
    }
}

name 用来指定需要均衡的服务,即三个订单服务,configuration 用来指定所用的策略配置,这里使用我们自定义的一个配置 MyRuleConfig。接下来,我们来定义这个配置。

2. 自定义配置

这个配置的位置有个地方需要注意:就是所在的包不能和主启动类在同一个包下面,这是官方文档提到的注意事项。所以我们自己新建一个和主启动类所在的包同级的包,然后写 MyRuleConfig。

/**
 * 自定义规则
 * @author shengwu ni
 */
@Configuration
public class MyRuleConfig {
    @Bean
    public IRule myselfRule() {
        // 指定策略:我们自定义的策略
        return new CustomRule();
    }
}

3. 自定义策略

OK,接下来就是实现这个自定义策略:CustomRule了。我们假设自己定义的策略如下:

还是按照轮询的方式来选择服务,但是每个被轮询到的服务,接下来访问4次(默认是1次),4次访问完之后,再切换到下一个服务,访问4次,以此类推。

拿到这个需求之后,我们需要改写策略了,根据官方 github 源码可以知道,类似于轮询、随机这种策略,都是继承了 AbstractLoadBalancerRule 类,然后重写 choose 方法。所以,自定义策略分两步走:

  1. 实现 AbstractLoadBalancerRule 类
  2. 重写 choose 方法

我先把代码复制一下,然后来分析一下:

/**
 * 自定义规则
 * @author shengwu ni
 */
public class CustomRule extends AbstractLoadBalancerRule {

    /**
     * 总共被调用的次数,目前要求每台被调用4次
      */
    private int total = 0;
    /**
     * 当前提供服务列表的索引
     */
    private int currentIndex = 0;

    @Override public void initWithNiwsConfig(IClientConfig iClientConfig) {
    }

    /**
     * 在choose方法中,自定义我们自己的规则,返回的Server就是具体选择出来的服务
     * 自己的规则:按照轮询的规则,但是每个被轮询到的服务调用5次。
     * @param o
     * @return
     */
    @Override public Server choose(Object o) {
        // 获取负载均衡器lb
        ILoadBalancer lb = getLoadBalancer();
        if (lb == null) {
            return null;
        }

        Server server = null;
        while (server == null) {
            if (Thread.interrupted()) {
                return null;
            }
            // 获取可用服务列表
            List<Server> upList = lb.getReachableServers();
            // 获取所有服务列表
            List<Server> allList = lb.getAllServers();
            int serverCount = allList.size();
            if (serverCount == 0) {
                return null;
            }

            // 若调用次数小于4次,一直调用可用服务列表中索引为 currentIndex 的服务
            if(total < 4)
            {
                server = upList.get(currentIndex);
                total++;
            } else {
                // 到了4次之后,服务列表中的索引值++,表示下一个调用下一个服务
                total = 0;
                currentIndex++;
                // 当索引大于可用服务列表的size时,要重新从头开始
                currentIndex = currentIndex % upList.size();

                if (server == null) {
                    Thread.yield();
                    continue;
                }

                if (server.isAlive()) {
                    return (server);
                }

                server = null;
                Thread.yield();
            }
        }
        return server;
    }
}

我来简单分析一下代码:首先获取 ILoadBalancer 对象,该对象可以获取当前的服务。我们需要获取当前可用的服务列表和当前所有的服务列表。

total 表示服务被调用的次数,到4次,该服务调用停止,切换到下一个可用服务;currentIndex 表示当前可用服务列表中的索引。若调用次数小于4次,一直调用可用服务列表中索引为 currentIndex 的服务,到了4次之后,服务列表中的索引值++,表示下一个调用下一个服务。具体可以看代码中的注释。

4. 测试一下

OK,到这里,自定义的负载均衡策略就完成了,我们启动三个 eureka 集群和三个订单服务提供者,然后启动消费方客户端(端口9001),然后仍然在浏览器输入:http://localhost:9001/consumer/order/get/1 来测试一下即可。

正常情况:当前订单提供服务会被调用四次,然后切换到另一个订单服务,轮流切换。


源码下载地址:https://gitee.com/eson15/springcloud_study
更多优质文章请关注我的微信公众号【程序员私房菜】,回复“资源”和“架构”可以领取优质的视频学习资源。
程序员私房菜

没有更多推荐了,返回首页