SpringCloud系列:负载均衡组件-Ribbon

作者平台:

| CSDN:blog.csdn.net/qq_41153943

| 掘金:juejin.cn/user/651387…

| 知乎:www.zhihu.com/people/1024…

| GitHub:github.com/JiangXia-10…

本文一共4529字,预计阅读12分钟

前言

前面几篇文章介绍了微服务相关的内容,比如什么是微服务,常见的一些服务注册中心组件,以及微服务之间是如何进行服务通信的。

在微服务架构中还有常见的一种场景就是服务的负载均衡。今天就一起学习SpringCloud提供的负载均衡组件-Ribbon。

什么是Ribbon

Spring Cloud Ribbon是一个基于http和tcp的客户端负载均衡工具,是基于netflix ribbon实现的,通过Spring Cloud封装, 可以让我们将面向服务的resttemplate请求自动转换成客户端负载均衡的服务调用。

所以Ribbon是SpringCloud提供一套客户端负载均衡组件,提供一系列的完善的配置,如超时,重试等,它有助于控制HTTP和TCP的客户端的行为。通过Load Balancer获取到服务提供的所有机器实例, Ribbon会自动基于某种规则(默认是轮询机制)去调用这些服务。Ribbon也可以实现我们自己的负载均衡算法。
在这里插入图片描述

标题Ribbon的负载均衡策略

基于Ribbon方式的负载均衡,Netflix默认提供了七种负载均衡策略,分别是:

1、RoundRobinRule(轮询策略)

轮询策略是Ribbon的默认策略,是按照顺序,依次对所有的服务实例进行访问。比如一共有 3 个服务,第一次调用服务 1,第二次调用服务 2,第三次调用服务3。

2、WeightedResponseTimeRule(权重策略)

权重策略是根据每个服务提供者的响应时间分配一个权重,响应时间越长,权重越小,被选中的可能性也就越低。它的实现原理是,刚开始使用轮询策略并开启一个计时器,每一段时间收集一次所有服务提供者的平均响应时间,然后再给每个服务提供者附上一个权重,权重越高被选中的概率也越大。

3、RetryRule(重试策略)

重试策略指的是按照轮询策略来获取服务,如果获取的服务实例为 null 或已经失效,则在指定的时间之内不断地进行重试来获取服务,如果超过指定时间依然没获取到服务实例则返回 null。

4、RandomRule(随机策略)

随机策略比较简单就是指从服务提供者的列表中随机选择一个服务实例。

5、BestAvailableRule(最小连接数策略)

最小连接数策略,也叫最小并发数策略,它是指遍历服务提供者列表,选取连接数最小的⼀个服务实例。如果有相同的最小连接数,那么会调用轮询策略进行选取。

6、ZoneAvoidanceRule(区域敏感策略)

区域敏感策略是根据服务所在区域的性能和服务的可用性来选择服务实例,在没有区域的环境下,该策略和轮询策略类似。

7、AvailabilityFilteringRule(可用敏感性策略)

可用敏感性策略是先过滤掉非健康的服务实例,然后再选择连接数较小的服务实例。

在ribbon中可以通过下述命令指定负载均衡策略,比如设置RoundRobinRule:

ribbon:NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RoundRobinRule

设置其他策略修改具体的策略名即可。

除此之外还可以自定义负载均衡策略。自定义负载均衡策略,则需要继承com.netflix.loadbalancer.AbstractLoadBalancerRule抽象类。

图片

实战

项目导入spring-cloud-starter-consul-discovery依赖后,包含了ribbon依赖,所以不需要额外导入ribbon依赖。项目是在之前项目的基础上, 可以参考:SpringCloud系列:服务注册中心组件—consul文中的项目。
在这里插入图片描述
使用resttemplate+ribbon组件去实现负载均衡,主要有三种方法:

1、使用DiscoveryClient对象

DiscoveryClient是一种服务发现客户端对象,可以用来获取服务注册中心的信息:

@Autowired
private DiscoveryClient discoveryClient;
//创建一个RestTemplate对象
RestTemplate restTemplate = new RestTemplate();
List<ServiceInstance> serviceInstances = discoveryClient.getInstances("orders");
serviceInstances.forEach(serviceInstance -> {
logger.info("服务主机:{};服务地址:{};服务端口:{}",serviceInstance.getHost(),serviceInstance.getUri(),serviceInstance.getPort());
});
String result = restTemplate.getForObject(serviceInstances.get(0).getUri()+"/order/order",String.class);

通过DiscoveryClient的getInstances方法根据服务id去服务注册中心获取对应的服务列表到本地中,但是可以发现这里其实并没有负载均衡,还是需要自己去实现负载均衡,并且服务的访问路径还是需要进行拼接。

2、LoadBalancerClient对象

LoadBalancerClient对象是一种负载均衡客户端对象,也是根据服务id去服务注册中心获取对应的服务列表,并且根据默认的负载均衡策略选择服务列表中的一台机器并返回,所以这里返回的是一个服务,而DiscoveryClient返回的是服务列表:

ServiceInstance serviceInstance = loadBalancerClient.choose("orders");
logger.info("服务主机:{};服务地址:{};服务端口:{}",serviceInstance.getHost(),serviceInstance.getUri(),serviceInstance.getPort());
String result = restTemplate.getForObject(serviceInstance.getUri()+"/order/order",String.class);

可以发现使用LoadBalancerClient时需要每次先根据服务id获取一个负载均衡的机器之后再通过resttemplate调用服务,也较为复杂和繁琐。

3、使用@LoadBalanced注解

@LoadBalanced注解是来自cloud包下的一个注解,这个注解就是让某一个东西拥有负载均衡的能力,该注解主要用在方法上。

比如这里就是让这个RestTemplate在请求时拥有客户端负载均衡的能力。可以这样写在一个配置类中:

@Configuration
public class MyConfig {@Bean@LoadBalanced //使其具有负载均衡属性public RestTemplate restTemplate(){return  new RestTemplate();}
}

然后在需要进行负载均衡的地方,使用服务名+请求路径即可:

String result = restTemplate.getForObject("http://orders/order/order",String.class);

这是如果启动项目,输入:

http://localhost:8083/user/user

并不断刷新,进行请求,则会按照默认的轮询的负载均衡策略依次请求8084和9999端口的请求:
图片
图片
通过上述的代码可以发现,Ribbon是客户端的负载均衡,它实现负载均衡是根据调用服务的服务id去服务注册中心获取对应服务id的服务列表,并将服务列表拉取到本地进行缓存,然后在本地根据负载均衡机制在现有的列表中选择可以可用节点提供服务。

Ribbon是一种客户端的负载均衡,在使用Ribbon的负载均衡中,大致可以分为以下几步:

1、首先拦截请求,并且通过请求中的url地址,截取服务名称 ;

2、通过LoadBalancerClient获取ILoadBalancer;

3、根据服务id在Eureka、consul等服务注册中心中获取服务列表;

4、通过IRule负载均衡策略选择具体服务;

5、ILoadBalancer通过IPing及定时更新机制来维护服务列表;

6、重构该url,并且最终调用HttpURLConnection发起请求。

总结

以上就是springcloud中使用resttemplate+ribbon实现负载均衡的内容。Ribbon是客户端的负载均衡,它实现负载均衡是根据调用服务的服务id去服务注册中心获取对应服务id的服务列表,并将服务列表拉取到本地进行缓存,然后在本地根据负载均衡机制在现有的列表中选择可以可用节点提供服务。

有任何问题或者不正确的地方,欢迎指出,交流讨论!

文章项目源码在:https://github.com/JiangXia-1024/SpringCloudProject。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/4817.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

idea 有时提示找不到类或者符号,日志报java: 找不到符号的解决

解决一&#xff1a; idea maven编译成功&#xff0c;运行失败提示找不到符号&#xff0c;主要是get和set方法找不到符号&#xff0c;此时就是idea的lombok版本冲突 IDEA版本导致的Lombok失效&#xff0c;需要更新lombok版本到1.18.14及之后版本得到解决 <dependency>&…

科技云报道:数字化转型完成后,制造业如何走向“数智”时代?

科技云报道原创。 随着我国数字化转型行动的深入推进和智能制造工程的大力实施&#xff0c;制造业正朝着“数智”时代迈进&#xff0c;生成式AI被视为推动制造业智能化发展的关键驱动力。 据预测&#xff0c;到2027年&#xff0c;将有30%的制造业采用生成式AI来提升产品研发效…

【C++修炼之路】类和对象(下)—— 完结篇

&#x1f451;作者主页&#xff1a;安 度 因 &#x1f3e0;学习社区&#xff1a;StackFrame &#x1f4d6;专栏链接&#xff1a;C修炼之路 文章目录 一、再谈构造函数1、初始化列表2、explicit 关键字 二、static 成员1、概念2、特性 三、友元1、友元函数2、友元类 四、内部类五…

zabbix监控linux主机、监控windows10主机

目录 一、环境准备 1、关闭防火墙 2、准备三台服务器、添加主机声明 3、修改主机名 4、此篇接着上一篇zabbix监控自己的环境下操作&#xff0c;server&#xff08;192.168.147.135&#xff09;已经配置好 二、源码安装zabbix 1、下载包、安装依赖包、联网同步清华时间 2…

十分钟让你了解 Linux ABI

getline() 提供了一种更灵活的方法&#xff0c;可以在不破坏系统的情况下将用户数据读入程序。 在 C 语言中读取字符串是一件非常危险的事情。当读取用户输入时&#xff0c;程序员可能会尝试使用 C 标准库中的 gets 函数。它的用法非常简单&#xff1a; char *gets(char *stri…

Kubernetes对象深入学习之三:对象属性

欢迎访问我的GitHub 这里分类和汇总了欣宸的全部原创(含配套源码)&#xff1a;https://github.com/zq2599/blog_demos 本篇概览 本文是《Kubernetes对象深入学习》系列的第三篇&#xff0c;主要内容是关于对象属性的知识点&#xff0c;关于对象属性&#xff0c;先通过一个具体…

LeetCode·每日一题·1851. 包含每个查询的最小区间·优先队列(小顶堆)

题目 示例 思路 离线查询&#xff1a; 输入的结果数组queries[]是无序的。如果我们按照输入的queries[]本身的顺序逐个查看&#xff0c;时间复杂度会比较高。 于是&#xff0c;我们将queries[]数组按照数值大小&#xff0c;由小到大逐个查询&#xff0c;这种方法称之为离线查询…

Ceph 服务的运用

目录 一、资源池 pool 管理 1.创建一个 Pool 资源池 2.查看集群 Pool 信息 3.查看资源池副本的数量 4.查看 PG 和 PGP 数量 5.修改 pg_num 和 pgp_num 的数量为 128 6.修改 Pool 副本数量为 2 7.修改默认副本数为 2 8.删除 Pool 资源池 8.1修改配置文件 8.2推送 ceph…

TypeScript 1 - 小记

文章目录 关于 TypeScript 关于 TypeScript TypeScript is a superset of JavaScript that compiles to clean JavaScript output. 官网&#xff1a;https://www.typescriptlang.orggithub : https://github.com/microsoft/TypeScriptplayground : https://www.typescriptlan…

BTP Integration Suite学习笔记 - (Unit3) Developing with SAP Integration Suite

BTP Integration Suite学习笔记 - (Unit1) Developing with SAP Integration Suite BTP Integration Suite学习笔记 - (Unit2) Developing with SAP Integration Suite 带着一个问题去学&#xff1a;明明可以直接访问一个后端系统的OData服务&#xff0c;为什么还要再多绕一道C…

Linux5.16 Ceph集群

文章目录 计算机系统5G云计算第四章 LINUX Ceph集群一、Ceph1.存储基础1&#xff09;单机存储设备2&#xff09;单机存储的问题3&#xff09;商业存储解决方案4&#xff09;分布式存储&#xff08;软件定义的存储 SDS&#xff09;5&#xff09;分布式存储的类型 2.Ceph 简介3.C…

获得servlet相关API,获得请求头和cookie-spring23

后台能够成功打印 如何获得请求头 如何获得cookie 获取浏览器信息 把network下user Agent的值赋给他 这个值可以直接赋给Cookie 就是这个cookie 把cookie的值赋值给一边JasonId&#xff0c; 这里面的Value代表着名字,名字是cookie后面那一块&#xff1a;

nginx推流环境搭建

目录 1、创建安装文件夹2、安装编译 nginx 所需要的库3、下载 nginx-1.21.6.tar.gz下载 nginx-rtmp-module4、解压解压nginx文件解压rtmp模块5、编译6、安装7、启动nginx,检测nginx是否能成功运行8、配置nginx使用RTMP9、重启nginx服务器1、创建安装文件夹 cd ~ mkdir nginx …

Comparator.comparing()实现中文排序及空指针处理

一、 Comparator.comparing()的用法请详见以下上一篇文章的汇总介绍。 Comparator用法_乞力马扎罗の黎明的博客-CSDN博客 二、应用示例&#xff1a; 1、中文排序、空值处理 Collator instance Collator.getInstance(Locale.CHINA); checkItemVoList.stream().sorted(Compar…

每日科技分享-POE新增文件和链接发送功能

POE推出新功能 注意POE需要魔法上午才能进去。 实测 实测可以发送论文给chatgpt&#xff0c;然后和AI进行共享的对话。 POE网站链接&#xff1a; 也可以发送链接&#xff0c;实测了一下&#xff0c;似乎有时候并不准确&#xff0c;我发送了关于分层强化的文章&#xff0c;但是…

<数据结构>NO11.归并排序|递归|非递归|优化

文章目录 归并排序递归写法非递归写法修正方案1.归并一段拷贝一段修正方案2.修正区间 算法优化算法分析 归并排序的应用外排序和内排序 归并排序 递归写法 思路: 如果给出两个有序数组&#xff0c;我们很容易可以将它们合并为一个有序数组。因此当给出一个无序数组时&#xf…

华为无线ac+ap旁挂二层组网常用配置案例

AC控制器理解配置步骤&#xff1a; capwap source interface Vlanif 100 //源IP回包地址 wlan ssid-profile name test //新建个模版名称为test ssid test //wifi名称 wlan security-profile name test //建立安全模版也叫test security wpa-wpa2 psk pass-phrase admin123 a…

linux 安装 cuda

需求&#xff1a; inux 下安装 cuda 进程&#xff1a; 先查看一下系统版本 uname -a查看能支持什么版本的cudacuda toolkit 下载 wget https://developer.download.nvidia.com/compute/cuda/11.1.0/local_installers/cuda_11.1.0_455.23.05_linux.run sudo sh cuda_11.1.0_4…

API 接口是什么?怎么对接 API?

一、API接口是什么&#xff1f; API接口即应用编程接口&#xff0c;是一些预先定义的函数&#xff0c;可以提供应用程序与开发人员基于某软件或硬件以访问一组例程的能力。简单来说&#xff0c;API接口相当于信息的桥梁&#xff0c;它可以让不同平台、应用程序或系统共享数据&…

对Element DatePicker时间组件的封装,时间组件开始时间和结束时间绑定

背景 我们时常有时间范围选择&#xff0c;需要选择一个开始时间和一个结束时间给后端&#xff0c;但我们给后端的是两个字段&#xff0c; 分别是开始时间和结束时间&#xff0c;现在使用element绑定的值是一个数组&#xff0c;我们还要来回处理&#xff0c;很麻烦列表也的查询…