SpringCloud 8 Ribbon负载均衡服务调用

SpringCloud 8 Ribbon负载均衡服务调用

一 概述

SpringCloud 8 Ribbon负载均衡服务调用_第1张图片
二、官网资料
https://github.com/Netflix/ribbon/wiki/Getting-Started

1、Ribbon目前也进入维护模式
SpringCloud 8 Ribbon负载均衡服务调用_第2张图片
2、未来替换方案
SpringCloud 8 Ribbon负载均衡服务调用_第3张图片

三、能干嘛

1、LB(负载均衡)
SpringCloud 8 Ribbon负载均衡服务调用_第4张图片

2、集中式LB与进程内LB区别

在这里插入图片描述
集中式负载均衡(服务端的负载均衡):比如nginx

SpringCloud 8 Ribbon负载均衡服务调用_第5张图片
进程内负载均衡:比如ribbon

总结:负载均衡+RestTemplate调用

四、Ribbon负载均衡演示

1、架构说明
SpringCloud 8 Ribbon负载均衡服务调用_第6张图片

2、POM
SpringCloud 8 Ribbon负载均衡服务调用_第7张图片
3、RestTemplate的使用

官网:
https://docs.spring.io/spring-framework/docs/5.2.2.RELEASE/javadoc-api/org/springframework/web/client/RestTemplate.html

getForObject方法/getForEntity方法
SpringCloud 8 Ribbon负载均衡服务调用_第8张图片
postForObject/postForEntity
SpringCloud 8 Ribbon负载均衡服务调用_第9张图片

五、Ribbon核心组件IRule

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

SpringCloud 8 Ribbon负载均衡服务调用_第10张图片
SpringCloud 8 Ribbon负载均衡服务调用_第11张图片

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

六、修改代码

1 添加规则类:
注意: 官方文档明确给出了警告:
SpringCloud 8 Ribbon负载均衡服务调用_第12张图片
这个自定义配置类不能放在 @ComponentScan 所扫描的当前包下以及子包下,否则自定义的配置类就会被所有的 Ribbon 客户端所共享,达不到特殊化定制的目的了

SpringCloud 8 Ribbon负载均衡服务调用_第13张图片

1、MySelfRule代码:

package com.atguigu.myrule;
import com.netflix.loadbalancer.IRule;
import com.netflix.loadbalancer.RandomRule;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
 * 自定义负载均衡规则类
 */
@Configuration
public class MySelfRule {
    @Bean
    public IRule myRule(){
        return new RandomRule();
    }
}

2 主启动类添加 @RibbonClient
在启动该微服务的时候就能去加载我们的自定义 Ribbon 配置类,从而使配置生效

package com.atguigu.springcloud;
import com.atguigu.myrule.MySelfRule;
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;

@SpringBootApplication
@EnableEurekaClient
@RibbonClient(name = "CLOUD-PROVIDER-SERVICE",configuration = MySelfRule.class)
public class OrderMain80 {
    public static void main(String[] args) {
        SpringApplication.run(OrderMain80.class,args);
    }
}

3 测试
SpringCloud 8 Ribbon负载均衡服务调用_第14张图片
多次刷新,是随机出现 serverPort ,负载规则就更改为随机了。

注意:
OrderController代码中配置字段信息要与OrderMain80启动类代码中@RibbonClient(name)保持一致

SpringCloud 8 Ribbon负载均衡服务调用_第15张图片
SpringCloud 8 Ribbon负载均衡服务调用_第16张图片

七、Ribbon负载均衡算法

SpringCloud 8 Ribbon负载均衡服务调用_第17张图片
原理

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

原码

package com.netflix.loadbalancer;
 
public interface IRule{
 
    public Server choose(Object key);
    
    public void setLoadBalancer(ILoadBalancer lb);
    
    public ILoadBalancer getLoadBalancer();    
}

手写:原理+JUC(CAS+自旋锁复习)

(1)7001/7002集群启动、

(2)8001/8002微服务改造、【Controller】

//	增加以下代码
...
@GetMapping(value = "/payment/lb")
public String getPaymentLB(){
    return serverPort;
}
...

(3)80客户端改造、【Controller】

  • ApplicationContextConfig去掉注解@LoadBalance
  • LoadBalancer接口

SpringCloud 8 Ribbon负载均衡服务调用_第18张图片

LoadBalancer 接口代码

package com.jiao.springcloud.lb;
 
import org.springframework.cloud.client.ServiceInstance;
 
import java.util.List;
 
public interface LoadBalancer {
    ServiceInstance instances(List serviceInstances); //通过serverName找serverPort
}
  • MyLb【也就是LoadBalancerImpl】

     package com.jiao.springcloud.lb;
      
     import org.springframework.cloud.client.ServiceInstance;
     import org.springframework.stereotype.Component;
      
     import java.util.List;
     import java.util.concurrent.atomic.AtomicInteger;
      
     @Component
     public class MyLb implements LoadBalancer{
      
         private AtomicInteger atomicInteger = new AtomicInteger(0); //初始为0
      
         private final int getAndIncrement(){
             int current;
             int next;
             do {
                 current = this.atomicInteger.get(); //0
                 next = current >= 2147483647 ? 0 : current + 1;
             }while (!this.atomicInteger.compareAndSet(current,next));   //自旋:当前值=期望值:修改值
             System.out.println("*****第几次访问next:"+next);
             return next;
         }
      
         public ServiceInstance instances(List serviceInstances) {
             int index = getAndIncrement() % serviceInstances.size();
             return serviceInstances.get(index);
         }
     }
    
  • OrderController 增加代码

     ...
     @Resource
     private LoadBalancer loadBalancer;  //自己写的负载均衡算法
     @Resource
     private DiscoveryClient discoveryClient;
     ...
     @GetMapping(value = "/consumer/payment/lb")
     public String getPaymentLB(){
        List instances = discoveryClient.getInstances("CLOUD-PAYMENT-SERVICE");
        if (instances == null || instances.size() <=0){
           return null;
        }
        ServiceInstance serviceInstance = loadBalancer.instances(instances);
        URI uri = serviceInstance.getUri();
        return restTemplate.getForObject(uri+"payment/lb",String.class);
     }
    
  • 测试【http:localhost/consumer/payment/lb】

SpringCloud 8 Ribbon负载均衡服务调用_第19张图片

SpringCloud 8 Ribbon负载均衡服务调用_第20张图片

注意:要配置服务名称(“CLOUD-PAYMENT-SERVICE”)

  • discoveryClient.getInstances(“CLOUD-PAYMENT-SERVICE”); 如果配置"http://CLOUD-PAYMENT-SERVICE" 则页面无效果也不会报错

SpringCloud 8 Ribbon负载均衡服务调用_第21张图片

对应代码下载地址:Ribbon

你可能感兴趣的