5分钟带你快速了解微服务负载均衡之Ribbon

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的整合包

image-20201201153514633

image-20201201153602403

Ribbon负载均衡策略介绍

IRule接口:根据特定算法从服务列表中选取一个要访问的服务

image-20201201160532961

image-20201202003440380

  1. RoundRobinRule

    轮询选择,轮询 index,选择 index 对应位置的 Server。

  2. WeightedResponseTimeRule

    根据响应时间分配一个 Weight(权重),响应时间越长,Weight 越小,被选中的可能性越低。

  3. ResponseTimeWeightedRule

    过时。作用同 WeightedResponseTimeRule,ResponseTime-Weighted Rule 后来改名为 WeightedResponseTimeRule。

  4. BestAvailableRule

    选择一个最小的并发请求的 Server,逐个考察 Server,如果 Server 被标记为错误,则跳过,然后再选择 ActiveRequestCount 中最小的 Server。

  5. ZoneAvoidanceRule

    使用 ZoneAvoidancePredicate 和 AvailabilityPredicate 来判断是否选择某个 Server,前一个判断判定一个 Zone 的运行性能是否可用,剔除不可用的 Zone(的所有 Server),AvailabilityPredicate 用于过滤掉连接数过多的 Server。

  6. AvailabilityFilteringRule

    过滤掉那些一直连接失败的且被标记为 circuit tripped 的后端 Server,并过滤掉那些高并发的后端 Server 或者使用一个 AvailabilityPredicate 来包含过滤 Server 的逻辑。其实就是检查 Status 里记录的各个 Server 的运行状态。

  7. RandomRule

    随机选择一个 Server。

  8. StickRule

    粘性规则。始终返回相同实例的负载平衡规则

设置负载均衡

1、注意配置细节

image-20201201161939464
image-20201201161942868
image-20201201161952712
即规则不能放在与主启动类同级及以下

手动设置负载均衡

定义负载规则

在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);
    }
}

启动测试

负载均衡算法原理

image-20201201164048470
image-20201201165620009

手写负载均衡算法

此轮询负载均衡算法参考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

image-20201201183732855

image-20201201183743242

image-20201201183750540

image-20201201183814732

可以看到,手写轮询算法还是比较简单的,只需要在LoadBalancer中添加自定义规则获取集群索引index的函数,然后在返回实例即可。

感谢你的观看,你的每一个点赞都是对我最大的帮助!

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值