基于 Eureka 的 Ribbon 负载均衡实现原理【SpringCloud 源码分析】

目录

一、前言

二、源码分析

三、负载均衡策略


一、前言

如下图,我们在 orderserver 中通过 restTemplate 向 usersever 发起 http 请求,在服务拉取的时候,主机名 localhost 是用服务名 userserver 代替的,那么该 url 是一个可访问的网络地址吗?


 

我们在浏览器中访问一下这个地址,果然不可用。

那么它又是怎么访问到 userserver 数据的?别忘了我们的服务都是注册在 Eureka 上的,那肯定是拿着服务名去找 Eureka 要人了对不对?找到服务之后把具体的主机名替换掉就OK了。

实际上,我们可能有多个 userserver 同时注册在 Eureka 上,这时候 orderserver 要去 Eureka 上拉取服务的时候,拉取到的就不只是一个 userserver 服务了,它应该是一个服务列表,那么最终执行的时候肯定是只交给一个服务去做,到底要交给谁呢?没错,这就是我们本篇要说的 —— Ribbon,用它来实现多服务的负载均衡。

二、源码分析

上一篇文章中,提到了 @LoadBalanced 注解,我们说用它可以开启负载均衡。这个注解其实就是一个标记,标记 RestTemplate 发起的请求要被 Ribbon 拦截并处理。

那个这个拦截动作具体是谁来做的呢?Ctrl + Shift + N,搜索 LoadBalancerInterceptor,点击第一个。

我们可以打断点 debug,可以看到 request.getURI() 这一步是在获取请求路径,也就是我们上面说的那个不可用的 url。

F8 快捷键下一步,originalUri.getHost() 应该就是在获取主机名,获取到的 host 正是 userserver。

拿到了主机名,就该去找 Eureka 拉取服务了,继续往下走,发现它把该服务名称交给了 loadBalancer.execute 去执行,F7 跟进该方法。

服务列表拿到之后就准备负载均衡了,F7 进入方法内部,我们发现它调用了 chooseServer 方法,翻译一下:选择服务。从刚才拉取到的服务列表中选择一个出来?

继续 F7 进入 chooseServer 方法,可以看到它又去调用父类的 chooseServer 方法了。

跟进方法往下走,返回一个 rule.choose?翻译一下:选择规则。说明我们从服务列表中选择一个服务的时候也是有规则的。

光标放到 rule 上,Ctrl 加鼠标左键跟进,它原来是一个 IRule 类型的。

 

那么这个 IRule 接口有哪些具体的 Rule 呢?光标放在 IRule 上,Ctrl + H,弹出它的实现类。翻译一下:有随机规则、轮询规则等等。

拿到了真实的访问地址,并且选择了一种负载均衡策略,就可以对之前不可访问的 url 进行替换了。

整体流程:

orderserver 发起 http 请求 → 请求被 LoadBalancerInterceptor 负载均衡拦截器拦截 → RibbonLoadBalancerClient 拿到服务名,并将其作为参数传给 DynamicServerListLoadBalancer → DynamicServerListLoadBalancer 就会去 Eureka 中拉取服务列表 → 随后 DynamicServerListLoadBalancer 又会去请求 IRule 接口做负载均衡,根据规则挑一个服务出来,并返回 → RibbonLoadBalancerClient 拿到了真实的服务地址就会对之前不可访问的 url 地址进行替换,最终请求到目标服务。

三、负载均衡策略

如下图,每一个子接口都是一种规则:

默认是的负载均衡策略是 ZoneAvoidanceRule,它父类的父类是轮询的,所以本质上讲 ZoneAvoidanceRule 也是一个轮询策略,但是它是以 Zone 对服务器进行划分的,这个 Zone 可以理解为一个机房,所以在选择服务的时候,它会优先选择跟自己在同一个机房里面的服务,然后进行轮询。

那么如何修改负载均衡规则呢?有两种方式。

① 代码方式,在 orderserver 的启动类中定义一个新的 IRule(作用于全局)

@Bean
public IRule randomRule() {return new RandomRule();
}

② 配置文件方式,在 orderserver 的 yml 文件中添加新的配置(只针对某个微服务而言)

Ribbon 的默认加载机制是懒加载,所谓懒加载就是不用的时候不加载,什么时候要用了才去加载,所以服务在第一次被访问的时候速度较慢,由于 Ribbon 给我们提供了缓存,所以之后的访问速度还是很快的。

相对于懒加载的是饥饿加载,顾名思义,饥饿加载就是在项目一启动的时候就开始加载,所以它的每一次访问速度都很快。那么如何修改 Ribbon 的加载方式呢?我们可以通过配置文件的方式进行修改。

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

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

相关文章

Java动态代理JKD版本

1、ISale.java package com.atguigu; public interface ISale {void saleShaoBing();void saleJianBing();void saleYueBing();void saleManTou(); }2、WuDa.java package com.atguigu;//Target:目标类、目标对象 public class WuDa implements ISale{//target method:目标方法…

DAY60 84.柱状图中最大的矩形

84.柱状图中最大的矩形 题目要求:给定 n 个非负整数,用来表示柱状图中各个柱子的高度。每个柱子彼此相邻,且宽度为 1 。 求在该柱状图中,能够勾勒出来的矩形的最大面积。 思路 单调栈 本地单调栈的解法和接雨水的题目是遥相呼…

git -1

1.创建第一个仓库并配置local用户信息 git config git config --global 对当前用户所有仓库有效 git config --system 对系统所有登录的用户有效 git config --local 只对某个仓库有效 git config --list 显示配置 git config --list --global 所有仓库 git config --list…

微信小程序 prettier 格式化

一、安装prettier插件 二、打开设置 然后再打开setting.json 新增代码 {"editor.formatOnSave": true,"editor.defaultFormatter": "esbenp.prettier-vscode","prettier.documentSelectors": ["**/*.wxml", "**/*.wx…

基于 Glibc 版本升级的 DolphinDB 数据查询性能优化实践

在高并发查询、查询需要涉及很多个分区的情况下,低版本的 glibc(低于2.23)会严重影响查询性能。需要升级 glibc 解决该问题优化性能。我们撰写了本文,通过 patchelf 工具修改可执行文件和动态库的 rpath,达到无需升级系…

专业课140+总分420+东南大学920专业综合考研,信息学院通信专业考研分享

专业课140总分420东南大学920专业综合考研,信息学院通信专业考研分享 我是三月开始系统考研备战,寒假先看的高数全书,奈何在家效率极其低下,才草草看了前三四章。回校后学习的比较认真,每天大概保持10个小时左右&…

3分钟看完NVIDIA GPU架构及演进

近期随着 AI 市场的爆发式增长,作为 AI 背后技术的核心之一 GPU(图形处理器)的价格也水涨船高。GPU 在人工智能中发挥着巨大的重要,特别是在计算和数据处理方面。目前生产 GPU 主流厂商其实并不多,主要就是 NVIDIA、AM…

利用OpenCV实现图片中导线的识别

下面是一个需求,识别图片中的导线,要在图像中检测导线,我们需要采用不同于直线检测的方法。由于OpenCV没有直接的曲线检测函数,如同它对直线提供的HoughLines或HoughLinesP,检测曲线通常需要更多的图像处理步骤和算法&…

java io流中为什么使用缓冲流就能加快文件读写速度

FileInputStream的read方法底层确实是通过调用JDK层面的read方法,并且这个JDK层面的read方法底层是使用C语言编写的,以实现高效的文件读取功能。但是它会涉及多次内核态与操作系统交互。当我们使用FileInputStream的read方法读取文件时,首先会…

UEC++ day7

敌人NPC机制 敌人机制分析与需求 新建一个character类来作为敌人,直接建蓝图设置骨骼网格,因为敌人可能多种就不规定死,然后这个敌人肯定需要两个触发器,一个用于大范围巡逻,一个用于是否达到主角近点进行攻击 注意我…

【Flink】Process Function

目录 1、ProcessFunction解析 1.1 抽象方法.processElement() 1.2 非抽象方法.onTimer() 2、Flink中8个不同的处理函数 2.1 ProcessFunction 2.2 KeyedProcessFunction 2.3 ProcessWindowFunction 2.4 ProcessAllWindowFunction 2.5 CoProcessFunction 2.6 ProcessJo…

https和http的区别和优势

大家好,我是咕噜-凯撒,HTTP(超文本传输协议)和HTTPS(安全超文本传输协议)是用于在网络上传输数据的协议,HTTPS相比HTTP在数据传输过程中更加安全可靠,适合对数据安全性要求较高的场景…

ventoy安装操作系统

下载ventoy https://github.com/ventoy/Ventoy/releases/download/v1.0.96/ventoy-1.0.96-windows.zip 解压后执行 Ventoy2Disk 2、安装后将ISO放入U盘大的分区,通过U盘启动就可以识别到ISO镜像开始装系统

MySQL 日志管理、备份与恢复

一、MySQL 日志管理 MySQL 的日志默认保存位置为 /usr/local/mysql/data vim /etc/my.cnf [mysqld] ##错误日志,用来记录当MySQL启动、停止或运行时发生的错误信息,默认已开启 log-error/usr/local/mysql/data/mysql_error.log #指定日志的保存位置…

springboot项目基于jdk17、分布式事务seata-server-1.7.1、分库分表shardingSphere5.2.1开发过程中出现的问题

由于项目需要,springboot项目需基于jdk17环境开发,结合nacos2.0.3、分布式事务seata-server-1.7.1、分库分表shardingSphere5.2.1等,项目启动过程中出现的问题解决方式小结。 问题一: Caused by: java.lang.RuntimeException: j…

职场Excel:求和家族,不简单

说到excel函数,很多人第一时间想到的就是求和函数sum。作为excel入门级函数,sum的确是小白级的,以至于很多人对求和函数有点“误解”,觉得求和函数太简单了。 但是,你可能不知道,sum只是excel求和家族里的一…

Ubuntu22.04 交叉编译GCC13.2.0 for Rv1126

一、安装Ubuntu22.04 sudo apt install vim net-tools openssh-server 二、安装必要项 sudo apt update sudo apt upgrade sudo apt install build-essential gawk git texinfo bison flex 三、下载必备软件包 1.glibc https://ftp.gnu.org/gnu/glibc/glibc-2.38.tar.gz…

引迈-JNPF低代码项目技术栈介绍

从 2014 开始研发低代码前端渲染,到 2018 年开始研发后端低代码数据模型,发布了JNPF开发平台。 谨以此文针对 JNPF-JAVA-Cloud微服务 进行相关技术栈展示: 1. 项目前后端分离 前端采用Vue.js,这是一种流行的前端JavaScript框架&a…