Ribbon实现自定义负载均衡算法

目标:每个服务都访问5次之后再切换下一个服务

Ribbon自带的负载均衡算法:

在这里插入图片描述

  1. RoundRobinRule,轮询算法, 轮询index,选择index对应位置的Server
  2. ZoneAvoidanceRule(默认),复合判断Server所在Zone的性能和Server的可用性选择Server,在没有Zone的情况下类是轮询
  3. RandomRule,随机算法,随机选择一个Server
  4. RetryRule,对选定的负载均衡策略机上重试机制,在一个配置时间段内当选择Server不成功, 则一直尝试使用subRule的方式选择一个可用的server
  5. AvailabilityFilteringRule,过滤掉一直连接失败的被标记为circuit tripped的后端Server,并过滤掉那些高并发的后端Server或者使用一个AvailabilityPredicate来包含过滤server的逻辑,其实就就是检查status里记录的各个Server的运行状态
  6. BestAvailableRule,选择一个最小的并发请求的Server,逐个考察Server,如果Server被tripped了,则跳过
  7. WeightedResponseTimeRule,根据响应时间加权,响应时间越长,权重越小,被选中的可能性越低

自定义Ribbon负载均衡算法的注意事项:

注意:官方文档中有指出,自定义的类不能放在@ComponentScan或SpringBootApplication所扫描的当前包以及子包下,否则自定义的这个配置类将会被所有的Ribbon客户端所共享。在这里插入图片描述

实现步骤:

1、在启动器的上一级创建一个包存放自定义算法的文件
在这里插入图片描述
2、找到一个自带的负载均衡算法,以随机算法为例,将RandomRule的代码拿出来,修改一下新的文件名。自定义算法必须继承于AbstractLoadBalancerRule类

package com.demo.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 RandomRule_Test extends AbstractLoadBalancerRule {
    public RandomRule_Test() {
    }

    private int total=0;             //当前调用次数
    private int currentIndex=0;      //当前被引用的服务

    public Server choose(ILoadBalancer lb, Object key) {
        if (lb == null) {
            return null;
        } else {
            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;
                }

                //自定义的负载均衡算法
                if (total<5){
                    server=upList.get(currentIndex);
                    total++;
                }else{
                    total=0;
                    currentIndex++;
                    if (currentIndex>upList.size()-1){
                        currentIndex=0;
                    }
                    server=upList.get(currentIndex);
                }
                /*
                Ribbon自带的一个获取随机Server的算法
                int index = this.chooseRandomInt(serverCount);
                server = (Server)upList.get(index);
                */

                if (server == null) {
                    Thread.yield();
                } else {
                    if (server.isAlive()) {
                        return server;
                    }

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

            return server;
        }
    }

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

    public Server choose(Object key) {
        return this.choose(this.getLoadBalancer(), key);
    }

    public void initWithNiwsConfig(IClientConfig clientConfig) {
    }
}

3、将自定义的负载均衡算法注入到Bean中,在自定义算法的文件同级创建一个配置类

package com.demo.myrule;

import com.netflix.loadbalancer.IRule;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class Rule_Test {

    @Bean
    public IRule myRule(){
    	//需要什么算法就new对应的类
        return new RandomRule_Test();
    }
}

4、在启动类中添加Ribbon注解

package com.demo.springcloud;

import com.demo.myrule.Rule_Test;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
import org.springframework.cloud.netflix.ribbon.RibbonClient;

@SpringBootApplication
@EnableEurekaClient
//name:针对哪个服务,configuration:使用什么算法类
@RibbonClient(name = "SPRINGCLOUD.PROVIDER-DEPT",configuration = Rule_Test.class)
public class DeptConsumer_80 {
    public static void main(String[] args) {
        SpringApplication.run(DeptConsumer_80.class,args);
    }
}

5、测试,将7001端口的服务注册中心启动,然后启动8001,8002,8003以及80端口的负载均衡微服务,在访问80负载均衡客户端请求时,每次刷新的结果都是按照我们写的这个负载均衡算法去执行,就算达成效果了


版权声明:本文为nov4th原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。