springcloud----负载均衡--Ribbon与LoadBalance

单于奕
2023-12-01

简介

Spring Cloud Ribbon 是 Netflix Ribbon 实现的一套客户端 负载均衡工具

简单的说,Ribbon 是 Netflix 发布的开源项目,主要功能是提供 客户端的复杂均衡算法服务调用 Ribbon 客户端组件提供一系列完善的配置项如超时重试等。简单的说,就是配置文件中列出 load Balancer (简称 LB)后面所有的机器,Ribbon 会自动的帮助你基于某种规则(如简单轮询,随机链接等)去链接这些机器。我们很容易使用 Ribbon 自定义的负载均衡算法。


Ribbon官网:https://github.com/Netflix/ribbon


状态 - 停更进维

替代方案 - Spring Cloud Loadbalancer

功能

LB 负载均衡(Load Balance)是什么

简单的说就是将用户的请求平摊的分配到多个服务上,从而达到系统的HA(高可用)

Ribbon 本地负载均衡客户端 VS Nginx 服务端负载均衡区别
  • Nginx 是服务器负载均衡,客户端所有请求都会交给nginx, 然后 nginx 实现转发请求。即负载均衡是由服务端实现的。

  • Ribbon 本地负载均衡,在调用微服务接口的时候,会在注册中心上获取注册信息服务列表后缓存到JVM 本地,从而在本地实现RPC远程 服务调用技术。

LB 实现方式

1、集中式

即在服务的消费方和提供方之间使用独立的LB 设施(可以是硬件,如F5, 也可以是软件如 Nginx ), 由该设置负责把访问请求通过某种策略转发至服务的提供方

2、进程内 LB

将 LB 逻辑集成到消费方,消费方从服务注册中心获取有哪些地址可用,然后自己再从这些地址中选择一个适合的服务器。
Ribbon 就属于进程内LB,它只是一个类库,集成于消费方进程,消费方通过它阿莱获取服务提供方的地址。

总结:

Ribbon 其实就是一个软负载均衡的客户端组件,他可以和其他所需请求的客户端结合使用,和eureka结合只是其中的一个实例
HA (高可用)

Ribbon 在工作时分为两步

第一步先选择 Server , 它优先选择在同一个区域呢负载较少的Server

第二步在根据用户执行的策略,在从server 取到的服务注册列表中选择一个地址。

其中 Ribbon 提供了多种策略:比如轮询随机根据响应时间加权

(测试使用Eureka做服务注册 ) 不需要额外导入依赖 ,在 spring-cloud-starter-netflix-eureka-client 自带 spring-cloud-starter-ribbon

使用方式:@LoadBalance + RestTemplate
@Bean
@LoadBalanced
public RestTemplate getRestTemplate(){
    return  new RestTemplate() ;
}

赋予RestTemplate 有负载均衡的能力 也是使用的 ribbon


指定负载均衡的方式

Ribbon 核心组件IRule : com.netflix.loadbalancer.IRule

相关的负载均衡算法 , 均在 com.netflix.loadbalancer 包下

全类名说明
RoundRobinRule轮询
RandomRule随机
RetryRule先按照RoundRobinRule的策略获取服务,如果获取服务失败则在指定时间内会进行重试,获取可用的服务
WeightedResponseTimeRule对RoundRobinRule 的拓展,响应速度越快的实例选择权重越大,越容易被选择
BestAvailableRule会先过滤掉由于多次访问故障而处断路器跳闸状态的服务,然后选择一个并发量最小的服务
AvailabilityFilteringRule先过滤掉故障实例,在选择并发较小的实例
ZoneAvoidanceRule默认规则,符合判断Server 所在区域的性能和 Server 的可用性选择服务器

指定负载均衡(在全局Main方法外面建立一个包写 , 不能让springboot扫描 , 不然会全局使用该方法)

@Configuration
public class MySelfRule {
   @Bean
   public IRule myRule(){
       return new RandomRule() ;  
   }
}
@SpringBootApplication
@EnableEurekaClient
@RibbonClient(name = "CLOUD-PAYMENT-SERVICE",configuration = MySelfRule.class) 
// 访问指定服务,使用指定的负载均衡算法
public class OrderMain80 {
   public static void main(String[] args){
       SpringApplication.run(OrderMain80.class,args) ;
   }
}

自定义负载均衡

负载均衡算法:rest 接口第几次请求数 % 服务器集群总数量 = 时机调用服务器位置下标,每次服务重启后rest 接口技术求从1开始。

List<ServiceInstance> instances = discoverClient.getInstances("PAYMENT-SERVICE");

如:  List[0] instances = 127.0.0.1:8002
          List[1] instances = 127.0.0.1:8001

8001 + 8002 组合为集群,他们共计2台服务器,集群总数为2 , 按照轮询算法原理:

当请求总数为1  时:1%2 = 1, 对应下标位置为1, 则获得服务地址为 127.0.0.1:8001
当请求总数为2 时:2%2 = 0, 对应下标位置为1, 则获得服务地址为 127.0.0.1:8002
当请求总数为3 时:2%2 = 1, 对应下标位置为1, 则获得服务地址为 127.0.0.1:8001

依次类推 。。。。

1、接口

public interface LandBalance {
    ServiceInstance instance(List<ServiceInstance> serviceInstances) ;
}

2、实现

@Component
public class MyLb implements LandBalance {
    // 原子类
    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> serviceInstances) {
        int index =  getAndIncrement() % serviceInstances.size() ;
        return serviceInstances.get(index) ;
    }
}

3、使用 (restTemplate 上不能有 LoadBalance注解)

@Autowired
private LandBalance landBalance ;
@Autowired
DiscoveryClient discoveryClient ;
    
@GetMapping("/consumer/payment/lb")
public String getPaymentLb(){
    List<ServiceInstance> instances = discoveryClient.getInstances("CLOUD-PAYMENT-SERVICE");
    if (instances == null || instances.size() <= 0 ){
        return  null ;
    }
    ServiceInstance instance = landBalance.instance(instances);
    URI uri = instance.getUri();
   return restTemplate.getForObject(uri+"/payment/lb",String.class) ;
}
 类似资料: