SpringCloud-Netflix学习笔记08——自定义Ribbon负载均衡策略

前言

在这里插入图片描述
  Ribbon默认的负载均衡策略是轮询,其实Ribbon还自带了其他的负载均衡策略,可以进行选择,有如下几种:

	实现接口:IRule
    不同实现类:
    * 1、AvailabilityFilteringRule:会先过滤掉跳闸的或者访问故障的服务,对剩下的服务进行轮询~
    * 2、RoundRobinRule:轮询(默认是这种策略)~
    * 3、RandomRule:随机~
    * 4、WeightedResponseTimeRule:按照分配的权重进行分配
    * 5、RetryRule:会先按照轮询获取服务,如果服务获取失败,则在指定的时间内进行重试~
    

  我们想要切换负载均衡策略的话,只需要将该策略注入Spring即可,会覆盖掉默认的轮询策略,如下:

	@Bean
    public IRule myRule(){
        return new RandomRule(); //使用随机策略
    }

  当然关于Ribbon的配置不应该在ConfigBean中配置,ConfigBean只是用来配置RestTemplate的,我们新建一个 myrule 包,在包中新建一个类 TangRule 来配置Ribbon。目录结构如下:

在这里插入图片描述

@Configuration
public class TangRule {  //关于Ribbon负载均衡策略的配置

    //实现接口:IRule
    /*不同实现类:
     * 1、AvailabilityFilteringRule:会先过滤掉跳闸的或者访问故障的服务,对剩下的服务进行轮询~
     * 2、RoundRobinRule:轮询(默认是这种策略)~
     * 3、RandomRule:随机~
     * 4、WeightedResponseTimeRule:按照分配的权重进行分配
     * 5、RetryRule:会先按照轮询获取服务,如果服务获取失败,则在指定的时间内进行重试~
     * */

    @Bean
    public IRule myRule(){
        return new RandomRule();
    }

}

  重新启动之后,就是用的随机策略了。

自定义Ribbon负载均衡策略

  仿照官方的代码,自定义一个负载均衡策略。

  首先在myrule包中新建一个类 TangRandomRule ,继承 AbstractLoadBalancerRule 父类,我们要实现的负载均衡策略如下:

每一个服务访问5次,换下一个服务,循环往复

  AbstractLoadBalancerRule 类代码如下:

package com.tang.myrule;

import com.netflix.client.config.IClientConfig;
import com.netflix.loadbalancer.AbstractLoadBalancerRule;
import com.netflix.loadbalancer.ILoadBalancer;
import com.netflix.loadbalancer.Server;

import java.util.List;
import java.util.concurrent.ThreadLocalRandom;

//启动之后之后加载一次这个类
public class TangRandomRule extends AbstractLoadBalancerRule {

    //每一个服务访问5次,换下一个服务

    private int count = 0;
    private int total = 0;

    //@edu.umd.cs.findbugs.annotations.SuppressWarnings(value = "RCN_REDUNDANT_NULLCHECK_OF_NULL_VALUE")
    //每次刷新都会进入这个方法,返回一个服务
    public Server choose(ILoadBalancer lb, Object key) {
        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;
            }
            int availableCount = upList.size();  //可利用服务的数量
            if(availableCount == 0){
                return null;
            }

            server = upList.get(total);
            if(server == null){
                Thread.yield();  //跳过本次线程
                continue;
            }

            if(server.isAlive()){
                count++;
                if(count == 5){
                    total++;
                    count = 0;
                    if(total == availableCount)
                        total = 0;
                }

                //System.out.println("count:" + count);
                //System.out.println("total:" + total);
                return server;
            }



            /*int index = chooseRandomInt(serverCount); //在全部服务中随机选取一个服务下标
            server = upList.get(index); //在可用的服务中拿出这个随机选取的服务*/

            /*if (server == null) { //可用服务中没有这个服务
                Thread.yield();  //跳过本次线程
                continue;
            }

            if (server.isAlive()) { //可用服务中包含这个服务
                return (server);  //返回这个服务(访问)
            }*/

            server = null;
            Thread.yield();
        }

        return server;

    }

    protected int chooseRandomInt(int serverCount) {
        return ThreadLocalRandom.current().nextInt(serverCount);
    }

	@Override
	public Server choose(Object key) {
		return choose(getLoadBalancer(), key);
	}

	@Override
	public void initWithNiwsConfig(IClientConfig clientConfig) {
		// TODO Auto-generated method stub
		
	}
}

  接着在 TangRule 中注入我们的策略覆盖掉默认的轮询策略即可。

@Configuration
public class TangRule {  //关于Ribbon负载均衡策略的配置

    //实现接口:IRule
    /*不同实现类:
     * 1、AvailabilityFilteringRule:会先过滤掉跳闸的或者访问故障的服务,对剩下的服务进行轮询~
     * 2、RoundRobinRule:轮询(默认是这种策略)~
     * 3、RandomRule:随机~
     * 4、WeightedResponseTimeRule:按照分配的权重进行分配
     * 5、RetryRule:会先按照轮询获取服务,如果服务获取失败,则在指定的时间内进行重试~
     * */

    @Bean
    public IRule myRule(){
        return new TangRandomRule();
    }

}

  需要注意的是,在服务启动时会加载一次这个类,而每次刷新都会重新执行 choose 方法,利用这个原理就可以实现自己的负载均衡策略了。

posted @   爱吃雪糕的小布丁  阅读(18)  评论(0编辑  收藏  举报  
相关博文:
阅读排行:
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· C#/.NET/.NET Core优秀项目和框架2025年2月简报
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 【杭电多校比赛记录】2025“钉耙编程”中国大学生算法设计春季联赛(1)
点击右上角即可分享
微信分享提示