详解SpringCloud微服务技术栈:强推!源码跟踪分析Ribbon负载均衡原理、Eureka服务部署

news2024/11/18 13:33:01

👨‍🎓作者简介:一位大四、研0学生,正在努力准备大四暑假的实习
🌌上期文章:详解SpringCloud微服务技术栈:认识微服务、服务拆分与远程调用
📚订阅专栏:微服务技术全家桶
希望文章对你们有所帮助

Eureka

  • 提供者与消费者
  • Eureka原理分析
  • 搭建Eureka服务
    • 搭建注册中心
    • 服务注册
    • 服务发现
  • Ribbon
    • 负载均衡原理
    • 源码跟踪原理(强推!)
      • 流程总结
    • 负载均衡策略
    • 饥饿加载

提供者与消费者

服务提供者:一次业务中,被其它微服务调用的服务(提供接口给其他微服务)
服务消费者:一次业务中,调用其它微服务的服务(调用其它微服务提供的接口)

若服务A调用服务B,服务B调用服务C,那么服务B是什么角色?

提供者与消费者的概念是相对的,一个服务既可以是提供者也可以是消费者

Eureka原理分析

上一节内容中服务调用存在问题,服务调用使用http请求,网址直接定死了,如果我们有多个服务集群,亦或是网址在后续开发过程中出现变更,就会产生不方便。如下所示:
在这里插入图片描述

我们需要解决以下三个问题:

服务消费者该如何获取服务提供者的地址信息?
如果有多个服务提供者,消费者该如何选择?
消费者如何得知服务提供者的健康状态?

而Eureka可以解决这个问题,Eureka的架构:

1、eureka-server:注册中心
2、eureka-client:
(1)服务消费者(集群)
(2)服务提供者(集群)

Eureka的作用及工作流程:

1、每个服务启动的时候,都会将注册服务信息记录在注册中心,例如端口号
2、服务信息都记住了,当服务消费者需要信息的时候,无须自己去记录,而是直接去Eureka-server中拉取,这样就可以得到服务提供者的信息
3、得到的服务提供者信息可能是个集群,包含多台服务的信息,这时候要做负载均衡去选取其中一个服务
4、消费者对提供者发起远程调用

这是核心的工作流程,另外,服务的提供者每隔30s就会向Eureka-server发送心跳续约,如果服务宕机了,那么Eureka-server就会将其剔除,这样能够保证服务消费者做远程调用的时候,能调用服务提供者都是健康的。

搭建Eureka服务

要首先Eureka服务,需要实现3点:

1、搭建注册中心(EurekaServer)
2、实现服务注册(将上一篇文章中的user-service、order-service注册到eureka)
3、实现服务发现(在order-service中完成服务拉取,然后通过负载均衡挑选一个服务,实现远程调用)

搭建注册中心

搭建EurekaServer的步骤如下:
1、创建项目,引入EurekaServer依赖:
在这里插入图片描述

	<dependencies>
        <!--Eureka服务端-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
        </dependency>
    </dependencies>

2、编写启动类,添加@EnableEurekaServer注解:

@EnableEurekaServer
@SpringBootApplication
public class EurekaApplication {
    public static void main(String[] args) {
        SpringApplication.run(EurekaApplication.class, args);
    }
}

3、添加application.yml文件,编写下列配置:

server:
  port: 10086 # 服务端口
spring:
  application:
    name: eurekaserver # 服务名称
eureka:
  client:
    service-url: # Eureka的地址信息
      defaultZone: http://localhost:10086/eureka

Eureka自己也是微服务,所以配置Eureka也需要将Eureka本身给注册。

接着就可以启动Eureka服务,访问端口可以看到其界面信息:
在这里插入图片描述
可以发现注册到Eureka的实例,现在只有它本身。

服务注册

将user-service注册到EurekaServer步骤如下:
1、将user-service项目引入spring-cloud-starter-netflix-eureka-client的依赖:

	<!--Eureka-Client依赖-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
        </dependency>

2、在application.yml文件,编写下面的配置:

spring:
  application:
    name: userservice # 服务名称
eureka:
  client:
    service-url: # Eureka的地址信息
      defaultZone: http://localhost:10086/eureka

同样的方式也可以将order-service注册。
刷新Eureka-server端网址:
在这里插入图片描述

如果你出现了java.lang.NoClassDefFoundError的问题,那可能是你的依赖导入错误了,我就不小心把依赖导入成下面这个:
在这里插入图片描述
记得要加上starter,才能被SpringBoot当成启动类。

另外,可以将user-service多次启动,模拟多实例部署,单位了避免端口冲突,需要修改端口设置:
在这里插入图片描述
在这里插入图片描述
将增加的端口也运行一下,工程看到注册了2个实例的实例列表:
在这里插入图片描述
服务注册总体来说分为两步:
1、引入eureka-client依赖
2、在application.yml中配置eureka地址

无论消费者还是提供者,引入eureka-client依赖,知道了eureka地址后,都可以完成服务注册。

服务发现

服务拉取是基于服务名称获取服务列表,然后对服务列表做负载均衡。
1、修改OrderService代码,修改访问的url路径,用服务名来代替ip、端口:

String url = "http://userservice/user/" + order.getUserId();

2、在order-service项目的启动类OrderApplication中的RestTemplate添加负载均衡注解:

	@Bean
    @LoadBalanced
    public RestTemplate restTemplate(){
        return new RestTemplate();
    }

重启OrderApplication服务,按顺序访问:
http://localhost:8080/order/101
http://localhost:8080/order/102

可以看到UserApplication与UserApplication2各做了一次数据库查询操作:
在这里插入图片描述
在这里插入图片描述
所以,服务的拉取以及负载均衡已经完成。

服务发现的实现流程总结:
1、引入eureka-client依赖
2、在application.yml中配置eureka地址
3、给RestTemplate添加@LoadBalanced注解
4、给用户提供者的服务名称远程调用

Ribbon

在上面已经实现了服务的拉取,并且验证了负载均衡。那么其原理是怎样的,什么时候做的服务拉取,又是什么时候做的负载均衡,咱们都还不知道。
而其中,负载均衡是由Ribbon组件实现的。

负载均衡原理

首先思考,url已经做了修改:

String url = "http://userservice/user/" + order.getUserId();

然而访问一下http://userservice/user/1,并不能访问到,说明它并不是真实可用的地址。因此,中间肯定有组件拦截了这个请求并且做了处理,这个组件就叫做Ribbon。
整个负载均衡的流程如下:
在这里插入图片描述
而具体到底是什么时候接受这个请求的,又是怎么去做后序工作的,需要跟踪源码来做分析。

源码跟踪原理(强推!)

1、找到LoadBalancerInterceptor类,发现它实现了ClientHttpRequestInterceptor接口:
在这里插入图片描述
2、进入这个接口,查看注释:
在这里插入图片描述

其说明的大致意思是,当客户端有http请求发出的时候,立马就会被这个接口给拦截,那大概就可以知道,当实现类调用这个接口的实现方法的时候,应该要能够实现拦截

3、再回到其实现类,在实现类中打上断点,并debug模式重启OrderApplication:
在这里插入图片描述

4、在浏览器中发起请求:http://localhost:8080/order/101,可以发现请求确实成功被拦截了
在这里插入图片描述
5、跟踪下去,可以看到它解析出了我们要请求的提供者服务端是userservice:
在这里插入图片描述
在这里插入图片描述
6、解析完了就要开始进行拉取了,在这里我们可以看到Ribbon的词眼:
在这里插入图片描述
这是一个RibbonLoadBalancerClient对象,意为Ribbon负载均衡的客户端。
7、跟入execute方法,查看其执行的底层:
在这里插入图片描述
在得到动态服务列表均衡器(DynamicServerListLoadBalancer)后,可以看到这里已经成功拉取到了服务。而getServer方法就肯定是在做负载均衡了。
8、点击进入getServer方法,可以发现这里就是在做服务器的选择了:
在这里插入图片描述
9、跟进,可以看到它在实现父类的方法,可以猜想到,服务器的选择是基于某种规则的:
在这里插入图片描述
10、找到rule的对象,这是一个接口,按住Ctrl+H找到其实现类:
在这里插入图片描述
RoundRobinRule指代轮询负载均衡,RandomRule指代随机负载均衡,这些其实在nginx里面都是接触过的,到这里为止,其实现的机理就不在这里继续跟踪了,想知道的话直接学nginx就可以了。

流程总结

1、order-service(消费者)发起请求,负载均衡拦截器LoadBalancerInterceptorRibbonLoadBalancerClient会接收请求的url,获取url中的服务id
2、RibbonLoadBalancerClient把服务id交给DynamicServerListLoadBalancer
3、DynamicServerListLoadBalancer会去eureka-server中拉取userservice,并返回服务列表
4、DynamicServerListLoadBalancer需要在服务列表中选一个,这个选择即为负载均衡,交给了一个交IRule的接口对象。
5、IRule会选择一个方法在列表中选择服务,把值返回给RibbonLoadBalancerClient
6、RibbonLoadBalancerClient将会修改url,使得其实正确的真实地址,即可在前端成功访问了。

负载均衡策略

Ribbon的负载均衡规则是一个叫做IRule的接口来定义的,每个子接口都是一种规则:
在这里插入图片描述
其中,ZoneAvoidanceRule是默认方式,其父类的父类是基于轮询的,因此也可以推测ZoneAvoidanceRule是基于轮询的。
ZoneAvoidanceRule:以区域可用的服务器为基础进行服务器的选择。使用Zone对服务器进行分类,这个Zone可以理解为一个机房、一个机架等。而后再对Zone内的多个服务做轮询。(Zone可以配置,没配置就默认所有服务都在一个Zone内)。

通过定义IRule可以修改负载均衡的规则,有2种方式:
1、代码方式:在order-service中的OrderApplication类中,定义一个新的IRule:

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

2、配置文件方式:在order-service的application.yml文件中,添加新的配置也可以修改规则:

userservice:
  ribbon:
    NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule # 负载均衡规则

测试的话大家自己多访问几次网址,看控制台就可以知道是不是随机负载均衡了。

饥饿加载

这部分看不懂就去回顾一下设计模式吧。
Ribbon默认是采用懒加载,即第一次访问时才会去创建LoadBalanceClient,请求时间会很长。
而饥饿加载则会在项目启动时创建,降低第一次访问的耗时,通过下面配置开启饥饿加载:

ribbon:
  eager-load:
    enabled: true # 开启饥饿加载
    clients: # 指定饥饿加载的服务名称
      - userservice

总结:

1、Ribbon负载均衡规则
(1)规则接口是IRule
(2)默认实现是ZoneAvoidanceRule,根据zone选择服务列表,然后轮询
2、负载均衡自定义方式
(1)代码方式:配置灵活,但修改时需要重新打包发布
(2)配置方式:直观,方便,无需重新打包发布,但是无法做全局配置
3、饥饿加载
(1)开启饥饿加载
(2)指定饥饿加载的微服务名称

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

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

相关文章

【LangChain学习之旅】—(6) 提示工程(下):用思维链和思维树提升模型思考质量

【LangChain学习之旅】—&#xff08;6&#xff09; 提示工程&#xff08;下&#xff09;&#xff1a;用思维链和思维树提升模型思考质量 什么是 Chain of ThoughtFew-Shot CoTZero-Shot CoTChain of Thought 实战CoT 的模板设计程序的完整框架Tree of Thought总结 Reference&a…

UE5 伤害数字跳出

学习视频 大体思路&#xff1a; 1.创建一个控件蓝图。 播放动画&#xff0c;K透明度&#xff0c;文本位置。 2.创建一个控件组件。 类默认值中设置。 3.在位置处创建组件实例 自定义事件略。

NVIDIA Isaac Sim 入门教程(一)

系列文章目录 前言 一、 NVIDIA Omniverse™ Isaac Sim 是什么&#xff1f; NVIDIA Omniverse™ Isaac Sim 是一款适用于 NVIDIA Omniverse™ 平台的机器人仿真工具包。Isaac Sim 具有构建虚拟机器人世界和实验的基本功能。它为研究人员和从业人员提供了创建稳健、物理精确的仿…

无法解析服务器的名称或地址/Wsl/0x80072eff/win10 WSL2问题解决Wsl 0x800701bc/Wsl:0x80041002

无法解析服务器的名称或地址 和 Wsl/0x80072eff 1.连VPN&#xff0c;推荐的VPN如下。(如一直显示无法连接&#xff0c;则推荐使用VPN) Anycast加速器 (any4ga.com) 优点&#xff1a;无限GB 缺点&#xff1a;较贵&#xff0c;通过银行卡充值9折后的价格是每月45元左右 …

JVM:双亲委派机制类加载器

JVM&#xff1a;双亲委派机制 1. 例子2. 类加载器总结3. 类加载过程4. 双亲委派模型的执行流程&#xff1a;5. 双亲委派模型的好处 1. 例子 Java运行时环境有一个java.lang包&#xff0c;里面有一个ClassLoader类 我们自定义一个String类在java.lang包下&#xff0c;下面的…

WEB 3D技术 three.js 点光源

本文的话 我们来设置一下点光源 点光源其实最直观的就是可以做萤火虫 也可以做星光 点点的效果 我们可以直接在官网中搜索 Pointlight 大家可以在官网这里看一下 其实 SpotLight 聚关灯中的属性 Pointlight 点光源也有的 我们先编写代码如下 import ./style.css import * a…

MySQL之单表查询

素材&#xff1a; 表名&#xff1a;worker-- 表中字段均为中文&#xff0c;比如 部门号 工资 职工号 参加工作 等 CREATE TABLE worker ( 部门号 int(11) NOT NULL, 职工号 int(11) NOT NULL, 工作时间 date NOT NULL, 工资 float(8,2) NOT NULL, 政治面貌 varchar(10) NO…

【Git】本地仓库管理远程库(GitHub)——clone(下载)、commit(添加到本地仓库)、push(提交到远程仓库)、pull(拉取)操作

目录 使用远程仓库的目的将本地仓库同步到git远程仓库 1.克隆远程仓库(clone)2.新建一个文件3.将工作区的文件添加到暂存区4.将暂存区的文件添加到本地仓库(commit)5.提交(同步)到远程仓库(push)6.远程库拉取到本地库(pull)7.团队协作开发和跨团队协作开发(开源项目) 使用远程…

PTA(浙大版《C语言程序设计(第3版)》题目集

PTA(浙大版《C语言程序设计&#xff08;第3版&#xff09;》题目集 学习C语言程序设计的PTA题目 目录 PTA(浙大版《C语言程序设计&#xff08;第3版&#xff09;》题目集PTA(浙大版《C语言程序设计&#xff08;第3版&#xff09;》题目集) 习题2-1 求整数均值 (10 分)输入格式:…

大型语言模型综述/总结 LLM A Survey of Large Language Models

A Survey of Large Language Model AbstractINTRODUCTIONOVERVIEW背景LLM的新兴能力LLM的关键技术GPT 系列模型的技术演进 大语言模型资源公开可用的模型检查点或 API常用语料库代码库资源 预训练数据收集架构 论文标题&#xff1a;A Survey of Large Language Model 论文地址&…

电子学会C/C++编程等级考试2023年09月(五级)真题解析

C/C++编程(1~8级)全部真题・点这里 第1题:红与黑 有一间长方形的房子,地上铺了红色、黑色两种颜色的正方形瓷砖。你站在其中一块黑色的瓷砖上,只能向相邻的黑色瓷砖移动。请写一个程序,计算你总共能够到达多少块黑色的瓷砖。 时间限制:1000 内存限制:65536 输入 包括多…

Linux的SSH远程管理和服务器之间的免密连接

目录 一、远程管理基础 1.ssh协议 2.ssh原理 3、使用ssh协议传输的命令 4.登录方法 二、免密连接 1.免密连接的原理 2.实战 一、远程管理基础 1.ssh协议 ssh协议是基于C/S机构的安全通道协议&#xff0c;通信数据进行加密处理&#xff0c;用于远程管理。 ssh的服务名…

Python文件读写与字符编码详解【第25篇—python基础知识】

文章目录 文件读写和字符编码在Python中的实现一、I/O操作概述二、文件读写实现原理与操作步骤1. 文件读写实现原理2. 文件读写操作步骤 三、文件打开模式四、Python文件操作步骤示例五、文件读取相关方法1. 读取指定长度的内容2. 读取文件中的一行内容3. 遍历打印一个文件中的…

Zookeeper使用详解

介绍 ZooKeeper是一个分布式的&#xff0c;开放源码的分布式应用程序协调服务&#xff0c;是Google的Chubby一个开源的实现&#xff0c;是Hadoop和Hbase的重要组件。它是一个为分布式应用提供一致性服务的软件&#xff0c;提供的功能包括&#xff1a;配置维护、域名服务、分布…

【搭建个人知识库-3】

搭建个人知识库-3 1 大模型开发范式1.1 RAG原理1.2 LangChain框架1.3 构建向量数据库1.4 构建知识库助手1.5 Web Demo部署 2 动手实践2.1 环境配置2.2 知识库搭建2.2.1 数据收集2.2.2 加载数据2.2.3 构建向量数据库 2.3 InternLM接入LangChain2.4 构建检索问答链1 加载向量数据…

鸿蒙应用开发学习:让page页面强制横屏

一、学习做了个适合横屏的页面但进入页面后是竖屏显示的 前几天在B站上跟着 黑马程序员的 HarmonyOS4.0开发应用教学视频学习了显式动画&#xff08;animateTo&#xff09;和属性动画&#xff08;animation&#xff09;功能&#xff0c;并参照教学视频的内容做了个小鱼动画。…

基于MOD02/MYD02获得亮度温度再转冰温

用HEG处理MOD02/MYD02,提取里面的EV_1KM_Emissive波段,band为11和12(其实就是band 31和32)。注意这里的band和output dile type 1. 获得之后,转辐射亮度。 参考:https://www.cnblogs.com/enviidl/p/16539422.html radiance_scales,和radiance_offset这两项参数代表波段…

实现STM32烧写程序-(4) BIN文件结构

简介 BIN文件是一种二进制文件格式&#xff0c;用于存储和传输二进制数据。它包含了计算机或设备可以直接读取和执行的原始二进制数据。BIN文件通常用于存储程序、固件或其他二进制数据&#xff0c;例如嵌入式系统的固件、操作系统的映像文件等。 BIN文件的起源可以追溯到计算机…

学习Vue配置代理总结

今天学习了Vue的配置代理&#xff0c;当我们想要向服务器取回来数据时就先要向服务器发送请求&#xff0c;但前端发送请求的方式也有很多种&#xff0c;首先是发送请求的鼻祖JS的XMLHttpRequest&#xff08;xhr&#xff09;&#xff0c;它操作起来相对麻烦&#xff0c;开发中也…

mysql5.7之从入门到放弃

系列文章目录 第一章 MySQL5.7之从入门到放弃 第二章 MySQL从入门到放弃之数据库体系结构与管理 第三章 MySQL基础应用之DDL、DCL、DML、DQL 第四章 MySQL之多表连接查询、AS别名、扩展内容 文章目录 系列文章目录前言一、Mysql的介绍和安装&#xff1f;1、什么是数据&#xf…