转载请注明出处:

1.什么是Ribbon

  是 Netflix 发布的一个负载均衡器,有助于控制 HTTP 和 TCP客户端行为。在 SpringCloud 中, nacos一般配合Ribbon进行使用,Ribbon提供了客户端负载均衡的功能,Ribbon利用从nacos中读 取到的服务信息,在调用服务节点提供的服务时,会合理(策略)的进行负载。 在SpringCloud中可以将注册中心和Ribbon配合使用,Ribbon自动的从注册中心中获取服务提供者的 列表信息,并基于内置的负载均衡算法,请求服务。

  Ribbon的主要作用:基于Ribbon实现服务调用, 通过拉取到的所有服务列表组成(服务名-请求路径的)映射关系。借助 RestTemplate 最终进行调用负载均衡,当有多个服务提供者时,Ribbon可以根据负载均衡的算法自动的选择需要调用的服务地址

2. restTemplate 调用接口时使用Ribbon

  首先需要定义 RestTemplate 使用 Ribbon 策略;

  @LoadBalanced
@Bean
public RestTemplate restTemplate() {
return new RestTemplate();
}

  

  本地使用 RestTemplate 调用远程接口;

@Autowired
private RestTemplate restTemplate;
@RequestMapping(value = "/echo/{id}", method = RequestMethod.GET)
public String echo(@PathVariable Long id) {
return restTemplate.getForObject("http://member-service/member/get/" + id, String.class);
}

3. Ribbon 原理

  使用RestTemplate对象只需要访问一个带有对象名称的路径,也就是http://userservice/user/XX,就可以访问到相对应的接口,这其中离不开LoadBalancerInterceptor的帮助,它会去RestTemplate的请求进行拦截,然后从Eureka中获取服务id与端口号,随后利用负载均衡算法得到真实的服务地址信息,替换服务id。

  在LoadBalancerInterceptor这个类中,会有一个intercept方法,其拦截了用户的HttpRequest请求,通过调用以下api ;

public ClientHttpResponse intercept(final HttpRequest request, final byte[] body, final ClientHttpRequestExecution execution) throws IOException {
// 获取请求uri,也就是 http://user-service/user/8
URI originalUri = request.getURI();
// 获取uri路径的主机名,其实就是服务id,user-service
String serviceName = originalUri.getHost();
Assert.state(serviceName != null, "Request URI does not contain a valid hostname: " + originalUri);
// 处理服务id,和用户请求
return (ClientHttpResponse)this.loadBalancer.execute(serviceName, this.requestFactory.createRequest(request, body, execution));
}

  获取到了url、主机名、和服务的id,再将这些信息作为参数传到LoadBalancerClient(this.loadBalancer)的execute的方法中;

  而在LoadBalancerClient的execute方法中可以通过服务id获取到服务列表,并获取合适的服务的端口号,这个方法的实现会进入到 RibbonLoadBalancerClient.execute 方法中;

  • getLoadBalancer(serviceId):根据服务id获取ILoadBalancer,而ILoadBalancer会拿着服务id去eureka中获取服务列表并保存起来。

  • getServer(loadBalancer):利用内置的负载均衡算法,从服务列表中选择一个。也就是127.0.0.1:8080

  从这里可以知道,负载均衡的实现是在getServer方法中实现的

protected Server getServer(ILoadBalancer loadBalancer, Object hint) {
  return loadBalancer == null ? null : loadBalancer.chooseServer(hint != null ? hint : "default");
}

  查看 loadBalancer.chooseServer 的实现,进入 BaseLoadBalancer 类

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

  从方法名中可以看出 rule.choose 为定义的负载均衡规则的选择,查看这个方法的实现:

  通过快捷键查看该方法的实现类可以看到 项目中所支持的负载均衡规则;若打断点 可以发现,前面传过来的default对应的是RoundRobinRule对象 ; RoundRobinRule对应的是一个轮询的规则,所以这里采用的默认负载均衡规则是轮询;

  集成了nacos 后,使用 NacosRule 规则进行负载均衡:

public Server choose(Object key) {
try {
String clusterName = this.nacosDiscoveryProperties.getClusterName();
String group = this.nacosDiscoveryProperties.getGroup();
DynamicServerListLoadBalancer loadBalancer = (DynamicServerListLoadBalancer)this.getLoadBalancer();
String name = loadBalancer.getName();
// 根据group,name 等获取nacos 中的服务组
NamingService namingService = this.nacosServiceManager.getNamingService(this.nacosDiscoveryProperties.getNacosProperties());
// 获取服务组对应的所有实例信息:updateServiceNow 里面去调用 /instance/list接口查询服务信息
List<Instance> instances = namingService.selectInstances(name, group, true);
if (CollectionUtils.isEmpty(instances)) {
LOGGER.warn("no instance in service {}", name);
return null;
} else {
List<Instance> instancesToChoose = instances; Instance instance = ExtendBalancer.getHostByRandomWeight2(instancesToChoose);
// 返回nacos的服务实例
return new NacosServer(instance);
}
} catch (Exception var10) {
LOGGER.warn("NacosRule error", var10);
return null;
}
}

4.常用的Ribbon负载均衡策略

   

内置负载均衡规则类 规则描述
RoundRobinRule 简单轮询服务列表来选择服务器。它是Ribbon默认的负载均衡规则。
AvailabilityFilteringRule 对以下两种服务器进行忽略: (1)在默认情况下,这台服务器如果3次连接失败,这台服务器就会被设置为“短路”状态。短路状态将持续30秒,如果再次连接失败,短路的持续时间就会几何级地增加。 (2)并发数过高的服务器。如果一个服务器的并发连接数过高,配置了AvailabilityFilteringRule规则的客户端也会将其忽略。并发连接数的上限,可以由客户端的..ActiveConnectionsLimit属性进行配置。
WeightedResponseTimeRule 为每一个服务器赋予一个权重值。服务器响应时间越长,这个服务器的权重就越小。这个规则会随机选择服务器,这个权重值会影响服务器的选择。
ZoneAvoidanceRule 以区域可用的服务器为基础进行服务器的选择。使用Zone对服务器进行分类,这个Zone可以理解为一个机房、一个机架等。而后再对Zone内的多个服务做轮询。
BestAvailableRule 忽略那些短路的服务器,并选择并发数较低的服务器。
RandomRule 随机选择一个可用的服务器。
RetryRule 重试机制的选择逻辑

  注意:nacos-discovery依赖了ribbon,可以不用再引入ribbon依赖

Ribbon 负载均衡源码解读的更多相关文章

  1. 小D课堂 - 新版本微服务springcloud+Docker教程_4-03 高级篇幅之Ribbon负载均衡源码分析实战

    笔记 3.高级篇幅之Ribbon负载均衡源码分析实战     简介: 讲解ribbon服务间调用负载均衡源码分析         1.完善下单接口         2.分析@LoadBalanced ...

  2. Ribbon负载均衡 (源码分析)

    Ribbon负载均衡 SpringCloud已经删除了ribbon组件,所以需要手动导入依赖.(要学是因为很多项目业务已经使用了ribbon) 服务拉取的时候添加了@LoadBalanced注解,实现 ...

  3. CentOS 6.5 + Nginx 1.8.0 + PHP 5.6(with PHP-FPM) 负载均衡源码安装

    CentOS 6.5 + Nginx 1.8.0 + PHP 5.6(with PHP-FPM) 负载均衡源码安装 http://www.cnblogs.com/ppoo24/p/4918288.ht ...

  4. HBase rebalance 负载均衡源码角度解读使用姿势

    关键词:hbase rebalance 负载均衡 参考源码版本:apache-hbase-1.1.2 什么是HBase Rebalance ? 随着数据写入越来越多以及不均衡,即使一开始每个Regio ...

  5. Tars | 第2篇 TarsJava SpingBoot启动与负载均衡源码初探

    目录 前言 1. Tars客户端启动 @EnableTarsServer 2. Communicator通信器 3. 客户端的负载均衡调用器LoadBalance 最后 前言 通过源码分析可以得出这样 ...

  6. CentOS 6.5 + Nginx 1.8.0 + PHP 5.6(with PHP-FPM) 负载均衡源码安装 之 (三)Nginx负载均衡配置

    Nginx反向代理到单个PHP-FPM(PHP-FPM可位于不同机器) 0.首先,创建我们的网站根目录[注:须在PHP-FPM所在的那台机器创建](以后网站的代码放到此目录下): mkdir /opt ...

  7. CentOS 6.5 + Nginx 1.8.0 + PHP 5.6(with PHP-FPM) 负载均衡源码安装 之 (二)PHP(PHP-FPM)安装篇

    编译安装PHP及内置PHP-FPM nginx本身不能处理PHP,它只是个web服务器,当接收到请求后,如果是php请求,则发给php解释器处理,并把结果返回给客户端(浏览器). nginx一般是把请 ...

  8. CentOS 6.5 + Nginx 1.8.0 + PHP 5.6(with PHP-FPM) 负载均衡源码安装 之 (一)Nginx安装篇

    CentOS 6.5 minimal安装不再赘述 Nginx源码安装 1.安装wget下载程序 yum -y install wget 2.安装编译环境:gcc gcc-c++ automake au ...

  9. 【RocketMQ】负载均衡源码分析

    RocketMQ在集群模式下,同一个消费组内,一个消息队列同一时间只能分配给组内的某一个消费者,也就是一条消息只能被组内的一个消费者进行消费,为了合理的对消息队列进行分配,于是就有了负载均衡. 接下来 ...

  10. CentOS 6.5 + Nginx 1.8.0 + PHP 5.6(with PHP-FPM) 负载均衡源码安装 之 (四)问题汇总

    关于外网无法访问虚拟机centos的问题 此一般由于centos默认防火墙配置,导致外部不允许访问80端口(或其他如9000端口).解决方法如下: 1.加入80端口的防火墙规则 /sbin/iptab ...

随机推荐

  1. hdu4365 Palindrome graph

    Palindrome graph Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) ...

  2. 蓝桥杯-最短路 (SPFA算法学习)

    SPFA算法主要用来解决存在负边权的单源最短路情况(但不能有负环!!!)一个简单的方法判断是否有没有负环可以通过判断是否有一个节点是否频繁进出队列. 以下内容转自https://blog.csdn.n ...

  3. MySQL运维13-Mycat分库分表之按月分片

    一.按照月分片 使用场景为按照自然月来分片,每个自然月为一个分片,但是一年有12个月,是不是要有12个数据节点才行呢?并不是.例如我现在只有三个分片数据库,这样就可以1月在第一个数据分片中,2月在第二 ...

  4. python 获取apk 信息

    python 获取apk 信息 1.安装androguard pip install androguard 2.获取apk的相关信息 引入基础信息 from androguard.misc impor ...

  5. 在Linux上部署.net Core 步骤以及遇到的一些问题

    Linux安装部署手册 一.安装.NET Core SDK centos 7 系统命令为: sudo rpm -Uvh https://packages.microsoft.com/config/ce ...

  6. 【独立闯天下】Prim新传奇!💥原团队的Blazor版本迟迟无音,合并请求石沉大海。于是,我们决定单干!加入Prime Blazor版项目,一起开创崭新的旅程吧!🌟📚

    共建Prime的Blazor版:为开源社区注入新活力 Prime组件库作为一款广受欢迎的开源组件库,一直以来都备受开发者们的青睐.然而,随着技术的不断发展和更新,原团队的Blazor版本似乎已经逐渐失 ...

  7. Cesium中用到的图形技术——Computing the horizon occlusion point

    译者注:本文翻译自Cesium官方博文<Computing the horizon occlusion point>,by KEVIN RING. 你厌倦了地平线剔除吗? 太好了,我也没有 ...

  8. CTPN+CRNN算法端到端实现文字识别的实战开发

    本文分享自华为云社区<CTPN+CRNN 算法端到端实现文字识别>,作者:HWCloudAI. OCR介绍 光学字符识别(英语:Optical Character Recognition, ...

  9. 华夏天信携手华为云开天aPaaS,打造安全、高效、节能的主煤流运输系统

    摘要:基于开天aPaaS集成工作台,主煤流运输系统如何实现多源异构数据融合.皮带物料和人员违章的智能感知,以及皮带的智能控制.灵活架构.高效集成.快速开发! 本文分享自华为云社区<华夏天信携手华 ...

  10. 鲲鹏基础软件开发赛道openLooKeng赛题火热报名中,数十万大奖等您来收割

    随着云计算.物联网.移动计算.智慧城市.人工智能等领域的发展,各类应用对大数据处理的需求也发生着变化.以实时分析.离线分析.交互式分析等为代表的计算引擎逐渐为各大企业行业发展所看重.作为鲲鹏产业生态的 ...