5分钟带你快速了解Ribbon
Ribbon介绍
Spring Cloud Ribbon是基于Netflix Ribbon实现的—套客户端负载均衡的工具。
主要功能是提供客户端的软件负载均衡算法和服务调用。
Ribbon客户端组件提供一系列完善的配置项如连接超时,重试等。
简单的说,就是在配置文件中列出Load Balancer(简称LB)后面所有的机器,Ribbon会自动的帮助我们基于某种规则(如简单轮询,随机连接等)去连接这些机器。并且我们很容易使用Ribbon实现自定义的负载均衡算法。
负载均衡(Load Balance)是什么
简单的说就是将用户的请求平摊的分配到多个服务上,从而达到系统的HA(高可用)。常见的负载均衡有软件Nginx , LVS,硬件F5等。
-
集中式LB
即在服务的消费方和提供方之间使用独立的LB设施(可以是硬件,如F5,也可以是软件,如nginx)
由该设施负责把访问请求通过某种策略转发至服务的提供方;
-
进程内LB
将LB逻辑集成到消费方,消费方从服务注册中心获知有哪些地址可用,然后自己再从这些地址中选择出一个合适的服务器。
Ribbon就属于进程内LB,它只是一个类库,集成于消费方进程,消费方通过它来获取到服务提供方的地址。
Ribbon本地客户端负载均衡 VS Nginx 服务端负载均衡 的区别
Nginx是服务器负载均衡,客户端所有请求都会交给nginx,然后由nginx实现转发请求。即负载均衡是由服务端实现的。
Ribbon本地负载均衡,在调用微服务接口时候,会在注册中心上获取注册信息服务列表之后缓存到VM本地,从而在本地实现RPC远程服务调用技术。
为什么eureka不用引入ribbon依赖
因为eureka升级后,其服务端与客户端自带了ribbon的整合包
Ribbon负载均衡策略介绍
IRule接口:根据特定算法从服务列表中选取一个要访问的服务
-
RoundRobinRule
轮询选择,轮询 index,选择 index 对应位置的 Server。
-
WeightedResponseTimeRule
根据响应时间分配一个 Weight(权重),响应时间越长,Weight 越小,被选中的可能性越低。
-
ResponseTimeWeightedRule
过时。作用同 WeightedResponseTimeRule,ResponseTime-Weighted Rule 后来改名为 WeightedResponseTimeRule。
-
BestAvailableRule
选择一个最小的并发请求的 Server,逐个考察 Server,如果 Server 被标记为错误,则跳过,然后再选择 ActiveRequestCount 中最小的 Server。
-
ZoneAvoidanceRule
使用 ZoneAvoidancePredicate 和 AvailabilityPredicate 来判断是否选择某个 Server,前一个判断判定一个 Zone 的运行性能是否可用,剔除不可用的 Zone(的所有 Server),AvailabilityPredicate 用于过滤掉连接数过多的 Server。
-
AvailabilityFilteringRule
过滤掉那些一直连接失败的且被标记为 circuit tripped 的后端 Server,并过滤掉那些高并发的后端 Server 或者使用一个 AvailabilityPredicate 来包含过滤 Server 的逻辑。其实就是检查 Status 里记录的各个 Server 的运行状态。
-
RandomRule
随机选择一个 Server。
-
StickRule
粘性规则。始终返回相同实例的负载平衡规则
设置负载均衡
1、注意配置细节
即规则不能放在与主启动类同级及以下
手动设置负载均衡
定义负载规则
在springboot主启动类上一层新建rule包存放新建规则
com.lejia.myrole.MySelfRule.java
@Configuration
public class MySelfRule {
@Bean
public IRule myRule(){
return new RandomRule(); //定义随机
}
}
启动自定义负载规则
在主启动类上添加注解
@RibbonClient(name = “CLOUD-PROVIDER-PAYMENT”, configuration = MySelfRule.class)
name代表着要访问的服务名称(大小写必须一致)
configuration代表自定义负载均衡配置
@SpringBootApplication
@EnableEurekaClient
//手动指定服务要访问的服务名集群,以及配置指定的负载均衡规则
@RibbonClient(name = "CLOUD-PROVIDER-PAYMENT", configuration = MySelfRule.class)
public class OrderMain80 {
public static void main(String[] args) {
SpringApplication.run(OrderMain80.class, args);
}
}
启动测试
略
负载均衡算法原理
手写负载均衡算法
此轮询负载均衡算法参考IRule接口以及RoundRobinRule类
需要先将服务注册到注册中心,使用的是eureka。
1、新建LoadBalancer接口以及其实现类
在com.lejia.springcloud.lb包下新建
LoadBalancer.class
public interface LoadBalancer {
//获取集群实例的数量
ServiceInstance instance(List<ServiceInstance> instances);
}
新建LoadBalancer实现类MyLB.class
内部有两个方法
getAndIncrement()通过自旋锁思想以及AtomicInteger来实现了记录用户访问的次数,内部采用了CAS思想
instance() 通过获取传来的服务实例集合得出集群的数量,并且通过访问记录数 % 服务集群总数 来获取到当前要访问集群机器的下标,并且返回服务实例给调用者
@Component
public class MyLB implements LoadBalancer {
private AtomicInteger atomicInteger = new AtomicInteger(0);
public final int getAndIncrement(){
int current;
int next;
do{
current = this.atomicInteger.get();
next = current > 2147483647 ? 0 : current + 1;
}while(!this.atomicInteger.compareAndSet(current,next));
System.out.println("**********next " + next +" *****************");
return next;
}
@Override
public ServiceInstance instance(List<ServiceInstance> serviceInstance) {
int index = getAndIncrement() % serviceInstance.size();
return serviceInstance.get(index);
}
}
2、在服务提供者端暴露接口
8001/8002/8003模块
controller层
@GetMapping("/payment/lb")
public String getPaymentLB(){
return serverPort;
}
3、在服务消费者端调用接口
80模块
controller层
@GetMapping("/payment/lb")
public String getPaymentLB(){
//调用服务发现获取实例集合
List<ServiceInstance> instances = discoveryClient.getInstances("CLOUD-PAYMENT-SERVICE");
if(instances == null || instances.size() <= 0){
return null;
}
//调用自定义负载均衡算法来实现轮询
ServiceInstance serviceInstance = loadBalancer.instance(instances);
//获取当前服务uri
URI uri = serviceInstance.getUri();
//调用RestTemplate远程访问
return restTemplate.getForObject(uri+"/payment/lb", String.class);
}
4、测试
启动80/8001/8002/8003
调用消费端接口 http://localhost/consumer/payment/lb
可以看到,手写轮询算法还是比较简单的,只需要在LoadBalancer中添加自定义规则获取集群索引index的函数,然后在返回实例即可。
感谢你的观看,你的每一个点赞都是对我最大的帮助!