微服务负载均衡组件-Ribbon
什么是Ribbon
Ribbon是Netflix发布的开源项目,其主要功能是提供客户端侧负载均衡算法。Ribbon客户端组件提供一系列完善的配置项如连接超时,重试等。Ribbon会自动的帮助你基于某种规则(如轮询,随机等)去连接这些机器,用时,Ribbon也支持自定义的负载均衡算法
在SpirngCloud中,Ribbon利用从Eureka中读取到的服务提供者列表信息,在调用服务节点提供服务时,基于内置的负载均衡算法,进行服务请求。
Ribbo和Nginx区别
一般实现负载均衡,会有俩个选择,客户端负载均衡和服务端的负载均衡
Nginx是服务端负载均衡,负载均衡的策略算法是在服务端实现的。
Ribbon是客户端负载均衡,负载均衡算法是由调用者本身进行维护的。
策略
Ribbon内置了多种负载均衡策略,内部负责复杂均衡的顶级接口为
com.netflix.loadbalancer.IRule;
com.netflix.loadbalancer.RoundRobinRule;轮询策略
com.netflix.loadbalabcer.RandomRule; 随机策略;
com.netflix.loadbalancer.BestAvailableRule; 最佳可用策略
用法
1.添加pom文件
<!--Ribbon-->
<!-- <dependency>-->
<!-- <groupId>org.springframework.cloud</groupId>-->
<!-- <artifactId>spring-cloud-starter-ribbon</artifactId>-->
<!-- <version>1.4.6.RELEASE</version>-->
<!-- </dependency>-->
<!--自带有ribbon-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka- client</artifactId>
</dependency>
2. 添加注解
@Bean
@LoadBalanced //Ribbon
public RestTemplate getRestTemplate(){
return new RestTemplate();
}
自定义ribbon
1. 重写方法
public class KuangRandomRule extends AbstractLoadBalancerRule {
//每个服务,访问5次~,换下一个服务(3个)
// total=0, 默认=0,如果=5,我们指向下一个服务节点
// index=0,默认0,如果total=5,index+1,
private int total = 0; //被调用的次数
private int currentIndex = 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 index = chooseRandomInt(serverCount); //生成区间随机数
// server = upList.get(index); //从活着的服务中,随机获取一个~
//-=========================================================
if (total<5){
server = upList.get(currentIndex);
total++;
}else {
total = 0;
currentIndex++;
if (currentIndex>upList.size()){
currentIndex = 0;
}
server = upList.get(currentIndex); //从活着的服务中,获取指定的服务来进行操作
}
//-=========================================================
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
}
}
2. 注入进去
````java
@Bean
public IRule myRule(){
return new RoundRobinRule(); //默认是轮询,现在我们定义为~ KuangRandomRule
}
注:一定要写在主配置外面,不然会被componentscan扫描到。否则,它由所有@RibbonClients共享。如果您使用@ComponentScan(或@SpringBootApplication),则需要采取措施避免将其包括在内(例如,可以将其放在单独的,不重叠的程序包中,或指定要在@ComponentScan)。