前言

  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 upList = lb.getReachableServers(); //获取可利用的服务

List 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 方法,利用这个原理就可以实现自己的负载均衡策略了。

参考文章

评论可见,请评论后查看内容,谢谢!!!
 您阅读本篇文章共花了: