【微服务】Ribbon实现负载均衡

news/2024/4/29 15:37:52/文章来源:https://blog.csdn.net/m0_64210833/article/details/129284568

目录

1.什么是负载均衡

2.自定义负载均衡

3.基于Ribbon实现负载均衡

Ribbon⽀持的负载均衡策略

4.负载均衡原理

源码跟踪

LoadBalancerIntercepor

LoadBalancerClient

5.负载均衡策略IRule

总结


1.什么是负载均衡

        通俗的讲, 负载均衡就是将负载(⼯作任务,访问请求)进⾏分摊到多个操作单元(服务器,组件)上进⾏执⾏。
        Ribbon负载均衡器就是接收客户端的发送的一个请求通过负载均衡算法分配给一个后端服务器(已经使用集群部署的服务器)进行处理,达到负载均衡的效果,避免所有的请求都发送给同一个服务器导致挂掉。

2.自定义负载均衡

1. 通过idea按照下面操作,输入-Dserver.port=8082
再进行启动⼀个 shop-product 微服务

2. 通过nacos查看微服务的启动情况

3. 修改 OrderServiceImpl 的代码,使用代码Random实现负载均衡

@Service
@Slf4j
public class OrderServiceImpl implements OrderService {@Autowiredprivate OrderDao orderDao;@Autowiredprivate DiscoveryClient discoveryClient;@Autowiredprivate RestTemplate restTemplate;@Overridepublic Order createOrder(Long productId,Long userId) {log.info("接收到{}号商品的下单请求,接下来调⽤商品微服务查询此商品信息",
productId);//从nacos中获取服务地址//⾃定义规则实现随机挑选服务List<ServiceInstance> instances = discoveryClient.getInstances("product-service");int index = new Random().nextInt(instances.size());ServiceInstance instance = instances.get(index);String url = instance.getHost()+":"+instance.getPort();log.info(">>从nacos中获取到的微服务地址为:" + url);//远程调⽤商品微服务,查询商品信息Product product = restTemplate.getForObject("http://"+url+"/product/"+productId,Product.class);log.info("查询到{}号商品的信息,内容是:{}", productId,
JSON.toJSONString(product));//创建订单并保存Order order = new Order();order.setUid(userId);order.setUsername("mxin5");order.setPid(productId);order.setPname(product.getPname());order.setPprice(product.getPprice());order.setNumber(1);orderDao.save(order);log.info("创建订单成功,订单信息为{}", JSON.toJSONString(order));return order;}
}
4. 启动两个服务提供者和⼀个服务消费者,多访问⼏次消费者测试效果

3.基于Ribbon实现负载均衡

RibbonSpring Cloud的⼀个组件, 它可以让我们使⽤⼀个注解就能轻松的搞定负载均衡
1. RestTemplate 的⽣成⽅法上添加@LoadBalanced注解
/*** @LoadBalanced就可以实现负载均衡,原理就是一个标记,标记Resttemplate发出的请求要被我们的Ribbon进行拦截和处理* */@LoadBalanced@Beanpublic RestTemplate restTemplate(){return new RestTemplate();}
2. 修改OrderServiceImpl服务调⽤的⽅法        
@Service
@Slf4j
public class OrderServiceImpl implements OrderService {@Autowiredprivate OrderDao orderDao;@Autowiredprivate RestTemplate restTemplate;@Overridepublic Order createOrder(Long productId,Long userId) {log.info("接收到{}号商品的下单请求,接下来调⽤商品微服务查询此商品信息",
productId);//远程调⽤商品微服务,查询商品信息Product product = restTemplate.getForObject("http://product-service/product/"+productId,Product.class);log.info("查询到{}号商品的信息,内容是:{}", productId,
JSON.toJSONString(product));//创建订单并保存Order order = new Order();order.setUid(userId);order.setUsername("叩丁狼教育");order.setPid(productId);order.setPname(product.getPname());order.setPprice(product.getPprice());order.setNumber(1);orderDao.save(order);log.info("创建订单成功,订单信息为{}", JSON.toJSONString(order));return order;}
}
3. 为了更直观看到请求是进⾏负载均衡了,我们修改⼀下ProductController代码
@RestController
@Slf4j
public class ProductController {@Autowiredprivate ProductService productService;@Value("${server.port}")private String port;//商品信息查询@RequestMapping("/product/{pid}")public Product findByPid(@PathVariable("pid") Long pid) {log.info("接下来要进⾏{}号商品信息的查询", pid);Product product = productService.findByPid(pid);product.setPname(product.getPname()+",data from "+port);log.info("商品信息查询成功,内容为{}", JSON.toJSONString(product));return product;}
}
4. 调⽤订单保存的⽅法,查看⽇志.
        默认情况下,采取的是ZoneAvoidanceRule的策略,复合判断server所在区域的性能和server的可⽤性选择server。

Ribbon⽀持的负载均衡策略

Ribbon内置了多种负载均衡策略,内部负载均衡的顶级接⼝为com.netflix.loadbalancer.IRule , 具体的负载策略如下图所示
我们可以通过修改配置来调整Ribbon的负载均衡策略,在order-server项⽬的application.yml中增加如下配置:
product-service: # 调⽤的提供者的名称
   ribbon:
      NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule# 轮询的方式

在上文的案例中我们添加了@LoadBalanced注解,即可实现负载均衡功能,这是什么原理呢?

我们这里的@LoadBalanced相当于是一个标记,标记这个RestTemplate发出的请求要被我们的Ribbon拦截和处理。

4.负载均衡原理

SpringCloud底层其实是利用了一个名为Ribbon的组件,来实现负载均衡功能的。

那么我们发出的请求明明是http://userservice/user/1,怎么变成了http://localhost:8081/user/1的呢?

源码跟踪

为什么我们只输入了service名称就可以访问了呢?之前还要获取ip和端口。

显然有人帮我们根据service名称,获取到了服务实例的ip和端口。它就是LoadBalancerInterceptor,这个类会在对RestTemplate的请求进行拦截,然后从Eureka根据服务id获取服务列表,随后利用负载均衡算法得到真实的服务地址信息,替换服务id。

我们进行源码跟踪:

LoadBalancerIntercepor

可以看到这里的intercept方法,拦截了用户的HttpRequest请求,然后做了几件事:

    request.getURI():获取请求uri,本例中就是 http://user-service/user/8
    originalUri.getHost():获取uri路径的主机名,其实就是服务id,user-service
    this.loadBalancer.execute():处理服务id,和用户请求。

这里的this.loadBalancerLoadBalancerClient类型,我们继续跟入。

LoadBalancerClient

继续跟入execute方法:

代码是这样的:

  • getLoadBalancer(serviceId):根据服务id获取ILoadBalancer,而ILoadBalancer会拿着服务id去eureka中获取服务列表并保存起来。
    • 我们在loadBalencer中可以看到拉取的服务列表; 

  • getServer(loadBalancer):利用内置的负载均衡算法,从服务列表中选择一个。本例中,可以看到获取了8082端口的服务

放行后,再次访问并跟踪,发现获取的是8081:

果然实现了负载均衡。

5.负载均衡策略IRule

在刚才的代码中,可以看到获取服务使通过一个getServer方法来做负载均衡:

 我们继续跟入:

继续跟踪源码chooseServer方法,发现这么一段代码:

 

 我们看看这个rule是谁:

这里的rule默认值是一个RoundRobinRule,看类的介绍:

这不就是轮询的意思嘛。到这里,整个负载均衡的流程我们就清楚了。

总结

SpringCloudRibbon的底层采用了一个拦截器,拦截了RestTemplate发出的请求,对地址做了修改。用一幅图来总结一下:

基本流程如下:

1.拦截我们的RestTemplate请求http://userservice/user/1
2.RibbonLoadBalancerClient会从请求url中获取服务名称,也就是user-service
3.DynamicServerListLoadBalancer根据user-service到eureka拉取服务列表
4.eureka返回列表,localhost:8081、localhost:8082
5.IRule利用内置负载均衡规则,从列表中选择一个,例如localhost:8081
6.RibbonLoadBalancerClient修改请求地址,用localhost:8081替代userservice,得到http://localhost:8081/user/1,发起真实请求。

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

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

相关文章

Java奠基】运算符的讲解与使用

目录 运算符与表达式的使用 算术运算符 隐式转换与强制转换 自增自减运算符 赋值运算符 关系运算符 逻辑运算符 三元运算符 运算符与表达式的使用 运算符是指&#xff1a;对字面量或者变量进行操作的符号。 表达式是指&#xff1a;用运算符把字面量或者变量连接起来&…

使用Geth搭建多节点私有链

使用Geth搭建多节点私有链 步骤 1.编辑初始化配置文件genesis.json {"config": {"chainId": 6668,"homesteadBlock": 0,"eip150Block": 0,"eip150Hash": "0x000000000000000000000000000000000000000000000000000000…

【工具插件类教学】UnityPackageManager私人定制资源工具包

目录 一.UnityPackageManager的介绍 二.package包命名 三.包的布局 四.生成清单文件 五.制作package内功能 六.为您的软件包撰写文档 1.信息的结构 2.文档格式 七.提交上传云端仓库 1.生成程序集文件 2.上传至云端仓库 八.下载使用package包 1.获取包的云端路径 …

Vue3 企业级项目实战:认识 Spring Boot

Vue3 企业级项目实战 - 程序员十三 - 掘金小册Vue3 Element Plus Spring Boot 企业级项目开发&#xff0c;升职加薪&#xff0c;快人一步。。「Vue3 企业级项目实战」由程序员十三撰写&#xff0c;2744人购买https://s.juejin.cn/ds/S2RkR9F/ 越来越流行的 Spring Boot Spr…

NJ+SCU42做Modbus RTU从站

NJSCU42做Modbus RTU从站实验时间&#xff1a;2023.2.28 硬件设备&#xff1a;NJ501-1300&#xff0c;CJ1W-SCU42 软件&#xff1a;Sysmac Studio&#xff0c;Commix串口调试助手 案例简介&#xff1a;发送Modbus RTU命令读取NJ里的数据 1. 系统概述 264 ​ 本次实验使用C…

回暖!“数”说城市烟火气背后

“人间烟火气&#xff0c;最抚凡人心”。在全国各地政策支持以及企业的积极生产运营下&#xff0c;经济、社会、生活各领域正加速回暖&#xff0c;“烟火气”在城市中升腾&#xff0c;信心和希望正在每个人心中燃起。 发展新阶段&#xff0c;高效统筹经济发展和公共安全&#…

[文件操作] File 类的用法和 InputStream, OutputStream 的用法

能吃是不是件幸福的事呢 文章目录前言1. 文件的相关定义2. 文件类型3. Java对文件系统的操作3.1 对文件的基础操作3.2 读文件3.3 写文件前言 从这章开始,我们就开始学文件操作相关的知识了~ 1. 文件的相关定义 1.文件的定义可以从狭义和广义两个方面解释. 狭义: 指硬盘上的文…

进程、线程、协程详解

目录 前言&#xff1a; 一、进程 进程的概念 进程内存空间 二、线程 线程的定义 内核线程 用户线程 内核线程和用户线程的比较 线程的状态 三、协程 协程的定义 协程序相对于线程优势 运用场景 四、线程、协程、进程切换比较 前言&#xff1a; 有时候无法…

原生JS实现拖拽排序

拖拽&#xff08;这两个字看了几遍已经不认识了&#xff09; 说到拖拽&#xff0c;应用场景不可谓不多。无论是打开电脑还是手机&#xff0c;第一眼望去的界面都是可拖拽的&#xff0c;靠拖拽实现APP或者应用的重新布局&#xff0c;或者拖拽文件进行操作文件。 先看效果图&am…

人力资源管理系统

技术&#xff1a;Java、JSP等摘要&#xff1a;在当今的信息化社会&#xff0c;为了更有效率地工作&#xff0c;人们充分利用现在的电子信息技术&#xff0c;在办公室架设起办公服务平台&#xff0c;将人力资源相关信息统一起来管理&#xff0c;帮助管理者有效组织降低成本和加速…

测试2年,当初一起入行的朋友很多月薪20k了,自己却还没过万,到底差在了哪里?

说来奇怪&#xff0c;不管是读书还是工作&#xff0c;都存在一个现象&#xff0c;那就是人比人&#xff0c;比死人。读书的时候&#xff0c;不管是老师还是家长口中&#xff0c;总会有一个“别人家的孩子”。同样&#xff0c;到工作中&#xff0c;领导口中总会有一个“别人的员…

代码随想录算法训练营day46 | 动态规划之背包问题 139.单词拆分

day46139.单词拆分1.确定dp数组以及下标的含义2.确定递推公式3.dp数组如何初始化4.确定遍历顺序5.举例推导dp[i]139.单词拆分 题目链接 解题思路&#xff1a;单词就是物品&#xff0c;字符串s就是背包&#xff0c;单词能否组成字符串s&#xff0c;就是问物品能不能把背包装满。…

【微服务】-认识微服务

目录 1.1 单体、分布式、集群 单体 分布式 集群 1.2 系统架构演变 1.2.1 单体应⽤架构 1.2.2 垂直应⽤架构 1.2.3 分布式架构 1.2.4 SOA架构 1.2.5 微服务架构 1.3 微服务架构介绍 微服务架构的常⻅问题 1.4 SpringCloud介绍 1.4.1 SpringBoot和SpringCloud有啥关…

高压放大器知识科普介绍

高压放大器是一种用于放大高压信号的电子设备&#xff0c;具有高压输出&#xff0c;低噪声&#xff0c;高精度&#xff0c;高稳定性&#xff0c;高可靠性&#xff0c;低功耗&#xff0c;低成本等的优点&#xff0c;所以才被广泛应用在磁场探测、电磁脉冲放大、电磁波放大、电磁…

Arduino IDE启动闪退或者运行中闪退

文章目录一、你中了哪一种&#xff1f;1、安装了不符合规格的库文件2、安装了不符合规范的开发板库文件二、解决方案1、轻方案2、全盘重来Arduino IDE启动闪退或者运行中闪退&#xff0c;出现这样的问题&#xff0c;其实不需要思考了&#xff0c;就是运行库配置的问题&#xff…

(Trie Tree)字典树

&#xff08;Trie Tree&#xff09;字典树 场景&#xff1a;在n个字符串中查找某个字符串。 暴力匹配&#xff0c;时间复杂度为O&#xff08;nm&#xff09;&#xff0c;m为字符串平均长度&#xff0c;效率过低。 字典查找单词"fly"&#xff0c;首先查找’f’,然后…

HACKTHEBOX——Teacher

nmapnmap -sV -sC -p- -T4 -oA nmap 10.10.10.153nmap只发现了对外开放了80端口&#xff0c;从http-title看出可能是某个中学的官网http打开网站确实是一个官网&#xff0c;查看每个接口看看有没有可以利用的地方发现了一个接口&#xff0c;/images/5.png&#xff0c;但是响应包…

【计算机二级python】综合题目

计算机二级python真题 文章目录计算机二级python真题题目一&#xff1a;全球大学排名题目二&#xff1a;红楼梦题目一&#xff1a;全球大学排名 在省略号处填写一行或多行代码&#xff0c;完成如下功能‪‬‪‬‪‬‪‬‪‬‮‬‭‬‪‬‪‬‪‬‪‬‪‬‪‬‮‬‫‬‭‬‪‬‪…

web,h5海康视频接入监控视频流记录三(后台node取流)

前端vue&#xff0c;接入ws视频播放 云台控制 &#xff0c;回放预览&#xff0c;都是需要调对应的海康接口。相当于&#xff0c;点击时&#xff0c;请求后台写好的接口&#xff0c;接口再去请求海康的接口 调用云台控制是&#xff0c;操作一次&#xff0c;不会自己停止&#x…

SpringBoot+Nacos+OpenFeign环境搭建

目录 1.boot方式nacos与openFeign集成 1.引入依赖 2.添加配置 3.测试接口调用 4.常见问题&#xff1a; 1.版本依赖 2.nacos客户端 2.cloud方式nacos与openFeign集成 1.引入依赖 2.添加配置 3.接口定义 4.开启FeignClients客户端 5.远程接口测试 6.Nacos配置中心 1…