暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

【SpringCloud】SpringCloud Ribbon的核心组件IRule

灵动思维文化传媒 2018-12-13
551

点击上方"蓝字", 右上角选择“设为星标”

 周一至五早8点半!精品技术文章准时送上!



一、前言


上篇文章我们介绍了SpringCloud的负载均衡组件Ribbon的基础理论以及完成服务消费方是如何通过Ribbon实现负载均衡的具体操作配置。具体详情参见《【SpringCloud】SpringCloud Ribbon负载均衡》。


本篇内容我们还是讲一讲Ribbon的一个核心的组件IRule。


二、IRule的七种算法


前面我们说到Ribbon会自动的帮助你基于某种规则(如简单轮询随机连接等)去连接服务提供方得到机器,而IRule就是制定Ribbon要用什么样的规则来实现负载均衡的。


简单的说:IRule就是根据特定算法中从服务列表中选取一个要访问的服务。而默认采用轮询算法。

IRule主要有七中已经制定好的算法:

  • RoundRobinRule  轮询


  • RandomRule  随机


  • RetryRule

    先按照RoundRobinRule的策略获取服务,如果获取服务失败则在指定时间内会进行重试,获取可用的服务


  • AvailabilityFilteringRule  

    会先过滤掉由于多次访问故障而处于断路器跳闸状态的服务,还有并发的连接数量超过阈值的服务,然后对剩余的服务列表按照轮询策略进行访问


  • WeightedResponseTimeRule

    根据平均响应时间计算所有服务的权重,响应时间越快服务权重越大被选中的概率越高。刚启动时如果统计信息不足,则使用RoundRobinRule策略,等统计信息足够,会切换到WeightedResponseTimeRule


  • BestAvailableRule

    会先过滤掉由于多次访问故障而处于断路器跳闸状态的服务,然后选择一个并发量最小的服务


  • ZoneAvoidanceRule

    默认规则,复合判断server所在区域的性能和server的可用性选择服务器


三、如果覆盖默认的算法


上面说过IRule的默认算法是轮询规则,那么问题来了我怎么样才能用其他六种规则呢?下面我们就来实现一下如果覆盖默认的算法。这里我们需要对工程cnzx-consumer-8021进行简单的修改


1.修改ConfigBean文件

package com.cnzx.consumer.cfgbeans;


import org.springframework.cloud.client.loadbalancer.LoadBalanced;

import org.springframework.context.annotation.Bean;

import org.springframework.context.annotation.Configuration;

import org.springframework.web.client.RestTemplate;


import com.netflix.loadbalancer.IRule;

import com.netflix.loadbalancer.RandomRule;


@Configuration

public class ConfigBean {


@Bean

@LoadBalanced

public RestTemplate getRestTemplate() {

return new RestTemplate();

}


@Bean

public IRule myRule() {

// 覆盖默认的轮询算法为随机算法

return new RandomRule();

}

}

只要加上上面红色字体的内容就可以了。


2.测试

首先我们先启动Eureka的三个集群工程cnzx-eureka-8031/cnzx-eureka-8032/cnzx-eureka-8033,然后在把服务提供者的工程cnzx-provider-8011启动,最后在启动服务消费方的工程cnzx-consumer-8021。

    然后分别访问:http://127.0.0.1:8021/dept/list,不断的刷新可以看出获取的结果已经不是轮询算法了,而是毫无规律的随机算法。


四、如果自定义算法


当IRule自带的算法无法满足某个业务需求时,我们需要自己根据需求自定义算法,那么这种情况我们该怎么做呢?我们先来看下官网怎么说的:

看上面红圈的内容:The FooConfiguratuib has to be @Configuration but take care it is not in a @ComponentScan for the main application context.意思就是那个自定义的规则算法必须要有@Configuration注解,但是要注意,它不能在@ComponentScan扫描的包下,也就是不能与启动类同级或者下级,否则所有的服务算法都用你自定义的,达不到特殊化定制的目的了。

下面我们来具体操作下步骤如下:

1.根据需求编写自己的算法类RoundRobinRuleNew

刚开始介绍算法时有张图,从图上可以看出所有的算法都继承了一个抽象的类AbstractLoadBalancerRule。

所以具体算法例子如下:依旧轮询策略,但是加上新需求,每个服务器要求被调用5次。 也即以前是每台机器一次,现在是每台机器5次


package com.cnzx.myrule;


import java.util.List;


import org.springframework.context.annotation.Configuration;


import com.netflix.client.config.IClientConfig;

import com.netflix.loadbalancer.AbstractLoadBalancerRule;

import com.netflix.loadbalancer.ILoadBalancer;

import com.netflix.loadbalancer.Server;


public class MyDefineRule extends AbstractLoadBalancerRule {


// 总共被调用的次数,目前要求每台被调用5次

private int total = 0;

// 当前提供服务的机器号

private int currentIndex = 0;


public Server choose(ILoadBalancer lb, Object key) {

if (lb == null) {

return null;

}

Server server = null;


while (server == null) {

if (Thread.interrupted()) {

return null;

}

ListupList = lb.getReachableServers();

ListallList = 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()) {

currentIndex = 0;

}

}

if (server == null) {

Thread.yield();

continue;

}


if (server.isAlive()) {

return (server);

}

server = null;

Thread.yield();

}

return server;

}


@Override

public Server choose(Object key) {

return this.choose(getLoadBalancer(), key);

}


@Override

public void initWithNiwsConfig(IClientConfig arg0) {


}


}

2.创建一个配置类MyConfigRule

上面说过在这个类必须加上@Configuration注解,说明这个类是配置类。

代码如下:

package com.cnzx.myrule;


import org.springframework.context.annotation.Bean;

import org.springframework.context.annotation.Configuration;


import com.netflix.loadbalancer.IRule;


@Configuration

public class MyConfigRule {


@Bean

public IRule myIRule() {

return new RoundRobinRuleNew(); 

}

}

3.把自定义的算法指定到某个服务上

这里直接在启动类上添加@RibbonClient注解,使得自定义得算法规则生效。

package com.cnzx.consumer;


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;


import com.cnzx.myrule.RoundRobinRuleNew;


@SpringBootApplication

@EnableEurekaClient

@RibbonClient(name = "CNZX-PROVIDER", configuration = RoundRobinRuleNew.class)

public class ConsumerAppStart8021 {


public static void main(String[] args) {

SpringApplication.run(ConsumerAppStart8021.class, args);

}

}

4.测试

重新启动cnzx-consumer-8021工程,浏览器访问:http://127.0.0.1:8021/dept/list,在不断刷新可以看出Ribbon的负载均衡算法已经变为我们自定义的算法了。


下篇文章我们来说说SpringCloud的另外一个组件SpringCloud Feign《【SpringCloud】SpringCloud Feign负载均衡(客户端)


END


更多Java、数据库、微服务、分布式的原创系列文章正在路上,欢迎扫描下方二维码,持续关注:

灵动思维文化传媒(id:itjhzx)
多年技术经验倾囊相授



文章转载自灵动思维文化传媒,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论