Ribbon 负载均衡源码解读
转载请注明出处:
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 负载均衡源码解读的更多相关文章
- 小D课堂 - 新版本微服务springcloud+Docker教程_4-03 高级篇幅之Ribbon负载均衡源码分析实战
笔记 3.高级篇幅之Ribbon负载均衡源码分析实战 简介: 讲解ribbon服务间调用负载均衡源码分析 1.完善下单接口 2.分析@LoadBalanced ...
- Ribbon负载均衡 (源码分析)
Ribbon负载均衡 SpringCloud已经删除了ribbon组件,所以需要手动导入依赖.(要学是因为很多项目业务已经使用了ribbon) 服务拉取的时候添加了@LoadBalanced注解,实现 ...
- 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 ...
- HBase rebalance 负载均衡源码角度解读使用姿势
关键词:hbase rebalance 负载均衡 参考源码版本:apache-hbase-1.1.2 什么是HBase Rebalance ? 随着数据写入越来越多以及不均衡,即使一开始每个Regio ...
- Tars | 第2篇 TarsJava SpingBoot启动与负载均衡源码初探
目录 前言 1. Tars客户端启动 @EnableTarsServer 2. Communicator通信器 3. 客户端的负载均衡调用器LoadBalance 最后 前言 通过源码分析可以得出这样 ...
- CentOS 6.5 + Nginx 1.8.0 + PHP 5.6(with PHP-FPM) 负载均衡源码安装 之 (三)Nginx负载均衡配置
Nginx反向代理到单个PHP-FPM(PHP-FPM可位于不同机器) 0.首先,创建我们的网站根目录[注:须在PHP-FPM所在的那台机器创建](以后网站的代码放到此目录下): mkdir /opt ...
- 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一般是把请 ...
- 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 ...
- 【RocketMQ】负载均衡源码分析
RocketMQ在集群模式下,同一个消费组内,一个消息队列同一时间只能分配给组内的某一个消费者,也就是一条消息只能被组内的一个消费者进行消费,为了合理的对消息队列进行分配,于是就有了负载均衡. 接下来 ...
- CentOS 6.5 + Nginx 1.8.0 + PHP 5.6(with PHP-FPM) 负载均衡源码安装 之 (四)问题汇总
关于外网无法访问虚拟机centos的问题 此一般由于centos默认防火墙配置,导致外部不允许访问80端口(或其他如9000端口).解决方法如下: 1.加入80端口的防火墙规则 /sbin/iptab ...
随机推荐
- 【论文阅读】HTTP 流量和恶意 URL 的异常检测
Part 1关于论文 基本信息 题目:HTTP 流量和恶意 URL 的异常检测 源码:sec2vec源代码 摘要 在本文中,我们将展示如何利用自然语言处理(NLP)中已知 的方法来检测 HTTP 请求 ...
- 漆包线工厂生产管理MES系统解决方案
漆包线行业老板痛点: 1.漆包线比较传统的行业,一般都是靠人工去管理,老板想及时知道工厂的生产,销售.出入库.库存情况: 2.型号多称重打印易错,没有系统前 :称重打印,出入库,财务脱节,库存和 ...
- 6.elasticsearch中search template和alias
什么是search template 顾名思义,查询模版,就是提前设定好查询的DSL,再次查询时,只需要指定对应的模版,然后传入相应的参数就好.一是可以每次不用构建复杂的DSL,二是可以供开发直接使用 ...
- BUUCTF 加固题 Ezsql WriteUp
文章目录 想直接要加固代码的点这里 题目 一.查看 二.进入目标机器加固 修改前的文件: 添加如下代码: 修改后的文件 三.Check 想直接要加固代码的点这里 题目 靶机地址解释: 第一行:目标机器 ...
- javacv实现屏幕录制(一)
javacv实现屏幕录制(一) javacv从入门到入土系列,发现了个好玩的东西,视频处理,于是我想搞个屏幕录屏,我百度了一下,copy那些代码我没有实现过,那些代码也没有说明,只好去官网看文档找资料 ...
- Spring Boot入坑-3-Maven简介
概述 Maven是一个自动化构建工具 能够将支持Maven项目的依赖包从远程仓库拉取到本地仓库,并进行依赖管理 项目中通过pom.xml来描述项目,对项目依赖进行管理与配置 给项目提供编译.打包.安装 ...
- Java 设置Excel页面背景
本文介绍通过Java 程序在Excel表格中设置页面背景的方法,可设置颜色背景(即指定单一颜色作为背景色).图片背景(即加载图片设置成页面背景).程序中需要使用免费版Excel类库工具 Free Sp ...
- 今天又和Redis超时杠上了
摘要:究竟是不是cpu占比高的问题导致redis超时的呢? 本文分享自华为云社区<我又和redis超时杠上了>,作者:蓝胖子的编程梦 . 背景 经过上次redis超时排查,并联系云服务商解 ...
- 详解Native Memory Tracking 追踪区域分析
摘要:本篇将介绍NMT追踪区域的部分内存类型--Java heap.Class.Thread.Code 以及 GC. 本文分享自华为云社区<Native Memory Tracking 详解(2 ...
- 基于Redis + Lua脚本的设计红包雨
摘要:红包雨是一个典型的高并发场景,短时间内有海量请求访问服务端,为了让系统运行顺畅,抢红包采用了基于 Redis + Lua 脚本的设计方案. 本文分享自华为云社区<红包雨中:Redis 和 ...