【微服务 SpringCloud】实用篇 · Ribbon负载均衡

微服务(4)

在这里插入图片描述

文章目录

  • 微服务(4)
    • 1. 负载均衡原理
    • 2. 源码跟踪
      • 1)LoadBalancerIntercepor
      • 2)LoadBalancerClient
      • 3)负载均衡策略IRule
      • 4)总结
    • 3. 负载均衡策略
      • 3.1 负载均衡策略
      • 3.2 自定义负载均衡策略
    • 4. 饥饿加载

微服务(4)

在前面,我们添加了@LoadBalanced注解,即可实现负载均衡功能,这是什么原理、什么策略呢?

1. 负载均衡原理

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

在这里插入图片描述

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

2. 源码跟踪

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

Ribbon是怎么拦截这个请求,并将url进行处理的呢?

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

我们进行源码跟踪(双击shift搜索):

在这里插入图片描述

1)LoadBalancerIntercepor

调试一下:

在这里插入图片描述

打个断点:

在这里插入图片描述

浏览器访问:

在这里插入图片描述

停在这了:

在这里插入图片描述

跳两步观察:

在这里插入图片描述

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

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

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

在这里插入图片描述

2)LoadBalancerClient

继续跟入execute方法,调用getLoadBalancer方法:

在这里插入图片描述

调用getServer方法:

在这里插入图片描述

这个就是我们的内网ip(命令行cmd,ipconfig查看)

在这里插入图片描述

代码是这样的:

  • getLoadBalancer(serviceId):根据服务id获取ILoadBalancer,而ILoadBalancer会拿着服务id去eureka中获取服务列表并保存起来。
  • getServer(loadBalancer):利用内置的负载均衡算法,从服务列表中选择一个。本例中,可以看到获取了8081端口的服务

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

在这里插入图片描述

果然实现了负载均衡。

3)负载均衡策略IRule

跟进getServer方法:

进入方法内部:

在这里插入图片描述

  • 通过规则选择

在这里插入图片描述

IRule,故名思意就是规则接口,想必就是负载均衡算法的规则取决于它

在这里插入图片描述

可见IRule接口有很多的实现

最明显的就是RandomRule,顾名思义就是随机;RoundRobinRule,顾名思义就是轮询调度

而现在的规则是:ZoneAvoidanceRule

在这里插入图片描述

key是default(其实就是尝试从配置文件里获取常量,没有配置就获取不到,就默认咯)

我们看看这个rule是谁:

在这里插入图片描述

这不就是轮询的意思嘛。

到这里,整个负载均衡的流程我们就清楚了,至于这些策略规则是什么,随后讲解~

4)总结

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

在这里插入图片描述

基本流程如下:

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

3. 负载均衡策略

3.1 负载均衡策略

负载均衡的规则都定义在IRule接口中,而IRule有很多不同的实现类:

在这里插入图片描述

不同规则的含义如下:

内置负载均衡规则类规则描述
RoundRobinRule简单轮询服务列表来选择服务器。
AvailabilityFilteringRule对以下两种服务器进行忽略: (1)在默认情况下,这台服务器如果3次连接失败,这台服务器就会被设置为“短路”状态。短路状态将持续30秒,如果再次连接失败,短路的持续时间就会几何级地增加。 (2)并发数过高的服务器。如果一个服务器的并发连接数过高,配置了AvailabilityFilteringRule规则的客户端也会将其忽略。并发连接数的上限,可以由客户端的..ActiveConnectionsLimit属性进行配置。
WeightedResponseTimeRule为每一个服务器赋予一个权重值。服务器响应时间越长,这个服务器的权重就越小。这个规则会随机选择服务器,这个权重值会影响服务器的选择。
ZoneAvoidanceRule以区域可用的服务器为基础进行服务器的选择。使用Zone对服务器进行分类,这个Zone可以理解为一个机房、一个机架等。而后再对Zone内的多个服务做轮询。(如果没有Zone的划分,其实就是跟普通轮询没啥区别)
BestAvailableRule忽略那些短路的服务器,并选择并发数较低的服务器。
RandomRule随机选择一个可用的服务器。
RetryRule重试机制的选择逻辑

默认的实现就是ZoneAvoidanceRule,是一种轮询方案

默认情况下,浏览器依次访问101、102、103、104,查看日志:(右侧栏有个垃圾桶,点击清空日志)

在这里插入图片描述

其实每次都这样(一个2 4;一个1 3),就是轮询策略~

3.2 自定义负载均衡策略

通过定义IRule实现可以修改负载均衡规则,有两种方式

  1. 代码方式:在order-service中的OrderApplication类中,定义一个新的IRule:
    • 那么ribbon就会以这个bean的规则优先
@Bean
public IRule randomRule(){return new RandomRule();
}

效果:

在这里插入图片描述

每次都不一样,甚至会出现有一个服务一个都没有,很明显是随机(次数多了还每个服务的调用次数是很均衡的)

  1. 配置文件方式:在order-service的application.yml文件中,添加新的配置也可以修改规则:
userservice: # 给某个微服务配置负载均衡规则,这里是userservice服务ribbon:NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule # 负载均衡规则 

在这里插入图片描述

效果一致~

注意,一般用默认的负载均衡规则,不做修改。

  1. 配置文件的设置优先级较高,如果代码方法设置的是A,配置方法设置的是B,则最终呈现是B
  2. 代码设置的是全局的方案,也就是说在order-service访问哪个微服务的都是这个规则
  3. 配置设置的是特定的微服务负载均衡规则(优先级高也正常了)
    • 从配置设置的键(userservice)可见,是针对一个微服务的

4. 饥饿加载

不知道你有没有发现,我们浏览器测试刚才的用例的时候,第一次要反应一会儿,后面的就很流畅:

我们通过浏览器开发者工具来看看第一次访问的时候的时间:

在这里插入图片描述

达到恐怖的744ms!

而之后就比较快了:

在这里插入图片描述

这是因为:

  • Ribbon默认是采用懒加载,即第一次访问时才会去创建LoadBalanceClient,请求时间会很长。

在这里插入图片描述

  • 严格来说是第一次用到这个服务的LoadBalanceClient才会加载
  • 加载之后就缓存下来了,可以直接用或者下一次拉取直接赋值给这个对象就行了
    • 当然,如果是别的服务的LoadBalanceClient,还需要加载

饥饿加载则会在项目启动时创建,降低第一次访问的耗时,通过下面配置开启饥饿加载:

ribbon:eager-load:enabled: true # 默认false为懒加载,这里设置为true为饥饿加载clients: userservice # 指定对哪个微服务饥饿加载

在这里插入图片描述

  • clients的值是一个集合,可以这么写:

在这里插入图片描述

重启

在这里插入图片描述

  • 可见已经加载

观察一下时间:

在这里插入图片描述

第一次访问快了不少了(第一次也要加载一些框架之类的,当然也可以设置为饥饿加载,不在这里演示)


文章到此结束!谢谢观看
可以叫我 小马,我可能写的不好或者有错误,但是一起加油鸭🦆

代码:cloud-demo · 游离态/云服务 - 码云 - 开源中国 (gitee.com)


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

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

相关文章

C++前缀和算法的应用:向下取整数对和 原理源码测试用例

本文涉及的基础知识点 C算法&#xff1a;前缀和、前缀乘积、前缀异或的原理、源码及测试用例 包括课程视频 题目 向下取整数对和 给你一个整数数组 nums &#xff0c;请你返回所有下标对 0 < i, j < nums.length 的 floor(nums[i] / nums[j]) 结果之和。由于答案可能会…

Kubeadm部署k8s集群 kuboard

目录 主机准备 主机配置 修改主机名&#xff08;三个节点分别执行&#xff09; 配置hosts&#xff08;所有节点&#xff09; 关闭防火墙、selinux、swap、dnsmasq(所有节点) 安装依赖包&#xff08;所有节点&#xff09; 系统参数设置(所有节点) 时间同步(所有节点) 配…

(转)c 多张图片生成avi视频

https://www.cnblogs.com/songhe364826110/p/7619949.html 修改了几个参数&#xff0c;可以生成视频了。下载主要是为了学习avi视频格式。最后编一个摄像头生成视频的程序。 本程序把标准avi 视频格式的各种数据结构自定义在文件头(JpegAVI.h)中&#xff0c;所以就不用去下载…

Java面试题-UDP\TCP\HTTP

UDP UDP特性 &#xff08;1&#xff09;UDP是无连接的&#xff1a;发送数据之前不需要像TCP一样建立连接&#xff0c;也不需要释放连接&#xff0c;所以减少了发送和接收数据的开销 &#xff08;2&#xff09;UDP 使用尽最大努力交付&#xff1a;即不保证可靠交付 &#xff0…

Java开发规范记录

不要使用 count(column)或 count(1)来替代 count(*)&#xff0c;count(*)是 SQL92 定义的 标准统计行数的语法&#xff0c;跟数据库无关&#xff0c;跟 NULL 和非 NULL 无关。 注意&#xff1a;count(*)会统计值为 NULL 的行&#xff0c;而 count(列名)不会统计此列为 NULL 值的…

高级深入--day35

反反爬虫相关机制 Some websites implement certain measures to prevent bots from crawling them, with varying degrees of sophistication. Getting around those measures can be difficult and tricky, and may sometimes require special infrastructure. Please consi…

Java面向对象(基础)--package和import关键字的使用

文章目录 一、package关键字的使用1. 说明2. 包的作用3. JDK中主要的包 二、import关键字的使用 一、package关键字的使用 1. 说明 package:包package用于指明该文件中定义的类、接口等结构所在的包。语法格式 举例&#xff1a;pack1\pack2\PackageTest.java package pack1.…

Xshell+screen解决ssh连接 服务器掉线的问题

Linux screen命令解决SSH远程服务器训练代码断开连接后运行中断_linux screen ssh-CSDN博客 Linux命令之screen命令_linux screen_恒悦sunsite的博客-CSDN博客 使用教程&#xff1a; 这里粗略介绍一下 &#xff08;1&#xff09;xshell xftp&#xff08;xshell点这个&#…

Git合并某个分支上的某个提交

1. 首先&#xff0c;确保你当前所在的分支是你要合并分支的父分支。你可以使用以下命令切换到父分支&#xff1a; git checkout <父分支名称> 2. 确保你要合并的分支是可用的。你可以使用以下命令查看所有可用的分支&#xff1a; git branch -a 这将显示所有本地和远程…

组合数(递推版)的初始化

初始考虑为将第一列数和斜对角线上的数进行初始化。 橙色方块由两个绿色方块相加而来&#xff0c;一个为1&#xff0c;一个为0&#xff0c;所以斜对角线都为1&#xff0c;可以通过计算得来&#xff0c;不需要初始化&#xff0c;需要与码蹄集盒子与球 第二类Stirling数&#xf…

Sobel算子详解及例程

Sobel算子是一种经典的边缘检测算子&#xff0c;被广泛应用于图像处理领域。它基于图像亮度的变化率来检测边缘的位置&#xff0c;主要通过计算图像中像素点的梯度来实现。 Sobel算子分为水平和垂直两个方向的算子&#xff0c;记作Gx和Gy。它们分别对图像进行水平和垂直方向的…

Go并发编程之一

一、前言 新年学新语言Go系列文章已经完结&#xff0c;用了最简单的例子去了解Go基础语法&#xff0c;但Go最牛B的是它对并发的友好支持&#xff0c;每一门语言都有它自己独特的优势&#xff0c;如Java适合大型工程化项目&#xff0c;Python适合做数据分析及运维脚本&#xff0…

✔ ★【备战实习(面经+项目+算法)】 10.21学习时间表(总计学习时间:5h30min)(算法刷题:7道)

✔ ★【备战实习&#xff08;面经项目算法&#xff09;】 坚持完成每天必做如何找到好工作1. 科学的学习方法&#xff08;专注&#xff01;效率&#xff01;记忆&#xff01;心流&#xff01;&#xff09;2. 每天认真完成必做项&#xff0c;踏实学习技术 认真完成每天必做&…

工具篇之Axure RP 10的使用

引言 最近在学习原型图&#xff0c;针对画原型图的工具&#xff0c;反复对比墨刀、Axure、xiaopiu后&#xff0c;最终选择Axure。 接下来&#xff0c;我便从Axure RP 10的下载、安装、中文字体、授权等几个方面&#xff0c;来介绍Axure。 一、背景 Axure是一款强大的原型设计…

分布式缓存选型比较:Memcache VS Redis

分布式缓存比较&#xff1a;Memcache VS Redis 1、Redis不仅仅支持简单的k/v类型的数据&#xff0c;同时还提供list&#xff0c;set&#xff0c;zset&#xff0c;hash等数据结构的存储。而memcache只支持简单数据类型&#xff0c;需要客户端自己处理复杂对象 2、Redis支持数据的…

华为OD技术面试-最短距离矩阵(动态规划、广度优先)

背景 记录2023-10-21 晚华为OD三面的手撕代码题&#xff0c;当时没做出来&#xff0c;给面试官说了我的想法&#xff0c;评价&#xff1a;解法复杂了&#xff0c;只是简单的动态规范 或 广度优先算法&#xff0c;事后找资料记录实现方式。 题目 腐烂的橘子 问题描述&#xff…

[SQL | MyBatis] MyBatis 简介

目录 一、MyBatis 简介 1、MyBatis 简介 2、工作流程 二、入门案例 1、准备工作 2、示例 三、Mapper 代理开发 1、问题简介 2、工作流程 3、注意事项 4、测试 四、核心配置文件 mybatis-config.xml 1、environment 2、typeAilases 五、基于 xml 的查询操作 1、…

EtherCAT主站SDO写报文抓包分析

0 工具准备 1.EtherCAT主站 2.EtherCAT从站&#xff08;本文使用步进电机驱动器&#xff09; 3.Wireshark1 抓包分析 1.1 报文总览 本文设置从站1的对象字典&#xff0c;设置对象字典主索引为0x2000&#xff0c;子索引为0x00&#xff0c;设置值为1500。主站通过发送SDO写报文…

STM32-LCD液晶显示

目录 LCD液晶显示 ILI9341液晶控制器简介 液晶屏的信号线和8080时序 使用STM32的FSMC外设模拟8080接口时序 FSMC 功能框图 通讯引脚 存储器控制器 时钟控制逻辑 FSMC的地址映射 FSMC控制异步Nor Flash的时序 FSMC模拟8080时序 FSMC结构体 NOR FLASH时序结构体 F…

由Django-Session配置引发的反序列化安全问题

漏洞成因 漏洞成因位于目标配置文件settings.py下 关于这两个配置项 SESSION_ENGINE&#xff1a; 在Django中&#xff0c;SESSION_ENGINE 是一个设置项&#xff0c;用于指定用于存储和处理会话&#xff08;session&#xff09;数据的引擎。 SESSION_ENGINE 设置项允许您选择不…