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

news2024/12/31 5:00:18

目录

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 {
 @Autowired
 private OrderDao orderDao;
 @Autowired
 private DiscoveryClient discoveryClient;
 @Autowired
 private RestTemplate restTemplate;
 @Override
 public 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实现负载均衡

Ribbon Spring Cloud 的⼀个组件, 它可以让我们使⽤⼀个注解就能轻松的搞定负载均衡
1. RestTemplate 的⽣成⽅法上添加 @LoadBalanced 注解
/**
     * @LoadBalanced就可以实现负载均衡,原理就是一个标记,标记Resttemplate发出的请求要被我们的Ribbon进行拦截和处理
     * */
    @LoadBalanced
    @Bean
    public RestTemplate restTemplate(){
        return new RestTemplate();
    }
2. 修改 OrderServiceImpl服务调⽤的⽅法        
@Service
@Slf4j
public class OrderServiceImpl implements OrderService {
 @Autowired
 private OrderDao orderDao;
 @Autowired
 private RestTemplate restTemplate;
 @Override
 public 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 {
 @Autowired
 private 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.coloradmin.cn/o/380346.html

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

相关文章

环境搭建04-Ubuntu16.04更改conda,pip的镜像源

我常用的pipy国内镜像源&#xff1a; https://pypi.tuna.tsinghua.edu.cn/simple # 清华 http://mirrors.aliyun.com/pypi/simple/ # 阿里云 https://pypi.mirrors.ustc.edu.cn/simple/ #中国科技大学1、将conda的镜像源修改为国内的镜像源 先查看conda安装的信息…

【shell 编程大全】sed详解

sed详解1. 概述 今天单独拉出一章来讲述下sed命令。因为sed命令确实内容太多&#xff0c;不过也是比较灵活的&#xff0c;好了不废话了。我们开始吧 1.2 原理解析 shell脚本虽然功能很多&#xff0c;但是它最常用的功能还是处理文本文件&#xff0c;尤其是在正常的业务操作流程…

4.3 where关键字过滤查询数据

文章目录1.使用WHERE子句2.WHERE子句操作符2.1 使用单个值2.2 不匹配检查2.3 范围值查询2.4 空值检查3.组合WHERE子句3.1 AND操作符3.2 OR操作符3.3 计算次序4.IN操作符5.NOt关键字&#xff15;.注意事项&#xff15;.1 NULL与不匹配&#xff15;.2 SQL过滤与应用过滤&#xff…

【RSA】HTTPS中SSL/TLS握手时RSA前后端加密流程

SSL/TLS层的位置 SSL/TLS层在网络模型的位置&#xff0c;它属于应用层协议。接管应用层的数据加解密&#xff0c;并通过网络层发送给对方。 SSL/TLS协议分握手协议和记录协议&#xff0c;握手协议用来协商会话参数&#xff08;比如会话密钥、应用层协议等等&#xff09;&…

QT中级(6)基于QT的文件传输工具(2)

QT中级&#xff08;6&#xff09;基于QT的文件传输工具&#xff08;2&#xff09;本文实现第一步1 新增功能2 运行效果3 实现思路4 源代码实现这个文件传输工具大概需要那几步&#xff1f;实现多线程对文件的读写实现TCP客户端和服务端实现网络传输 书接上回&#xff1a;QT中级…

27k入职阿里测开岗那天,我哭了,这5个月付出的一切总算没有白费~

先说一下自己的个人情况&#xff0c;计算机专业&#xff0c;16年普通二本学校毕业&#xff0c;经历过一些失败的工作经历后&#xff0c;经推荐就进入了华为的测试岗&#xff0c;进去才知道是接了个外包项目&#xff0c;不太稳定的样子&#xff0c;可是刚毕业谁知道什么外包不外…

沸点 | 实时图数据库技术将赋能银行数字化转型——访同心尚科技总裁王昊

实时图数据库技术将赋能银行数字化转型 ——访同心尚科技总裁王昊 本报记者 赵萌 全国两会召开在即&#xff0c;近日&#xff0c;在多家媒体或研究机构的两会热点话题预测中&#xff0c;“科技创新”“数字经济”位列其中。如何更好发挥信息科技对支持实体经济发展的放大、叠加…

【运维有小邓】Oracle数据库审计

一些机构通常将客户记录、信用卡信息、财务明细之类的机密业务数据存储在Oracle数据库服务器中。这些数据存储库经常因为内部安全漏洞和外部安全漏洞而受到攻击。对这类敏感数据的任何损害都可能严重降低客户对机构的信任。因此&#xff0c;数据库安全性对于任何IT管理员来说都…

webpack.config.js与package.json文件的配置

path要使用绝对路径&#xff0c;通过每次复制文件位置非常麻烦且容易导致问题 使用node中的 写个包名跟入口名称&#xff0c;其他全部回车 此步完成后&#xff0c;自动生成一个package.json包 licence指的是开源&#xff0c;一般不写 安装文件夹需要的依赖 dirname是node自带…

图注意网络GAT理解及Pytorch代码实现【PyGAT代码详细注释】

文章目录GAT代码实现【PyGAT】GraphAttentionLayer【一个图注意力层实现】用上面实现的单层网络测试加入Multi-head机制的GAT对数据集Cora的处理csr_matrix()处理稀疏矩阵encode_onehot()对label编号build graph邻接矩阵构造GAT的推广GAT 题&#xff1a;Graph Attention Netwo…

Netty之ChannelFuture详解

目录 目标 Netty版本 Netty官方API 客户端如何与服务器建立连接&连接成功后的操作方式 实现 如何处理客户端与服务器连接关闭后的操作 正确关闭连接的方式 方法一 方法二 目标 了解Netty如何处理客户端与服务器之间的连接与关闭问题。 Netty版本 <dependency&…

Kafka系列之:Kafka生产者和消费者

Kafka系列之:Kafka生产者和消费者 一、Kafka生产者发送流程二、提高生产者吞吐量三、Kafka消费方式四、Kafka消费者总体工作流程五、按照时间消费Kafka Topic一、Kafka生产者发送流程 batch.size:只有数据积累到batch.size之后,sender才会发送数据,默认16K。linger.ms:如果…

预热:Eyeshot 2023 Beta 正式版不远 Eyeshot 2023 Fem

预热&#xff1a;Eyeshot 2023 Beta 离正式版不远 Eyeshot 2023 Fem 破解版 devDept Software 自豪地宣布推出新的Eyeshot 2023 Beta版本。 现在已经完成了几次迁移&#xff0c;我们有了一个最终的工作区架构&#xff0c;它不再需要设计/设计用户界面分离的对象。正如我们在迁移…

SMPL可视化大杀器,你并不需要下载SMPL就能可视化你的3D Pose

SMPL 是一种3D人体建模方法&#xff0c;现在几乎所有的元宇宙人体建模都是基于此类方法&#xff0c;包括但不限于元宇宙&#xff0c;自动驾驶等领域。它能估计出比较准确的人体3D姿态&#xff0c;得益于海量数据训练的人体3D先验。不仅仅是人体&#xff0c;包括手部&#xff0c…

【Windows应急响应】HW蓝队必备——开机启动项、临时文件、进程排查、计划任务排查、注册表排查、恶意进程查杀、隐藏账户、webshell查杀等

Windows应急响应应急响应的重要性开机启动项temp文件分析浏览器信息分析文件时间属性分析最近打开文件分析进程分析计划任务隐藏账户的发现添加与删除恶意进程发现及关闭补丁信息webshell查杀应急响应的重要性 近年来信息安全事件频发&#xff0c;信息安全的技能、人才需求大增…

linux + jenkins + svn + maven + node 搭建及部署springboot多模块前后端服务

linux搭建jenkins 基础准备 linux配置jdk、maven&#xff0c;配置系统配置文件 vi /etc/profile配置jdk、maven export JAVA_HOME/usr/java/jdk1.8.0_261-amd64 export CLASSPATH.:$JAVA_HOME/jre/lib/rt.jar:$JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jarexport MAVEN_H…

【深入浅出 Yarn 架构与实现】4-6 RM 行为探究 - 申请与分配 Container

本小节介绍应用程序的 ApplicationMaster 在 NodeManager 成功启动并向 ResourceManager 注册后&#xff0c;向 ResourceManager 请求资源&#xff08;Container&#xff09;到获取到资源的整个过程&#xff0c;以及 ResourceManager 内部涉及的主要工作流程。 一、整体流程 …

吴恩达机器学习笔记——线性回归

1.模型描述有训练集数据房子面积和卖出的价钱&#xff0c;我们用这组数据来模拟特定面积的房子能够卖出的价钱。这是一个很明显的监督学习&#xff08;supervised learning&#xff09;的例子&#xff0c;因为我们的训练集里包含了正确的结果&#xff08;即房子的卖价&#xff…

非递归迭代实现二叉树前序,中序,后序遍历

文章目录1. 前序遍历2. 中序遍历3. 后序遍历1. 前序遍历 题目链接 解题思路&#xff1a; 非递归遍历一棵树有两点&#xff1a; 1.左路结点 2.左路结点的右子树 什么意思呢&#xff1f; 我们知道前序遍历是按照根&#xff0c;左子树&#xff0c;右子树来的。所以它是先根&…

js中的原型链

js中原型和原型链&#x1f61a; 1、为什么需要原型链&#xff1f;&#x1f923;&#x1f61a; 凡事都是有一定的需求和原因发展起来的&#xff0c;在ECMA中为什么要提出原型链这个概念呢&#xff1f; 我们知道&#xff0c;创建对象有两种方式。一种是通过字面量来创建&#…