3 Spring Cloud Ribbon
Spring Cloud Ribbon
Spring Cloud Ribbon 是一套基于 Netflix Ribbon 实现的客户端负载均衡和服务调用工具。
Netflix Ribbon 是 Netflix 公司发布的开源组件,其主要功能是提供客户端的负载均衡算法和服务调用。Spring Cloud 将其与 Netflix 中的其他开源服务组件(例如 Eureka、Feign 以及 Hystrix 等)一起整合进 Spring Cloud Netflix 模块中,整合后全称为 Spring Cloud Netflix Ribbon。
Ribbon 是 Spring Cloud Netflix 模块的子模块,它是 Spring Cloud 对 Netflix Ribbon 的二次封装。通过它,我们可以将面向服务的 REST 模板(RestTemplate)请求转换为客户端负载均衡的服务调用。
Ribbon 是 Spring Cloud 体系中最核心、最重要的组件之一。它虽然只是一个工具类型的框架,并不像 Eureka Server(服务注册中心)那样需要独立部署,但它几乎存在于每一个使用 Spring Cloud 构建的微服务中。Spring Cloud 微服务之间的调用,API 网关的请求转发等内容,实际上都是通过 Spring Cloud Ribbon 来实现的,包括后续我们要介绍的 OpenFeign 也是基于它实现的。
负载均衡
在任何一个系统中,负载均衡都是一个十分重要且不得不去实施的内容,它是系统处理高并发、缓解网络压力和服务端扩容的重要手段之一。
负载均衡(Load Balance) ,简单点说就是将用户的请求平摊分配到多个服务器上运行,以达到扩展服务器带宽、增强数据处理能力、增加吞吐量、提高网络的可用性和灵活性的目的。
常见的负载均衡方式有两种:
- 服务端负载均衡
- 客户端负载均衡
服务端负载均衡
服务端负载均衡是最常见的负载均衡方式,其工作原理如下图。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-X5QzPtOU-1647507189748)(en-resource://database/1131:1)]
服务端负载均衡是在客户端和服务端之间建立一个独立的负载均衡服务器,该服务器既可以是硬件设备(例如 F5),也可以是软件(例如 Nginx)。这个负载均衡服务器维护了一份可用服务端清单,然后通过心跳机制来删除故障的服务端节点,以保证清单中的所有服务节点都是可以正常访问的。
当客户端发送请求时,该请求不会直接发送到服务端进行处理,而是全部交给负载均衡服务器,由负载均衡服务器按照某种算法(例如轮询、随机等),从其维护的可用服务清单中选择一个服务端,然后进行转发。
服务端负载均衡具有以下特点:
- 需要建立一个独立的负载均衡服务器。
- 负载均衡是在客户端发送请求后进行的,因此客户端并不知道到底是哪个服务端提供的服务。
- 可用服务端清单存储在负载均衡服务器上。
客户端负载均衡
相较于服务端负载均衡,客户端服务在均衡则是一个比较小众的概念。客户端负载均衡的工作原理如下图。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-rUGoz34m-1647507189750)(en-resource://database/1132:1)]
客户端负载均衡是将负载均衡逻辑以代码的形式封装到客户端上,即负载均衡器位于客户端。客户端通过服务注册中心(例如 Eureka Server)获取到一份服务端提供的可用服务清单。有了服务清单后,负载均衡器会在客户端发送请求前通过负载均衡算法选择一个服务端实例再进行访问,以达到负载均衡的目的;
客户端负载均衡也需要心跳机制去维护服务端清单的有效性,这个过程需要配合服务注册中心一起完成。
客户端负载均衡具有以下特点:
- 负载均衡器位于客户端,不需要单独搭建一个负载均衡服务器。
- 负载均衡是在客户端发送请求前进行的,因此客户端清楚地知道是哪个服务端提供的服务。
- 客户端都维护了一份可用服务清单,而这份清单都是从服务注册中心获取的。
Ribbon 就是一个基于 HTTP 和 TCP 的客户端负载均衡器,当我们将 Ribbon 和 Eureka 一起使用时,Ribbon 会从 Eureka Server(服务注册中心)中获取服务端列表,然后通过负载均衡策略将请求分摊给多个服务提供者,从而达到负载均衡的目的。
不同点 | 服务端负载均衡 | 客户端负载均衡 |
---|---|---|
是否需要建立负载均衡服务器 | 需要在客户端和服务端之间建立一个独立的负载均衡服务器。 | 将负载均衡的逻辑以代码的形式封装到客户端上,因此不需要单独建立负载均衡服务器。 |
是否需要服务注册中心 | 不需要服务注册中心。 | 需要服务注册中心。在客户端负载均衡中,所有的客户端和服务端都需要将其提供的服务注册到服务注册中心上。 |
可用服务清单存储的位置 | 可用服务清单存储在位于客户端与服务器之间的负载均衡服务器上。 | 所有的客户端都维护了一份可用服务清单,这些清单都是从服务注册中心获取的。 |
负载均衡的时机 | 先将请求发送到负载均衡服务器,然后由负载均衡服务器通过负载均衡算法,在多个服务端之间选择一个进行访问;即在服务器端再进行负载均衡算法分配。简单点说就是,先发送请求,再进行负载均衡。 | 在发送请求前,由位于客户端的服务负载均衡器(例如 Ribbon)通过负载均衡算法选择一个服务器,然后进行访问。简单点说就是,先进行负载均衡,再发送请求。 |
客户端是否了解服务提供方信息 | 由于负载均衡是在客户端发送请求后进行的,因此客户端并不知道到底是哪个服务端提供的服务。 | 负载均衡是在客户端发送请求前进行的,因此客户端清楚的知道是哪个服务端提供的服务。 |
Ribbon 实现服务调用
Ribbon 可以与 RestTemplate(Rest 模板)配合使用,以实现微服务之间的调用。RestTemplate 是 Spring 家族中的一个用于消费第三方 REST 服务的请求框架。RestTemplate 实现了对 HTTP 请求的封装,提供了一套模板化的服务调用方法。通过它,Spring 应用可以很方便地对各种类型的 HTTP 请求进行访问。
RestTemplate 针对各种类型的 HTTP 请求都提供了相应的方法进行处理,例如 HEAD、GET、POST、PUT、DELETE 等类型的 HTTP 请求,分别对应 RestTemplate 中的 headForHeaders()、getForObject()、postForObject()、put() 以及 delete() 方法。
实际代码实现
项目中引入:
<!--Spring Cloud Ribbon 依赖-->
<dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
</dependency>
创建一个名为 ConfigBean 的配置类,将 RestTemplate 注入到容器中,代码如下:
import com.netflix.loadbalancer.IRule;
import com.netflix.loadbalancer.RetryRule;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.client.RestTemplate;
// 配置类注解
@Configuration
public class ConfigBean {@Bean //将 RestTemplate 注入到容器中@LoadBalanced //在客户端使用 RestTemplate 请求服务端时,开启负载均衡(Ribbon)public RestTemplate getRestTemplate() {return new RestTemplate();}
}
创建一个名为 UserConsumer 的 Controller,该 Controller 中定义的请求用于调用服务端提供的服务,代码如下。
@Autowiredprivate
RestTemplate restTemplate;
//RestTemplate 是一种简单便捷的访问 restful 服务模板类,是 Spring 提供的用于访问 Rest 服务的客户端模板工具集,提供了多种便捷访问远程 HTTP 服务的方法
Ribbon 实现负载均衡策略
Ribbon 提供了一个 IRule 接口,该接口主要用来定义负载均衡策略,它有 7 个默认实现类,每一个实现类都是一种负载均衡策略。
实现类 | 负载均衡策略 |
---|---|
RoundRobinRule | 按照线性轮询策略,即按照一定的顺序依次选取服务实例 |
RandomRule | 随机选取一个服务实例 |
RetryRule | 按照 RoundRobinRule(轮询)的策略来获取服务,如果获取的服务实例为 null 或已经失效,则在指定的时间之内不断地进行重试(重试时获取服务的策略还是 RoundRobinRule 中定义的策略),如果超过指定时间依然没获取到服务实例则返回 null 。 |
WeightedResponseTimeRule | WeightedResponseTimeRule 是 RoundRobinRule 的一个子类,它对 RoundRobinRule 的功能进行了扩展。根据平均响应时间,来计算所有服务实例的权重,响应时间越短的服务实例权重越高,被选中的概率越大。刚启动时,如果统计信息不足,则使用线性轮询策略,等信息足够时,再切换到 WeightedResponseTimeRule。 |
BestAvailableRule | 继承自 ClientConfigEnabledRoundRobinRule。先过滤点故障或失效的服务实例,然后再选择并发量最小的服务实例。 |
AvailabilityFilteringRule | 先过滤掉故障或失效的服务实例,然后再选择并发量较小的服务实例。 |
ZoneAvoidanceRule | 默认的负载均衡策略,综合判断服务所在区域(zone)的性能和服务(server)的可用性,来选择服务实例。在没有区域的环境下,该策略与轮询(RandomRule)策略类似。 |
切换负载均衡策略
Spring Cloud Ribbon 默认使用轮询策略选取服务实例,我们也可以根据自身的需求切换负载均衡策略。切换负载均衡策略的方法很简单,我们只需要在服务消费者(客户端)的配置类中,将 IRule 的其他实现类注入到容器中即可。
实际代码改动
配置类 ConfigBean 中添加以下代码,将负载均衡策略切换为 RandomRule(随机)。
@Bean
public IRule myRule() {// RandomRule 为随机策略return new RandomRule();
}
定制负载均衡策略
创建一个名为 MyRandomRule 的类,代码如下
import com.netflix.client.config.IClientConfig;
import com.netflix.loadbalancer.AbstractLoadBalancerRule;
import com.netflix.loadbalancer.ILoadBalancer;
import com.netflix.loadbalancer.Server;import java.util.List;/**
* 定制 Ribbon 负载均衡策略
*/
public class MyRandomRule extends AbstractLoadBalancerRule {private int total = 0; // 总共被调用的次数,目前要求每台被调用5次private int currentIndex = 0; // 当前提供服务的机器号public Server choose(ILoadBalancer lb, Object key) {if (lb == null) {return null;}Server server = null;while (server == null) {if (Thread.interrupted()) {return null;}//获取所有有效的服务实例列表List<Server> upList = lb.getReachableServers();//获取所有的服务实例的列表List<Server> allList = lb.getAllServers();//如果没有任何的服务实例则返回 nullint serverCount = allList.size();if (serverCount == 0) {return null;}//与随机策略相似,但每个服务实例只有在调用 3 次之后,才会调用其他的服务实例if (total < 3) {server = upList.get(currentIndex);total++;} else {total = 0;currentIndex++;if (currentIndex >= upList.size()) {currentIndex = 0;}}if (server == null) {Thread.yield();continue;}if (server.isAlive()) {return (server);}server = null;Thread.yield();}return server;}@Overridepublic Server choose(Object key) {return choose(getLoadBalancer(), key);}@Overridepublic void initWithNiwsConfig(IClientConfig clientConfig) {// TODO Auto-generated method stub}
}
创建一个名为 MySelfRibbonRuleConfig 的配置类,将我们定制的负载均衡策略实现类注入到容器中,代码如下。
import com.netflix.loadbalancer.IRule;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;/**
* 定制 Ribbon 负载均衡策略的配置类
* 该自定义 Ribbon 负载均衡策略配置类 不能在 net.biancheng.c 包及其子包下
* 否则所有的 Ribbon 客户端都会采用该策略,无法达到特殊化定制的目的
*/
@Configuration
public class MySelfRibbonRuleConfig {@Beanpublic IRule myRule() {//自定义 Ribbon 负载均衡策略return new MyRandomRule(); //自定义,随机选择某一个微服务,执行五次}
}
3 Spring Cloud Ribbon相关推荐
- Spring Cloud Ribbon(服务消费者)
Spring Cloud Ribbon 是一个基于Http和TCP的客户端负载均衡工具,基于Netflix Ribbon实现的.它不像服务注册中心.配置中心.API网关那样独立部署,但是它几乎存在于每 ...
- 基于Spring cloud Ribbon和Eureka实现客户端负载均衡
前言 本案例将基于Spring cloud Ribbon和Eureka实现客户端负载均衡,其中Ribbon用于实现客户端负载均衡,Eureka主要是用于服务注册及发现: 传统的服务端负载均衡 常见的服 ...
- resttemplate 请求重试_使用Spring Cloud Ribbon重试请求
使用Spring Cloud Ribbon重试请求 在微服务调用中,一些微服务圈可能调用失败,通过再次调用以达到系统稳定性效果,本文展示如何使用Ribbon和Spring Retry进行请求再次重试调 ...
- java B2B2C springmvc mybatis多租户电子商城系统-Spring Cloud Ribbon
Spring Cloud Ribbon是一个基于HTTP和TCP的客户端负载均衡工具,它基于Netflix Ribbon实现. 通过Spring Cloud的封装,可以让我们轻松地将面向服务的REST ...
- Spring Cloud Ribbon –进行安全呼叫
很简单,但是最近我为此感到困惑 –我必须对安全的远程服务进行基于Netflix Ribbon的客户端调用. 事实证明,使用Netflix Ribbon可以通过两种方式实现这一点,我将通过Spring ...
- Spring Cloud微服务笔记(四)客户端负载均衡:Spring Cloud Ribbon
客户端负载均衡:Spring Cloud Ribbon 一.负载均衡概念 负载均衡在系统架构中是一个非常重要,并且是不得不去实施的内容.因为负载均衡对系统的高可用性. 网络压力的缓解和处理能力的扩容的 ...
- 为Spring Cloud Ribbon配置请求重试(Camden.SR2+)
当我们使用Spring Cloud Ribbon实现客户端负载均衡的时候,通常都会利用@LoadBalanced来让RestTemplate具备客户端负载功能,从而实现面向服务名的接口访问(原理可见& ...
- Spring Cloud Ribbon 负载均衡客户端调用示例
承接 Spring Cloud 最简入门示例 这一篇, 本篇演示如何使用负载均衡客户端 Ribbon 调用在Eureka注册的服务. Ribbon 是什么? Ribbon是Netflix 的开源项目, ...
- Java中Spring Cloud Ribbon
Spring Cloud Ribbon是一个基于HTTP和TCP的客户端负载均衡工具,它基于Netflix Ribbon实现.通过Spring Cloud的封装,可以让我们轻松地将面向服务的REST模 ...
- Spring Cloud的负载均衡Spring Cloud Ribbon和Spring Cloud Feign
一.客户端负载均衡:Spring Cloud Ribbon. Spring Cloud Ribbon是基于HTTP和TCP的客户端负载工具,它是基于Netflix Ribbon实现的.通过Spring ...
最新文章
- 八成名校AI教授,都拿过谷歌微软亚马逊们的钱
- Spark和Scala当中的collect方法的用法和例子
- C++ string转字符串
- GMTC2019|闲鱼-基于Flutter的架构演进与创新
- Qt学习: QFileDialog和QMessageBox的用法和程序示例
- python读取数据库后生成网页_python查询数据库并将结果按照格式生成HTML页面展示...
- 如何获取客户端MAC地址(三个方法)
- sublime 常用插件列表
- 金融银行业机器学习—机遇、风险、案例
- PAT乙级-1028人口普查
- 在vue中在线查看pdf
- wordpress插件_哪个是最好的WordPress画廊插件? (性能比较)
- 磁导航组成与基本原理
- PMI采购MogaFX经理人指数是什么(二)
- 对ASP.NET程序员非常有用的85个工具
- hadoop 爬虫_这些不用编程的爬虫工具,你一定要知道
- input button 光标变为手型
- 什么是数据库索引,索引有什么作用
- 金泰克/tigo S300 240G SM225K H27QFG8PEM5R 完整开盘教程
- 爬虫实战 爬取糗事百科
热门文章
- 32位计算机精度,16bit、24bit和32bit有什么区别?
- 【券商报告】春季行情仍在路上,关注涨价景气品种——附下载链接
- 狄杰斯特拉算法:单源最短路径问题
- 12T服务器硬盘,WD全球最大硬盘内部:8碟12T充氦封装
- 算法——树(10%)
- 解决libreoffice打开文件乱码
- 项目总结:vue.js2.5饿了么APP(3)主要组件实现 - 购物车相关组件(上)
- 【论文笔记】Image Inpainting for Irregular Holes Using Partial Convolutions
- 总裁演说思维模式口才训练小方法:主动问候寒暄法
- jquery中使用eval()函数