Ribbon实现原理
文章目录
- 概要
- 什么是Ribbon
- 客户端负载均衡
- RestTemplate核心方法
- GET 请求
- getForEntity
- getForObject
- POST 请求
- postForEntity
- postForObject
- postForLocation
- PUT请求
- DELETE请求
- 源码分析
- 类图关系
- 与Eureka结合
- 重试机制
概要
什么是Ribbon
Spring Cloud Ribbon是一个基于HTTP和TCP的客户端负载均衡工具,它基于Netflix Ribbon实现。通过Spring Cloud的封装,可以让我们轻松地将面向服务的REST模板请求自动转换成客户端负载均衡的服务调用。Spring Cloud Ribbon虽然只是一个工具类框架,它不像服务注册中心、配置中心、API 网关那样需要独立部署,但是它几乎存在于每一个Spring Cloud构建的微服务和基础设施中。因为微服务间的调用,API网关的请求转发等内容,实际上都是通过Ribbon来实现的,包括后续我们将要介绍的Feign,它也是基于Ribbon实现的工具。
客户端负载均衡
负载均衡在系统架构中是一个非常重要,并且是不得不去实施的内容。因为负载均衡是对系统的高可用、网络压力的缓解和处理能力扩容的重要手段之一。我们通常所说的负载均衡都指的是服务端负载均衡,其中分为硬件负载均衡和软件负载均衡。硬件负载均衡主要通过在服务器节点之间安装专门用于负载均衡的设备,比如F5等;而软件负载均衡则是通过在服务器上安装一些具有均衡负载功能或模块的软件来完成请求分发工作,比如Nginx 等。
硬件负载均衡的设备或是软件负载均衡的软件模块都会维护一个下挂可用的服务端清单,通过心跳检测来剔除故障的服务端节点以保证清单中都是可以正常访问的服务端节点。当客户端发送请求到负载均衡设备的时候,该设备按某种算法(比如线性轮询、按权重负载、按流量负载等)从维护的可用服务端清单中取出一台服务端的地址,然后进行转发。
而客户端负载均衡和服务端负载均衡最大的不同点在于上面所提到的服务清单所存储的位置。在客户端负载均衡中,所有客户端节点都维护着自己要访问的服务端清单,而这些服务端的清单来自于服务注册中心,比如上一章我们介绍的Eureka服务端。同服务端负载均衡的架构类似,在客户端负载均衡中也需要心跳去维护服务端清单的健康性,只是这个步骤需要与服务注册中心配合完成。在Spring Cloud实现的服务治理框架中,默认会创建针对各个服务治理框架的 Ribbon 自动化 整 合 配 置 , 比 如 Eureka 中 的org.springframework.cloud.netflix.ribbon.eureka.RibbonEurekaAutoConfiguration,Consul 中 的org.springframework.cloud.consul.discovery.RibbonConsulAutoConfiguration。在实际使用的时候,我们可以通过查看这两个类的实现,以找到它们的配置详情来帮助我们更好地使用它。
通过Spring Cloud Ribbon的封装,我们在微服务架构中使用客户端负载均衡调用非常简单,只需要如下两步:
- 服务提供者只需要启动多个服务实例并注册到一个注册中心或是多个相关联的服务注册中心。
- 服 务 消 费 者 直 接 通 过 调 用 被 @LoadBalanced 注 解 修 饰 过的RestTemplate来实现面向服务的接口调用。
这样,我们就可以将服务提供者的高可用以及服务消费者的负载均衡调用一起实现了。
RestTemplate核心方法
GET 请求
getForEntity
getForEntity函数。该方法返回的是ResponseEntity,该对象是Spring对HTTP请求响应的封装,其中主要存储了HTTP的几个重要元素,比如HTTP请求状态码的枚举对象httpStatus(也就是我们常说的404、500这些错误码)、在它的父类HttpEntity中还存储着HTTP请求的头信息对象HttpHeaders以及泛型类型的请求体对象。
getForObject
getForObject函数。该方法可以理解为对getForEntity的进一步封装,它通过HttpMessageConverterExtractor对HTTP的请求响应体body内容进行对象转换,实现请求直接返回包装好的对象内容。
POST 请求
postForEntity
postForEntity函数。该方法同GET请求中的getForEntity类似,会在调用后返回ResponseEntity对象,其中T为请求响应的body类型。
postForObject
postForObject 函数。该方法也跟 getForObject 的类型类似,它的作用是简化postForEntity的后续处理。通过直接将请求响应的body内容包装成对象来返回使用。
postForLocation
postForLocation函数。该方法实现了以POST请求提交资
源,并返回新资源的URI
PUT请求
在RestTemplate中,对PUT请求可以通过put方法进行调用实现。put函数为void类型,所以没有返回内容,也就没有其他函数定义的 responseType 参 数 , 除 此 之 外 的 其 他 传 入 参 数 定 义 与 用 法 与 postForObject 基本一致。
DELETE请求
在RestTemplate中,对DELETE请求可以通过delete方法进行调用实现,由于我们在进行REST请求时,通常都将DELETE请求的唯一标识拼接在url中,所以DELETE请求也不需要request的body信息。
源码分析
从@LoadBalanced 注解源码的注释中可以知道,该注解用来给RestTemplate 做标记,以使用负载均衡的客户端(LoadBalancerClient)来配置它。
LoadBalancerClient 是Spring Cloud中定义的一个接口:
public interface LoadBalancerClient {ServiceInstance choose(String serviceId);<T> T execute ( String serviceId,LoadBalancerRequest<T>
request)throws IOException;URI reconstructURI(ServiceInstance instance,URI original);
}
从该接口中,我们可以通过定义的抽象方法来了解客户端负载均
衡器中应具备的几种能力:
- ServiceInstance choose(String serviceId):根据传入的服务名serviceId,从负载均衡器中挑选一个对应服务的实例。
- T execute( String serviceId,LoadBalancerRequest request) throws IOException:使用从负载均衡器中挑选出的服务实例来执行请求内容。
- URI reconstructURI(ServiceInstance instance,URI original):为系统构建一个合适的host:port形式的URI。在分布式系统中,我们使用逻辑上的服务名称作为host来构建URI(替代服务实例的host:port形式)进行请求。
类图关系

从类的命名上可初步判断 LoadBalancerAutoConfiguration 为实现客户端负载均衡器的自动化配置类。
@Configuration
@ConditionalOnClass(RestTemplate.class)
@ConditionalOnBean(LoadBalancerClient.class)
public class LoadBalancerAutoConfiguration {@LoadBalanced@Autowired(required=false)private List<RestTemplate>restTemplates=Collections.emptyList();@Beanpublic SmartInitializingSingletonloadBalancedRestTemplateInitializer(final List<RestTemplateCustomizer> customizers){return new SmartInitializingSingleton(){@Overridepublic void afterSingletonsInstantiated(){for ( RestTemplate restTemplate :LoadBalancerAutoConfiguration.this.restTemplates){for ( RestTemplateCustomizer customizer :customizers){customizer.customize(restTemplate);
}
}
}
};
}
@Bean
@ConditionalOnMissingBean
public RestTemplateCustomizer restTemplateCustomizer(
final LoadBalancerInterceptor loadBalancerInterceptor){return new RestTemplateCustomizer(){
@Override
public void customize(RestTemplate restTemplate){List<ClientHttpRequestInterceptor> list=new ArrayList<>(restTemplate.getInterceptors());list.add(loadBalancerInterceptor);restTemplate.setInterceptors(list);
}
};
}@Bean
public LoadBalancerInterceptor ribbonInterceptor(
LoadBalancerClient loadBalancerClient){return new LoadBalancerInterceptor(loadBalancerClient);
}
}
从LoadBalancerAutoConfiguration类头上的注解可以知道,Ribbon实现的负载均衡自动化配置需要满足下面两个条件。
- @ConditionalOnClass(RestTemplate.class):RestTemplate 类必须存在于当前工程的环境中。
- @ConditionalOnBean ( LoadBalancerClient.class ) : 在 Spring 的Bean工程中必须有LoadBalancerClient的实现Bean。
在该自动化配置类中,主要做了下面三件事:
- 创建了一个 LoadBalancerInterceptor 的 Bean,用于实现对客户端发起请求时进行拦截,以实现客户端负载均衡。
- 创建了一个RestTemplateCustomizer的Bean,用于给RestTemplate增加LoadBalancerInterceptor拦截器。
- 维护了一个被@LoadBalanced注解修饰的RestTemplate对象列表,并在这里进行初始化,通过调用RestTemplateCustomizer的实例来给需要客户端负载均衡的RestTemplate增加LoadBalancerInterceptor拦截器。
LoadBalancerInterceptor 拦截器将一个普通的RestTemplate变成客户端负载均衡流程:
当一个被@LoadBalanced注解修饰的RestTemplate对象向外发起HTTP请求时,会被LoadBalancerInterceptor类的intercept函数所拦截。由于我们在使用RestTemplate时采用了服务名作为host,所以直接从HttpRequest的URI对象中通过getHost()就可以拿到服务名,然后调用execute函数去根据服务名来选择实例并发起实际的请求。
LoadBalancerClient只是一个抽象的负载均衡器接口,实现类为org.springframework.cloud.netflix.ribbon 包下的RibbonLoadBalancerClient。在execute函数的实现中,第一步做的就是通过getServer根据传入的服务名serviceId去获得具体的服务实例。
在使用Ribbon实现负载均衡器的时候,实际使用的还是Ribbon中定义的 ILoadBalancer 接 口 的 实 现 , 自 动 化 配 置 会 采 用
ZoneAwareLoadBalancer的实例来实现客户端负载均衡。
与Eureka结合
当在Spring Cloud的应用中同时引入Spring Cloud Ribbon和Spring Cloud Eureka依赖时,会触发Eureka中实现的对Ribbon的自动化配置。这 时 ServerList 的 维 护 机 制 实 现 将 被com.netflix.niws.loadbalancer.DiscoveryEnabledNIWSServerList 的实例所覆盖,该实现会将服务清单列表交给Eureka的服务治理机制来进行维护;IPing的实现将被com.netflix.niws.loadbalancer.NIWSDiscoveryPing的实例所覆盖,该实现也将实例检查的任务交给了服务治理框架来进行维护。默认情况下,用于获取实例请求的ServerList接口实现将采用Spring Cloud Eureka 中 封 装 的org.springframework.cloud.netflix.ribbon.eureka.DomainExtractingServerList,其目的是为了让实例维护策略更加通用,所以将使用物理元数据来进行负载均衡,而不是使用原生的AWS AMI元数据。
由于Spring Cloud Ribbon默认实现了区域亲和策略,所以,我们可以通过Eureka实例的元数据配置来实现区域化的实例配置方案。
重试机制
由于Spring Cloud Eureka实现的服务治理机制强调了CAP原理中的AP,即可用性与可靠性,它与ZooKeeper这类强调CP(一致性、可靠性)的服务治理框架最大的区别就是,Eureka为了实现更高的服务可用性,牺牲了一定的一致性,在极端情况下它宁愿接受故障实例也不要丢掉“健康”实例,比如,当服务注册中心的网络发生故障断开时,由于所有的服务实例无法维持续约心跳,在强调 AP 的服务治理中将会把所有服务实例都剔除掉,而Eureka则会因为超过85%的实例丢失心跳而会触发保护机制,注册中心将会保留此时的所有节点,以实现服务间依然可以进行互相调用的场景,即使其中有部分故障节点,但这样做可以继续保障大多数的服务正常消费。
由于Spring Cloud Eureka在可用性与一致性上的取舍,不论是由于触发了保护机制还是服务剔除的延迟,引起服务调用到故障实例的时候,希望能够增强对这类问题的容错。所以,在实现服务调用的时候通常会加入一些重试机制。较高版本的Spring Cloud整合了Spring Retry来增强RestTemplate的重试能力,对于开发者来说只需通过简单的配置,原来那些通过RestTemplate 实现的服务访问就会自动根据配置来实现重试策略(相关配置可以查看官网)。
相关文章:
Ribbon实现原理
文章目录 概要什么是Ribbon客户端负载均衡 RestTemplate核心方法GET 请求getForEntitygetForObject POST 请求postForEntitypostForObjectpostForLocation PUT请求DELETE请求 源码分析类图关系 与Eureka结合重试机制 概要 什么是Ribbon Spring Cloud Ribbon是一个基于HTTP和T…...
MuMu-LLaMA:通过大型语言模型进行多模态音乐理解和生成(Python代码实现+论文)
MuMu-LLaMA 模型是一种音乐理解和生成模型,能够进行音乐问答以及从文本、图像、视频和音频生成音乐,以及音乐编辑。该模型利用了用于音乐理解的 MERT、用于图像理解的 ViT 和用于视频理解的 ViViT 等编码器,以及作为音乐生成模型(…...
高效Android MQTT封装工具:简化物联网开发,提升性能与稳定性
在Android开发中,封装MQTT工具可以帮助简化与MQTT服务器的通信。MQTT(Message Queuing Telemetry Transport)是一种轻量级的发布/订阅消息传输协议,常用于物联网(IoT)设备之间的通信。 以下是一个简单的MQ…...
数据库原理7
1.“数据库系统运行与维护工具”的研究属于数据库管理系统软件 2.1970年IBM公司的高级研究员E.F.Codd提出了关系数据模型 3.每个属性的属性值是不可分解的,即关系的每个分量必须是一个不可分的数据项。属性值的取值应满足域完整性约束。 4.视图作用:简…...
2025最新比较使用的ai工具都有哪些,分别主要用于哪些方面?
文章目录 一、AI对话与交互工具二、AI写作与内容生成工具三、AI绘画与设计工具四、AI视频生成工具五、办公与效率工具六、其他实用工具选择建议 根据2025年最新行业动态和用户反馈,以下AI工具在多个领域表现突出,覆盖对话、写作、设计、视频生成等场景&a…...
什么是 MyBatis? 它的优点和缺点是什么?
一、 什么是 MyBatis? 定义: MyBatis 是一款优秀的持久层框架,用于简化 Java 应用程序与数据库之间的交互。MyBatis 通过 XML 或注解 的方式,将 SQL 语句与 Java 代码分离,提供了一种灵活的、易于维护的数据访问解决方…...
在ArcMap中通过Python编写自定义工具(Python Toolbox)实现点转线工具
文章目录 一、需求二、实现过程2.1、创建Python工具箱(.pyt)2.2、使用catalog测试代码2.3、在ArcMap中使用工具 三、测试 一、需求 通过插件的形式将点转线功能嵌入ArcMap界面,如何从零开始创建一个插件,包括按钮的添加、工具的实…...
Array and string offset access syntax with curly braces is deprecated
警告信息 “Array and string offset access syntax with curly braces is deprecated” 是 PHP 中的一个弃用警告(Deprecation Notice),表明在 PHP 中使用花括号 {} 来访问数组或字符串的偏移量已经被标记为过时。 背景 在 PHP 的早期版本…...
moodle 开源的在线学习管理系统(LMS)部署
一、Moodle 简介 Moodle(Modular Object-Oriented Dynamic Learning Environment)是一个开源的在线学习管理系统(LMS),广泛应用于教育机构和企业培训。其核心功能包括课程管理、作业提交、在线测试、论坛互动和成绩跟…...
后智能体时代的LLM和Agent
文章目录 1. 关于AI重塑的哲学体系2. 关于AI大模型体系的认知3. 关于AI大模型体系的畅想4. 关于人和AI大模型体系的共处5. 写在最后 随着OpenAI、Deepseek、Manus等等智能体的爆火,人们茶前饭后、插科打诨的话题都离不开这些智能体,现状也正如《人民日报…...
Day6 DFS
一、跳台阶 一个楼梯共有 nn 级台阶,每次可以走一级或者两级,问从第 00 级台阶走到第 nn 级台阶一共有多少种方案。 输入格式 共一行,包含一个整数 nn。 输出格式 共一行,包含一个整数,表示方案数。 数据范围 1…...
Releases(发布) 和 版本管理 是两个紧密相关的概念
在软件开发和维护中,Releases(发布) 和 版本管理 是两个紧密相关的概念,特别是在开源项目或企业软件开发中。 1. Releases(发布) Release 是指软件的一个正式发布版本,通常经过开发、测试、修复 Bug,并被认为是足够稳定和可用于生产环境的版本。 主要特点 里程碑:通…...
模型微调——模型性能提升方法及注意事项(自用)
名词补充 人为为训练数据标注的标签称为黄金标准或真实值,这个过程一定程度上保证训练的准确性,但是其人工标注的成本和时间很高,并且标注的标签受人的主观因素影响。 导致模型性能不佳的因素和解决办法 ①不同类别的数据不平衡:统…...
景联文科技:以精准数据标注赋能AI进化,构筑智能时代数据基石
在人工智能技术席卷全球的浪潮中,高质量数据已成为驱动AI模型进化的核心燃料。作为全球领先的AI数据服务解决方案提供商,景联文科技深耕数据标注领域多年,以技术为基、以专业为本,致力于为全球客户提供全场景、高精度、多模态的数…...
嵌入式L6计算机网络
Telnet不加密 socket是应用层和下面的内核...
华为鸿蒙系统全景解读:从内核设计到生态落地的技术革命
华为鸿蒙系统全景解读:从内核设计到生态落地的技术革命 前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,可以分享一下给大家。点击跳转到网站。 https://www.captainbed.cn/ccc 文章目录 华为鸿蒙系统全景解读&#x…...
2025最新软件测试面试八股文(含答案+文档)
1、请试着比较一下黑盒测试、白盒测试、单元测试、集成测试、系统测试、验收测试的区别与联系。 参考答案: 黑盒测试:已知产品的功能设计规格,可以进行测试证明每个实现了的功能是否符合要求。 白盒测试:已知产品的内部工作过程…...
微前端框架 Qiankun 的应用及问题分析
一、Qiankun 的核心应用场景与优势 多技术栈共存与灵活集成 Qiankun 支持主应用与子应用使用不同技术栈(如 Vue、React、Angular 等),通过 HTML Entry 方式接入子应用,无需深度改造子应用即可实现集成,降低了技术迁移成…...
八卡5090服务器首发亮相!
AI 人工智能领域热度居高不下。OpenAI 的 GPT - 4 凭强悍语言处理能力,在内容创作、智能客服等领域广泛应用。清华大学团队的 DeepSeek 大模型在深度学习训练优势突出,正促使各行业应用端算力需求向推理主导转变,呈爆发式增长 。 随着 DeepS…...
C#类型转换基本概念
一、基本定义 C# 类型转换是将数据从一种类型转换为另一种类型的过程,分为 隐式转换 和 显式转换 两类。 强类型语言特性:C# 要求变量类型在编译时确定,类型转换需满足兼容性或显式规则。目的:处理不同数据类…...
基于SSM+Vue+uniapp的驾校预约管理小程序+LW示例
系列文章目录 1.基于SSM的洗衣房管理系统原生微信小程序LW参考示例 2.基于SpringBoot的宠物摄影网站管理系统LW参考示例 3.基于SpringBootVue的企业人事管理系统LW参考示例 4.基于SSM的高校实验室管理系统LW参考示例 5.基于SpringBoot的二手数码回收系统原生微信小程序LW参考示…...
关于C++数据类型char的类型是整数的思考
学习数据类型时,整数类型中有一个特殊的类型char,可以使用字符来为其赋,也可以用整数来为其赋值,这是怎么一回事?其实任何类型,在计算机的内存中,在最小的存储单元比特中,内部只有0或…...
在Spring Boot项目中分层架构
常见的分层架构包括以下几层: 1. Domain 层(领域层) 作用:领域层是业务逻辑的核心,包含与业务相关的实体类、枚举、值对象等。它是对业务领域的抽象,通常与数据库表结构直接映射。 主要组件: 实体类(Entity):与数据库表对应的Java类,通常使用JPA或MyBatis等ORM框架…...
《用Python+PyGame开发双人生存游戏!源码解析+完整开发思路分享》
导语 "你是否想过用Python开发一款可玩性高的双人合作游戏?本文将分享如何从零开始实现一款类《吸血鬼幸存者》的生存射击游戏!包含完整源码解析、角色系统设计、敌人AI逻辑等核心技术点,文末提供完整代码包下载!" 哈…...
ArcGIS操作:13 生成最小外接矩阵
应用情景:筛选出屋面是否能放下12*60m的长方形,作为起降场候选点(一个不规则的形状内,判断是否能放下指定长宽的长方形) 1、面积初步筛选 Area ≥ 720 ㎡ 面积计算见 2、打开 ArcToolbox → Data Management Tools …...
manus对比ChatGPT-Deep reaserch进行研究类学术相关数据分析!谁更胜一筹?
没有账号,只能挑选一个案例 一夜之间被这个用全英文介绍全华班出品的新爆款国产AI产品的小胖刷频。白天还没有切换语言的选项,晚上就加上了。简单看了看团队够成,使用很长实践的Monica创始人也在其中。逐渐可以理解,重心放在海外产…...
android为第三方提供部分系统接口
文章目录 Settings - 亮灭屏Settings - 恢复出厂设置Settings - 数字锁屏/解锁Settings - 设置系统时间PackageInstaller - 安装/卸载第三方应用摘要:本文对系统模块进行改造,提供广播等形式的接口对外提供无法直接调用的系统级别接口,实现部分功能的集合。如果是广播形式,…...
在虚拟机上安装Hadoop
以下是在虚拟机上安装Hadoop的一般步骤: 准备工作 - 安装虚拟机软件:如VMware Workstation或VirtualBox等。 - 创建虚拟机:选择合适的操作系统镜像,如Ubuntu或CentOS等Linux发行版,为虚拟机分配足够的CPU、内存和磁盘…...
Python —— pow()函数
一、示例1 # 计算 2 的 3 次幂 result1 pow(2, 3) print(result1) # 输出: 8# 计算 2.5 的 2 次幂 result2 pow(2.5, 2) print(result2) # 输出: 6.25 二、示例2 # 计算 (2 ** 3) % 5 result3 pow(2, 3, 5) print(result3) # 输出: 3 三、示例3 ntxt input("请输…...
开发环境搭建-完善登录功能
一.完善登录功能 我们修改密码为md5中的格式,那么就需要修改数据库中的密码和将从前端获取到的密码转化成md5格式,然后进行比对。比对成功则登录成功,失败则禁止登录。 二.md5格式 使用DigestUtils工具类进行md5加密,调用md4Dig…...
