Eureka注册中心及Ribbon的源码跟踪

news2025/1/16 7:44:41

搭建的思路: 一个Eureka注册中心, 两个微服务, 一个为order-service(订单服务), 一个为user-service(用户服务), 在order-service中需要使用user-service中的方法.

步骤:

  1. 搭建 Eureka-server服务, 用于服务的消费者和提供者注册服务
  2. 向注册中心注册user-service服务
  3. 向注册中心注册order-service服务, 发送请求(此时内置Ribbon会自动的找到注册中心,获取服务)

1. 搭建eureka-server(eureka注册中心)

eureka-server,这必须是一个独立的微服务

1 引入eureka依赖

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
    <version>2.2.7.RELEASE</version>
</dependency>

2 编写启动类

给eureka-server服务编写一个启动类,一定要添加一个@EnableEurekaServer注解,开启eureka的注册中心功能:

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

3 编写配置文件

server:
  port: 10086
spring:
  application:
    name: eureka-server  # 指定服务名
eureka:
  client:
    service-url: 
      defaultZone: http://127.0.0.1:10086/eureka  # 指定注册中心

4 启动服务

启动微服务,然后在浏览器访问:http://127.0.0.1:10086

在这里插入图片描述

思考一个问题: 这里为什么Eureka注册中心还要向自己注册

原因之一: Eureka Server 也是一个微服务,在分布式架构中可能也会有多个,此时就可以实现Eureka Server 之间互相访问

2. 服务注册

1. 引入依赖

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
    <version>2.2.7.RELEASE</version>
</dependency>

2. 配置文件

在user-service中,修改application.yml文件,添加服务名称、eureka地址:

spring:
  application:
    name: userservice  # 指定服务名
eureka:
  client:
    service-url:
      defaultZone: http://127.0.0.1:10086/eureka # 指定注册中心

此时的user-service为了体现负载均衡的特点可以在idea中开两个user-service服务,来展示,具体可参考下面的笔记

idea中同一SpringBoot项目运行两次_yfs1024的博客-CSDN博客

3. 服务发现

下面,我们将order-service的逻辑修改:向eureka-server拉取user-service的信息,实现服务发现。

1 引入依赖

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
    <version>2.2.7.RELEASE</version>
</dependency>

2 配置文件

spring:
  application:
    name: orderservice  # 指定服务名
eureka:
  client:
    service-url:
      defaultZone: http://127.0.0.1:10086/eureka  # 指定注册中心

3 服务拉取和负载均衡

最后,我们要去eureka-server中拉取user-service服务的实例列表,并且实现负载均衡。

不过这些动作不用我们去做,只需要添加一些注解即可。

在order-service的OrderApplication中,给RestTemplate这个Bean添加一个@LoadBalanced注解:

RestTemplate是Spring提供的用于访问Rest服务的客户端模板工具类。它简化了和HTTP服务的交互,支持HTTP协议中所有的方法:GET、POST、PUT、DELETE。

这个一定要会, 后面虽然会使用Feign组件来发送请求, 但是与其相比RestTemplate更加的灵活

在这里插入图片描述

设置访问的url路径,用服务名代替ip、端口:

在这里插入图片描述

spring会自动帮助我们从eureka-server端,根据userservice这个服务名称,获取实例列表,而后完成负载均衡。

这里可能会有一个疑问? 为什么我写服务名就可以访问到了呢,小孩没娘说来话长, 此时就需要研究源码了

我们可以看到与直接调用相比,使用Eureka时我们只需要添加服务名即可, 此时就很灵活,比如上面说的user-service有多个服务时, 如果按照老的方式,此时就需要改代码通过路径来调用对应的服务, 而使用服务名的形式,此时底层就会自动的获取对应服务列表,然后通过负载均衡规则来选择指定的服务.

也就是为什么我们发出的请求明明是http://user-service/user/1,变成了http://localhost:8081/user/1

那么谁为我们做了这一件事儿呢? Ribbon组件

Ribbon是Netflix开源的一个负载均衡客户端,可以很好地控制HTTP和TCP客户端的行为。Spring Cloud集成了Ribbon,用于支持负载均衡。

Ribbon的主要功能有:

  1. 客户端负载均衡:Ribbon可以在客户端均衡HTTP请求或TCP流量到多个服务实例。

  2. 服务发现:Ribbon可以使用Eureka或Consul来发现服务实例清单。

  3. 断路器:Ribbon支持Hystrix熔断器来防止级联故障。

  4. können cash:Ribbon支持响应缓存。

  5. 自定义策略:Ribbon支持自定义负载均衡算法、重试机制等。

    (资料来源网络)

SpringCloud底层其实是利用了一个名为Ribbon的组件,来实现负载均衡功能的。上图对于user-service服务的底层调用的过程大致如图:

在这里插入图片描述

源码跟踪:

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

那么LoadBalancerInterceptor的作用是什么呢?我们可以看一下他的父接口ClientHttpRequestInterceptor的描述,这样就很明确了,也就是使用RestTemplate发送的http请求会被这个拦截器拦截

在这里插入图片描述

1)LoadBalancerIntercepor

在这里插入图片描述

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

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

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

2)LoadBalancerClient

继续跟入execute方法:

在这里插入图片描述

代码是这样的:

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

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

在这里插入图片描述

可以看出实现了负载均衡。

3) 负载均衡策略IRule

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

那我们看getServer方法做了什么

继续跟踪源码chooseServer方法

调用了父类的chooseServer方法,那我们看父类又做了什么

在这里插入图片描述

进入点进rule里看看里面是什么, 可见默认的规则,也是就是ZoneAvaidanceRule

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

这不就是轮询的意思嘛。

到这里,整个负载均衡的流程我们就清楚了。

总结:

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

基本流程如下:

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

负载均衡策略

I 开头的类一般都是接口, 比如这里的IRule是定义负载均衡规则的接口

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

不同规则的含义如下:

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

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

注意:Ribbon默认的负载均衡规则是RoundRobinRule, 但是默认的实现是ZoneAvoidanceRule

再看一下上面默认规则的截图: 这里的DEFAULT_RULEnew RoundRobinRule(),但是最终的规则idea给出了提示,如黄色部分

对于负载均衡的规则定义可以在服务的消费者中进行定义: 定义的形式有两种

1. 代码方式:

在order-service(消费者)中的OrderApplication类中,定义一个新的IRule:

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

2. 配置文件方式

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

注意: 配置顶格: 因为当前配置不在谁的配置下

userservice: # 给某个微服务配置负载均衡规则,这里是userservice服务
  ribbon:
    NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule # 负载均衡规则 

说明: 笔记中有一些自己在学习时候的理解,如果有误解的地方还望指正; 文中资料来自B站黑马cxy

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

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

相关文章

即时通讯开发商如何选择?

随着即时通讯开发技术进步&#xff0c;人与人之间沟通互动更加便利。同时在企业的营销过程中&#xff0c;即时聊天手机APP为企业与消费者提供了即时互动平台&#xff0c;有效增强营销效果。 企业内部沟通、电商客服沟通都是需要用到即时通讯功能。而现在开发即时通讯功能并不是…

Yolov1 源码讲解 detect.py

讲完了训练部分 接下来是检测部分 惯例看看结构 VOC_CLASS_BGR是不同类别应该用什么颜色画框容易区分&#xff0c;比如A用红色&#xff0c;B用绿色&#xff0c;不容易在途中颜色混在一起 画框框 def visualize_boxes(image_bgr, boxes, class_names, probs, name_bgr_dictNon…

这一篇LiveData掉不掉价(使用+粘性事件解决)

1. 简介 LiveData 是一种可观察的数据存储器类。与常规的可观察类不同&#xff0c;LiveData 具有生命周期感知能力&#xff0c;意指它遵循其他应用组件&#xff08;如 activity、fragment 或 service&#xff09;的生命周期。这种感知能力可确保 LiveData 仅更新处于活跃生命周…

要创建富文本内容?Kendo UI Angular组件有专门的编辑器应对!

您的Angular应用程序可能需要允许用户添加带有格式化选项的文本、图像、表格、外观样式和/或链接&#xff0c;使用Kendo UI for Angular的编辑器&#xff0c;可以轻松搞定这些&#xff01; Kendo UI for Angular是专业级的Angular UI组件库&#xff0c;不仅是将其他供应商提供…

Final关键字的使用技巧及其性能优势

文章目录 概念Final关键字的基本用法Final关键字的使用技巧Final关键字的性能优势总结 概念 Java中的final关键字用于修饰变量、方法和类&#xff0c;可以让它们在定义后不可更改&#xff0c;从而提高程序的稳定性和可靠性。此外&#xff0c;final关键字还有一些使用技巧和性能…

YAPI--撰写接口文档的平台

1 YAPI 1.1 YAPI介绍 在前后台分离开发中&#xff0c;我们前后台开发人员都需要遵循接口文档&#xff0c;所以接下来我们介绍一款撰写接口文档的平台。 YApi 是高效、易用、功能强大的 api 管理平台&#xff0c;旨在为开发、产品、测试人员提供更优雅的接口管理服务。 其官…

opencv实践之图像拼接

目录 1.简介2. 步骤2.1 特征检测与提取2.2 关键点检测2.3 关键点和描述符2.4 特征匹配2.5 比率测试2.6 估计单应性 3. 完整代码 1.简介 图像拼接是计算机视觉中最成功的应用之一。如今&#xff0c;很难找到不包含此功能的手机或图像处理API。在本 文中&#xff0c;我们将讨论如…

Ubuntu在线安装及卸载MySQL

目录 1 安装 1.1 更新包管理工具apt-get 1.2 安装MySQL服务器端 1.3 安装MySQL客户端 1.4 初始化配置 1.5 检查MySQL服务状态 2 卸载 2.1 查看MySQL依赖项 2.2 卸载mysql-common 2.3 再卸载 mysql-server-8.0 2.4 再用dpkg --list|grep mysql查看&#xff0c;还剩什么…

MySQL -- 基础

目录 1. 数据库的操作 1.1 显示当前数据库 1.2 创建数据库 1.3 使用数据库 1.4 删除数据库 2. 常用的数据类型 2.1 数值类型 2.2 字符串类型 2.3 日期类型 3. 表的操作 3.1 查看表的结构 3.2 创建表 3.4 删除表 1. 数据库的操作 1.1 显示当前数据库 show databases; 1.2…

网络安全合规-Tisax(三)

一、什么是TISAX? TISAX 可信信息安全评估与交换标准是基于ISO 27001信息安全管理体系标准和VDA-ISA信息安全评价检查表而建立的汽车行业专用信息安全标准。TISAX 为汽车行业内不同服务商提供了信息安全评估结果互认的模式&#xff0c;供应商通过了该评估&#xff0c;即意味着…

如何访问chatGPT-国内上chatGPT的方法

如何在国内使用GPT 在国内使用 GPT&#xff08;Generative Pre-trained Transformer&#xff09;技术&#xff0c;可以实现多种自然语言处理和语义分析的任务&#xff0c;如机器翻译、聊天机器人、文本生成、问答系统等。但对于许多人来说&#xff0c;如何在国内使用 GPT 技术…

Java每日一练(20230505) 递增路径、编辑距离、数据流

目录 1. 矩阵中的最长递增路径 &#x1f31f;&#x1f31f;&#x1f31f; 2. 编辑距离 &#x1f31f;&#x1f31f;&#x1f31f; 3. 数据流的中位数 &#x1f31f;&#x1f31f;&#x1f31f; &#x1f31f; 每日一练刷题专栏 &#x1f31f; Golang每日一练 专栏 Pyt…

解决修改es默认host时的问题

微信公众号也不定期更新&#xff0c; leetcode_algos_life 背景 es默认只能是在非root场景下进行启动&#xff0c;且默认host是本地地址&#xff0c;即localhost或者是127.0.0.1。 当线上部署restful服务时&#xff0c;此时如果其他服务与es服务不在同一台机器上&#xff0c;会…

Mysql数据库管理与高可用

目录 一、克隆/复制一个表1.1 方法一1.2 方法二 二、清空表&#xff0c;删除表内所有数据2.1 方法一2.2 方法二2.3 drop、truncate、delete对比①.drop table name②.truncate table table_name③.delete from table_name小结&#xff1a; 三、创建临时的表四、用户管理4.1 新建…

MSQL知识学习07(MySQL执行计划分析)

1、什么是执行计划&#xff1f; 执行计划 是指一条 SQL 语句在经过 MySQL 查询优化器 的优化会后&#xff0c;具体的执行方式。 执行计划通常用于 SQL 性能分析、优化等场景。通过 EXPLAIN 的结果&#xff0c;可以了解到如数据表的查询顺序、数据查询操作的操作类型、哪些索引…

【刷题之路Ⅱ】LeetCode 143. 重排链表

【刷题之路Ⅱ】LeetCode 143. 重排链表 一、题目描述二、解题1、方法1——线性表辅助1.1、思路分析1.2、代码实现 2、方法2——中间节点反转链表合并链表2.1、思路分析2.2、代码实现 一、题目描述 原题连接&#xff1a; 143. 重排链表 题目描述&#xff1a; 给定一个单链表 L …

7. Docker——Dockerfile

本章讲解知识点 DockerfileDockerfile 常用命令Dockerfile 综合示例Docker Compose当我们理解了镜像的基本原理后,我们就可以开始 Dockerfile 的学习了。 1. Dockerfile Dockerfile 是用于构建 Docker 镜像的脚本。它包含一组指令,按顺序执行以创建 Docker 镜像,从而使其可…

多通道振弦传感器无线采集仪通过短信和FTP文件修改参数

多通道振弦传感器无线采集仪通过短信和FTP文件修改参数 通过短信修改参数 向设备发送参数修改指令&#xff0c;设备在下次采发过程中若收到包含有合法指令的短信时会解析并执行短信内的指令&#xff0c;参数修改完成后会以短信形式回发应答信息。短信指令的格式如下&#xff1a…

ChatGPT实现仪表盘生成

仪表盘生成 Grafana是开源社区最流行的数据可视化软件&#xff0c;一定程度上也和 superset 一起被视为 tableau 等商业 BI 的开源替代品&#xff0c;很多IT 团队、科研团队&#xff0c;都会使用 Grafana 来做数据监控、挖掘分析。Grafana社区也有很多贡献者&#xff0c;在 gi…

设计模式-基本概念

设计模式-基本概念 基本概念奇异递归模板模式&#xff08;CRTP&#xff09;说明示例例子1&#xff1a;对象计数例子2&#xff1a;多态复制构造例子4&#xff1a;std::enable_shared_from_this例子5 树简单遍历 混合继承属性SOLID 设计原则 参考 基本概念 奇异递归模板模式&…