一:Ribbon简介

Ribbon是Netflix公司开源的一个负载均衡的项目,是一个客户端负载均衡器,运行在客户端上。它是一个经过了云端测试的IPC库,可以很好地控制HTTP和TCP客户端的一些行为。 Feign已经默认使用了Ribbon。

二:Ribbon的工作流程

1:user微服务1、user微服务2、user微服务3是一个服务集群,它们都会向注册中心注册服务(它们的应用名都是USER-SERVICE)

2:注册中心记录集群元数据信息,即USER-SERVICE下有3个服务节点

3:Ribbon拦截所有的请求,从请求信息中获取应用名

4:ribbon根据应用名从eureka注册中心获取服务列表

5:ribbon从服务列表中通过相关均衡策略获取具体某个服务

6:请求远程服务

三:Ribbon源码解析

第一步:Ribbon拦截请求,获取应用名

LoadBalancerAutoConfiguration是Ribbon的自动配置类,在这个配置类里面配置了一个拦截器,该拦截器会拦截所有请求,这就是Ribbon的入口

LoadBalancerInterceptor的intercept方法(当远程调用的时候都会被拦截器拦截)

@Override
public ClientHttpResponse intercept(final HttpRequest request, final byte[] body,
      final ClientHttpRequestExecution execution) throws IOException {
   final URI originalUri = request.getURI();
   String serviceName = originalUri.getHost();//这里就是获取应用名可以打断点测试
   Assert.state(serviceName != null"Request URI does not contain a valid hostname: " + originalUri);
   return this.loadBalancer.execute(serviceName, requestFactory.createRequest(request, body, execution));
}

第二步:通过应用名获取服务列表

负载均衡器ZoneAwareLoadBalancer是获取服务列表的重要组件

@Override
public <T> T execute(String serviceId, LoadBalancerRequest<T> request) throws IOException {ILoadBalancer loadBalancer = getLoadBalancer(serviceId);//获取负载均衡器Server server = getServer(loadBalancer);if (server == null) {throw new IllegalStateException("No instances available for " + serviceId);}RibbonServer ribbonServer = new RibbonServer(serviceId, server, isSecure(server,serviceId), serverIntrospector(serviceId).getMetadata(server));return execute(serviceId, ribbonServer, request);
}

 

ILoadBalancer是一个接口,具体的实现类是ZoneAwareLoadBalancer

// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//

package com.netflix.loadbalancer;import java.util.List;public interface ILoadBalancer {void addServers(List<Server> var1);//从列表中获取具体某个服务
    Server chooseServer(Object var1);void markServerDown(Server var1);/** @deprecated */@DeprecatedList<Server> getServerList(boolean var1);List<Server> getReachableServers();//获取服务列表List<Server> getAllServers();
}

 

ZoneAwareLoadBalancer负载均衡器是在RibbonClientConfiguration中提前定义的

@Bean
@ConditionalOnMissingBean
public ILoadBalancer ribbonLoadBalancer(IClientConfig config, ServerList<Server> serverList, ServerListFilter<Server> serverListFilter, IRule rule, IPing ping, ServerListUpdater serverListUpdater) {return (ILoadBalancer)(this.propertiesFactory.isSet(ILoadBalancer.class, this.name) ? (ILoadBalancer)this.propertiesFactory.get(ILoadBalancer.class, config, this.name) : new ZoneAwareLoadBalancer(config, rule, ping, serverList, serverListFilter, serverListUpdater));
}

 

ZoneAwareLoadBalancer的继承关系图如下:

getAllServers获取服务列表,ZoneAwareLoadBalancer没有定义getAllServers方法,但是父类BaseLoadBalancer定义了该方法

 

第三步:从列表中获取具体服务

ZoneAwareLoadBalancer定义了获取服务的方法,但是该方法最终调用的是父类BaseLoadBalancer  chooseServer方法

public Server chooseServer(Object key) {if (counter == null) {counter = createCounter();}counter.increment();if (rule == null) {return null;} else {try {return rule.choose(key);} catch (Exception e) {logger.warn("LoadBalancer [{}]:  Error choosing server for key {}", name, key, e);return null;}}
}

默认均衡策略ZoneAvoidanceRule,在RibbonClientConfiguration配置类中配置了IRule bean

 

 

均衡策略的接口是IRule,具体实现类有10个:

 

IRule

这是所有负载均衡策略的父接口,里边的核心方法就是choose方法,用来选择一个服务实例。

AbstractLoadBalancerRule

AbstractLoadBalancerRule是一个抽象类,里边主要定义了一个ILoadBalancer,就是我们上文所说的负载均衡器,负载均衡器的功能我们在上文已经说的很详细了,这里就不再赘述,这里定义它的目的主要是辅助负责均衡策略选取合适的服务端实例。

RandomRule

看名字就知道,这种负载均衡策略就是随机选择一个服务实例,看源码我们知道,在RandomRule的无参构造方法中初始化了一个Random对象,然后在它重写的choose方法又调用了choose(ILoadBalancer lb, Object key)这个重载的choose方法,在这个重载的choose方法中,每次利用random对象生成一个不大于服务实例总数的随机数,并将该数作为下标所以获取一个服务实例。

RoundRobinRule

RoundRobinRule这种负载均衡策略叫做轮询负载均衡策略,也就是我们在上文所说的BaseLoadBalancer负载均衡器中默认采用的负载均衡策略。这个类的choose(ILoadBalancer lb, Object key)函数整体逻辑是这样的:开启一个计数器count,在while循环中遍历服务清单,获取清单之前先通过incrementAndGetModulo方法获取一个下标,这个下标是一个不断自增长的数先加1然后和服务清单总数取模之后获取到的(所以这个下标从来不会越界),拿着下标再去服务清单列表中取服务,每次循环计数器都会加1,如果连续10次都没有取到服务,则会报一个警告No available alive servers after 10 tries from load balancer: XXXX

RetryRule

看名字就知道这种负载均衡策略带有重试功能。首先RetryRule中又定义了一个subRule,它的实现类是RoundRobinRule,然后在RetryRule的choose(ILoadBalancer lb, Object key)方法中,每次还是采用RoundRobinRule中的choose规则来选择一个服务实例,如果选到的实例正常就返回,如果选择的服务实例为null或者已经失效,则在失效时间deadline之前不断的进行重试(重试时获取服务的策略还是RoundRobinRule中定义的策略),如果超过了deadline还是没取到则会返回一个null。

WeightedResponseTimeRule

WeightedResponseTimeRule是RoundRobinRule的一个子类,在WeightedResponseTimeRule中对RoundRobinRule的功能进行了扩展,WeightedResponseTimeRule中会根据每一个实例的运行情况来给计算出该实例的一个权重,然后在挑选实例的时候则根据权重进行挑选,这样能够实现更优的实例调用。WeightedResponseTimeRule中有一个名叫DynamicServerWeightTask的定时任务,默认情况下每隔30秒会计算一次各个服务实例的权重,权重的计算规则也很简单,如果一个服务的平均响应时间越短则权重越大,那么该服务实例被选中执行任务的概率也就越大。

ClientConfigEnabledRoundRobinRule

ClientConfigEnabledRoundRobinRule选择策略的实现很简单,内部定义了RoundRobinRule,choose方法还是采用了RoundRobinRule的choose方法,所以它的选择策略和RoundRobinRule的选择策略一致,不赘述。

BestAvailableRule

BestAvailableRule继承自ClientConfigEnabledRoundRobinRule,它在ClientConfigEnabledRoundRobinRule的基础上主要增加了根据loadBalancerStats中保存的服务实例的状态信息来过滤掉失效的服务实例的功能,然后顺便找出并发请求最小的服务实例来使用。然而loadBalancerStats有可能为null,如果loadBalancerStats为null,则BestAvailableRule将采用它的父类即ClientConfigEnabledRoundRobinRule的服务选取策略(线性轮询)。

PredicateBasedRule

PredicateBasedRule是ClientConfigEnabledRoundRobinRule的一个子类,它先通过内部定义的一个过滤器过滤出一部分服务实例清单,然后再采用线性轮询的方式从过滤出来的结果中选取一个服务实例。

ZoneAvoidanceRule(Finchley.SR1版本中默认均衡策略)

ZoneAvoidanceRule是PredicateBasedRule的一个实现类,只不过这里多一个过滤条件,ZoneAvoidanceRule中的过滤条件是以ZoneAvoidancePredicate为主过滤条件和以AvailabilityPredicate为次过滤条件组成的一个叫做CompositePredicate的组合过滤条件,过滤成功之后,继续采用线性轮询的方式从过滤结果中选择一个出来。

 

四:自定义均衡策略

在引导类中配置负载均衡策略

@Bean
public IRule myRule(){//return new RoundRobinRule();//轮询// return new RetryRule();//重试return new BestAvailableRule();
}

 


转载于:https://www.cnblogs.com/xiufengchen/p/10430531.html

springcloud微服务总结四 负载均衡相关推荐

  1. java B2B2C Springcloud电子商城系统--------负载均衡(Load Balance)

    负载均衡(Load Balance) 由于目前现有网络的各个核心部分随着业务量的提高,访问量和数据流量的快速增长,其处理能力和计算强度也相应地增大,使得单一的服务器设备根本无法承担.在此情况下,如果扔 ...

  2. SpringCloud组件:Ribbon负载均衡策略及执行原理!

    大家好,我是磊哥. 今天我们来看下微服务中非常重要的一个组件:Ribbon.它作为负载均衡器在分布式网络中扮演着非常重要的角色. 本篇主要内容如下: 在介绍 Ribbon 之前,不得不说下负载均衡这个 ...

  3. SpringCloud(7)Ribbon 与负载均衡

    Ribbon SpringCloud Ribbon 是基于NetFlix Ribbon实现的一套客户端负载均衡的工具 简单的说,Ribbon是Netflix发布的开源项目,主要功能是提供客户端的软件负 ...

  4. 【微服务架构】SpringCloud使用Ribbon实现负载均衡

    说在前面 软负载均衡的实现方式有两种,分别是服务端的负载均衡和客户端的负载均衡 服务端负载均衡:当浏览器向后台发出请求的时候,会首先向反向代理服务器发送请求,反向代理服务器会根据客户端部署的ip:po ...

  5. apigateway-kong(四)负载均衡理论及实现

    负载均衡(Load balancing)是一种计算机网络技术,用来在多个计算机(计算机集群).网络连接.CPU.磁盘驱动器或其他资源中分配负载,以达到最佳化资源使用.最大化吞吐率.最小化响应时间.同时 ...

  6. 6.Springcloud的Ribbon的负载均衡算法解析及配置方式

    项目地址: github地址 配置方式 1.在restTemplate配置类里面添加一个bean,用于确认所属的负载均衡算法类类型,全部代码如下: package com.debuggg.cloud. ...

  7. SpringCloud的Ribbon自定义负载均衡算法

    1.Ribbon默认使用RoundRobinRule策略轮询选择server 策略名 策略声明 策略描述 实现说明 BestAvailableRule public class BestAvailab ...

  8. SpringCloud实战2-Ribbon客户端负载均衡

    https://www.cnblogs.com/huangjuncong/p/9022055.html 转载于:https://www.cnblogs.com/ruiati/p/9298562.htm ...

  9. 算法高级(17)-SpringCloud中的负载均衡算法

    前面讲的负载均衡技术实际上都是服务端负载均衡,一个请求需要被发送到哪台服务器做出响应,是由我们的服务器决定的.而在SpringCloud中,采用的缺是客户端负载均衡技术.那么客户端负载均衡的优势到底在 ...

最新文章

  1. 在MacBook Pro 2015上安装iTerm2笔记
  2. 【java】httpclient的使用之java代码内发送http请求
  3. 四、Dynamic-programming algorithm Dynamic--LCS
  4. Linux编程make命令
  5. sqlite 迁移 oracle,Oracle 数据导入 Sqlite
  6. 使用pdfobject.js实现在线浏览PDF
  7. POJO和po,vo,bo
  8. 键盘钢琴html代码,键盘钢琴KeyboardPiano(源代码)
  9. 80c51单片机c语言程序,80C51单片机电子钟程序
  10. 权宜之计是什么意思_四代火影死后,为什么没有五代火影上任?网友:纲手还在赌钱呢...
  11. 机器学习对我们生活的改变
  12. 6个部件组成一个圆球_【魔方拼装详细步骤】六块积木如何拼个球体
  13. 综合布线(楼栋)材料清单
  14. Gephi快速入门(一):Windows下安装Gephi
  15. 辽宁省内计算机专业本科大学排名,辽宁省本科院校排名
  16. nvidia linux屏幕撕裂,【技巧分享】你的Nvidia显卡在Win 7看视频画面撕裂没有?
  17. 如何将其他语言添加到Office 2010
  18. 整理一篇不错的关于软件加密的文章
  19. 太吾绘卷加载卡54_太吾绘卷保存卡死应对方案_无法保存解决方法一览_可可网...
  20. python去掉标点、特殊符号_python去掉标点_python正则化去掉标点符号_python去掉符号 - 云+社区 - 腾讯云...

热门文章

  1. SpringMVC:后台将List转为Json,传值到页面
  2. POJ 1260 Pearls
  3. Jackcard相似度和余弦相似度(向量空间模型)的java实现
  4. 什么是xmlschema
  5. cocos2d-x 3.1.1 学习笔记[17] 关于这些活动功能
  6. think in java interview-高级开发人员面试宝典(三)
  7. RotateWorldTest对层动作
  8. Hyper-V 内存管理必须知道的
  9. MOSS publishing功能:创建页面到子文件夹
  10. 学习python第四天内容回顾