3.1 Ribbon概述

Spring Cloud Ribbon是基于Netflix Ribbon实现的一套客户端(80)负载均衡的工具。

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

3.2 Riboon能干什么

实现服务的负载均衡:将用户的请求平摊的分配到多个服务器上,从而达到系统的HA(高可用)!

3.3 Ribbon本地负载均衡客户端(进程式) VS Nginx服务端(集中式)负载均衡区别?

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

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

Ribbon:负载均衡 + RestTemplate 实现调用

3.4 Ribbon使用基本步骤

step1:先选择EurekaServer ,它优先选择在同一个区域内负载较少的server.

step2:再根据用户指定的策略,在从server取到的服务注册列表中选择一个地址,其中Ribbon提供了多种策略:比如轮询、随机和根据响应时间加权

3.5 Ribbon使用方法的区别

getForObject / getForEntity、postForObject / postForEntity
Object 和Entity 的区别:
Object 返回对象为响应体中数据转化称的对象,基本可以理解为json或者entity的.getBody()方法
Entity 返回对象为ResponseEntity对象,包含了响应中的一些重要信息,比如响应头(getHeaders()),响应状态码(getStatusCode()),响应体(getBody())
响应状态码(statusCode) 包含了 is1xx情报,is2xx成功,is3xx重定向,is4xx客户端,is5xx服务端,isError(4xxor5xx) 六个返回状态码的boolean类型以供判断

3.6 Ribbon负载均衡策略的算法

3.6.1 IRuler接口下的负载均衡策略:image.png

3.6.2 如何替换Ribbon负载均衡策略:

1、自定义配置类,将默认轮询的规则修改为随机负载均衡
2、在主启动类上添加注解,实现注入@RibbonClient(name = “CLOUD-PAYMENT-SERVICE”,configuration = ConsumerConfig.class)

  1. @Bean
  2. // 实现负载均衡算法的替换:将默认的轮询替换为随机random
  3. public IRule iRule(){
  4. return new RandomRule();
  5. }

3.7 Ribbon负载均衡算法的原理

★3.7.1 基本原理(默认规则轮询负载的基本原理)

rest接口第几次请求数%服务器集群总数量=实际调用服务器位置下标,每次服务重启动后rest接口计数从1开始。
List instances = discoveryClient.getInstances(“CLOUD-PAYMENT-SERVICE”);

例如,当前共有8001、8002两个服务器,集群总数量为2。

第一次发送请求:1%2=1 ,index=1, instances (1) 访问下标为1的服务器位置
第二次发送请求:2%2=0,index=0,instances (0) 访问下标为0的服务器位置
第三次发送请求:3%2=1,index=1,访问下标为1的服务器位置
……
……
开始 1、0、1、0轮询

3.7.2 底层源码

step1:负载均衡开启 lb!=null;
step2: 得到服务端集群总数量 allServers
step3:调用incrementAndGetModulo() 方法,获得下一个要访问的服务器端位置的下标索引nextServerIndex。
自旋锁+CAS(Compare and set)的知识
step4: 根据下标索引,得到需要访问的服务器
image.png
image.png

3.7.3 自定义Ribbon负载均衡算法

Step1: 自定义LoadBlancer接口,初始化,得到所有的服务器集群的列表;
Step2:自定义lb实现类实现LoadBlancer接口;
Step3:创建instances( )方法,获得当前需要访问的服务器的下标;
仿照轮询的底层原理,利用自旋锁+CAS ,获得当前的 rest接口第几次请求数getAndIncrement()

  1. public class Mylb implements LoadBalanced {
  2. private AtomicInteger nextServerCyclicCounter;
  3. public Mylb(){
  4. this.nextServerCyclicCounter=new AtomicInteger(0);
  5. }
  6. /**
  7. * 获得当前服务器位置的下标
  8. * @param serviceInstance
  9. * @return
  10. */
  11. @Override
  12. public ServiceInstance instance(List<ServiceInstance> serviceInstance) {
  13. //获得服务器的总数量
  14. int AllService = serviceInstance.size();
  15. //利用CAS和自旋锁获得当前的请求次数
  16. int current=getAndIncrement();
  17. int index=current%AllService;
  18. return serviceInstance.get(index);
  19. }
  20. private int getAndIncrement() {
  21. int current;
  22. int next;
  23. do {
  24. current=this.nextServerCyclicCounter.get();
  25. next=current>Integer.MAX_VALUE?0:current+1;
  26. }while (!this.nextServerCyclicCounter.compareAndSet(current,next));
  27. log.info("********当前为第几次访问:"+next);
  28. return next;
  29. }
  30. }