SpringCloud 微服务全栈体系(二)
第三章 Eureka 注册中心
- 假如我们的服务提供者 user-service 部署了多个实例,如图:

-
思考几个问题:
- order-service 在发起远程调用的时候,该如何得知 user-service 实例的 ip 地址和端口?
- 有多个 user-service 实例地址,order-service 调用时该如何选择?
- order-service 如何得知某个 user-service 实例是否依然健康,是不是已经宕机?
一、Eureka 的结构和作用
- 这些问题都需要利用 SpringCloud 中的注册中心来解决,其中最广为人知的注册中心就是 Eureka,其结构如下:

-
回答之前的各个问题:
-
问题 1:order-service 如何得知 user-service 实例地址?
-
获取地址信息的流程如下:
- user-service 服务实例启动后,将自己的信息注册到 eureka-server(Eureka 服务端)。这个叫服务注册
- eureka-server 保存服务名称到服务实例地址列表的映射关系
- order-service 根据服务名称,拉取实例地址列表。这个叫服务发现或服务拉取
-
-
问题 2:order-service 如何从多个 user-service 实例中选择具体的实例?
- order-service 从实例列表中利用负载均衡算法选中一个实例地址
- 向该实例地址发起远程调用
-
问题 3:order-service 如何得知某个 user-service 实例是否依然健康,是不是已经宕机?
- user-service 会每隔一段时间(默认 30 秒)向 eureka-server 发起请求,报告自己状态,称为心跳
- 当超过一定时间没有发送心跳时,eureka-server 会认为微服务实例故障,将该实例从服务列表中剔除
- order-service 拉取服务时,就能将故障实例排除了
注意:一个微服务,既可以是服务提供者,又可以是服务消费者,因此 eureka 将服务注册、服务发现等功能统一封装到了 eureka-client 端
因此,接下来我们动手实践的步骤包括:

二、搭建 eureka-server
- 首先注册中心服务端:eureka-server,这必须是一个独立的微服务
1. 创建 eureka-server 服务
- 在 cloud-demo 父工程下,创建一个子模块:

- 填写模块信息:

- 然后填写服务信息:

2. 引入 eureka 依赖
- 引入 SpringCloud 为 eureka 提供的 starter 依赖:
<dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
</dependency>
3. 编写启动类
- 给 eureka-server 服务编写一个启动类,一定要添加一个@EnableEurekaServer 注解,开启 eureka 的注册中心功能:
package com.alex.eureka;import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;@SpringBootApplication
@EnableEurekaServer
public class EurekaApplication {public static void main(String[] args) {SpringApplication.run(EurekaApplication.class, args);}
}
4. 编写配置文件
- 编写一个 application.yml 文件,内容如下:
server:port: 10086
spring:application:name: eureka-server
eureka:client:service-url:defaultZone: http://127.0.0.1:10086/eureka
5. 启动服务
-
启动微服务,然后在浏览器访问:http://127.0.0.1:10086
-
看到下面结果应该是成功了:

三、服务注册
- 下面,我们将 user-service 注册到 eureka-server 中去。
1. 引入依赖
- 在 user-service 的 pom 文件中,引入下面的 eureka-client 依赖:
<dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
2. 配置文件
- 在 user-service 中,修改 application.yml 文件,添加服务名称、eureka 地址:
spring:application:name: userservice
eureka:client:service-url:defaultZone: http://127.0.0.1:10086/eureka
3. 启动多个 user-service 实例
-
为了演示一个服务有多个实例的场景,我们添加一个 SpringBoot 的启动配置,再启动一个 user-service。
-
首先,复制原来的 user-service 启动配置:

- 然后,在弹出的窗口中,填写信息:

- 现在,SpringBoot 窗口会出现两个 user-service 启动配置:

-
不过,第一个是 8081 端口,第二个是 8082 端口。
-
启动两个 user-service 实例:

- 查看 eureka-server 管理页面:

四、服务发现
- 下面,我们将 order-service 的逻辑修改:向 eureka-server 拉取 user-service 的信息,实现服务发现。
1. 引入依赖
-
之前说过,服务发现、服务注册统一都封装在 eureka-client 依赖,因此这一步与服务注册时一致。
-
在 order-service 的 pom 文件中,引入下面的 eureka-client 依赖:
<dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
2. 配置文件
-
服务发现也需要知道 eureka 地址,因此第二步与服务注册一致,都是配置 eureka 信息:
-
在 order-service 中,修改 application.yml 文件,添加服务名称、eureka 地址:
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 注解:

- 修改 order-service 服务中的 com.alex.order.service 包下的 OrderService 类中的 queryOrderById 方法。修改访问的 url 路径,用服务名代替 ip、端口:

- spring 会自动帮助我们从 eureka-server 端,根据 userservice 这个服务名称,获取实例列表,而后完成负载均衡。
第四章 Ribbon 负载均衡
- 上一章中,我们添加了@LoadBalanced 注解,即可实现负载均衡功能,这是什么原理呢?
一、负载均衡原理
- SpringCloud 底层其实是利用了一个名为 Ribbon 的组件,来实现负载均衡功能的。

- 那么我们发出的请求明明是 http://userservice/user/1,怎么变成了 http://localhost:8081 的呢?
二、源码跟踪
-
为什么我们只输入了 service 名称就可以访问了呢?之前还要获取 ip 和端口。
-
显然有人帮我们根据 service 名称,获取到了服务实例的 ip 和端口。它就是
LoadBalancerInterceptor,这个类会在对 RestTemplate 的请求进行拦截,然后从 Eureka 根据服务 id 获取服务列表,随后利用负载均衡算法得到真实的服务地址信息,替换服务 id。 -
我们进行源码跟踪:
1. LoadBalancerInterceptor

-
可以看到这里的 intercept 方法,拦截了用户的 HttpRequest 请求,然后做了几件事:
request.getURI():获取请求 uri,本例中就是 http://user-service/user/8originalUri.getHost():获取 uri 路径的主机名,其实就是服务 id,user-servicethis.loadBalancer.execute():处理服务 id,和用户请求。
-
这里的
this.loadBalancer是LoadBalancerClient类型,我们继续跟入。
2. LoadBalancerClient
- 继续跟入 execute 方法:

-
代码是这样的:
- getLoadBalancer(serviceId):根据服务 id 获取 ILoadBalancer,而 ILoadBalancer 会拿着服务 id 去 eureka 中获取服务列表并保存起来。
- getServer(loadBalancer):利用内置的负载均衡算法,从服务列表中选择一个。本例中,可以看到获取了 8082 端口的服务
-
放行后,再次访问并跟踪,发现获取的是 8081:

- 果然实现了负载均衡。
3. 负载均衡策略 IRule
- 在刚才的代码中,可以看到获取服务使通过一个
getServer方法来做负载均衡:

- 我们继续跟入:

- 继续跟踪源码 chooseServer 方法,发现这么一段代码:

- 我们看看这个 rule 是谁:

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

-
这不就是轮询的意思嘛。
-
到这里,整个负载均衡的流程我们就清楚了。
4. 总结
- 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,发起真实请求
三、负载均衡策略
1. 负载均衡策略
- 负载均衡的规则都定义在 IRule 接口中,而 IRule 有很多不同的实现类:

- 不同规则的含义如下:
| 内置负载均衡规则类 | 规则描述 |
|---|---|
| RoundRobinRule | 简单轮询服务列表来选择服务器。它是 Ribbon 默认的负载均衡规则。 |
| AvailabilityFilteringRule | 对以下两种服务器进行忽略: (1)在默认情况下,这台服务器如果 3 次连接失败,这台服务器就会被设置为“短路”状态。短路状态将持续 30 秒,如果再次连接失败,短路的持续时间就会几何级地增加。 (2)并发数过高的服务器。如果一个服务器的并发连接数过高,配置了 AvailabilityFilteringRule 规则的客户端也会将其忽略。并发连接数的上限,可以由客户端的..ActiveConnectionsLimit 属性进行配置。 |
| WeightedResponseTimeRule | 为每一个服务器赋予一个权重值。服务器响应时间越长,这个服务器的权重就越小。这个规则会随机选择服务器,这个权重值会影响服务器的选择。 |
| ZoneAvoidanceRule | 以区域可用的服务器为基础进行服务器的选择。使用 Zone 对服务器进行分类,这个 Zone 可以理解为一个机房、一个机架等。而后再对 Zone 内的多个服务做轮询。 |
| BestAvailableRule | 忽略那些短路的服务器,并选择并发数较低的服务器。 |
| RandomRule | 随机选择一个可用的服务器。 |
| RetryRule | 重试机制的选择逻辑 |
- 默认的实现就是 ZoneAvoidanceRule,是一种轮询方案
2. 自定义负载均衡策略
- 通过定义 IRule 实现可以修改负载均衡规则,有两种方式:
2.1 代码方式
- 在 order-service 中的 OrderApplication 类中,定义一个新的 IRule:
@Bean
public IRule randomRule(){return new RandomRule();
}
2.2 配置文件方式
- 在 order-service 的 application.yml 文件中,添加新的配置也可以修改规则:
userservice: # 给某个微服务配置负载均衡规则,这里是userservice服务ribbon:NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule # 负载均衡规则
注意,一般用默认的负载均衡规则,不做修改。
四、饥饿加载
-
Ribbon 默认是采用懒加载,即第一次访问时才会去创建 LoadBalanceClient,请求时间会很长。
-
而饥饿加载则会在项目启动时创建,降低第一次访问的耗时,通过下面配置开启饥饿加载:
ribbon:eager-load:enabled: trueclients: userservice
相关文章:
SpringCloud 微服务全栈体系(二)
第三章 Eureka 注册中心 假如我们的服务提供者 user-service 部署了多个实例,如图: 思考几个问题: order-service 在发起远程调用的时候,该如何得知 user-service 实例的 ip 地址和端口?有多个 user-service 实例地址…...
flutter 常用组件:列表ListView
文章目录 总结#1、通过构造方法直接构建 ListView 提供了一个默认构造函数 ListView,我们可以通过设置它的 children 参数,很方便地将所有的子 Widget 包含到 ListView 中。 不过,这种创建方式要求提前将所有子 Widget 一次性创建好,而不是等到它们真正在屏幕上需要显示时才…...
十四天学会C++之第七天:STL(标准模板库)
1. STL容器 什么是STL容器,为什么使用它们。向量(vector):使用向量存储数据。列表(list):使用列表实现双向链表。映射(map):使用映射实现键值对存储。 什么…...
Linux 下安装 miniconda,管理 Python 多环境
安装 miniconda 1、下载安装包 Miniconda3-py37_22.11.1-1-Linux-x86_64.sh,或者自行选择版本 2、把安装包上传到服务器上,这里放在 /home/software 3、安装 bash Miniconda3-py37_22.11.1-1-Linux-x86_64.sh 4、按回车 Welcome to Miniconda3 py37…...
Django和jQuery,实现Ajax表格数据分页展示
1.需求描述 当存在重新请求接口才能返回数据的功能时,若页面的内容很长,每次点击一个功能,页面又回到了顶部,对于用户的体验感不太友好,我们希望当用户点击这类的功能时,能直接加载到数据,请求…...
k8s认证
1. 证书介绍 服务端保留公钥和私钥,客户端使用root CA认证服务端的公钥 一共有多少证书: *Etcd: Etcd对外提供服务,要有一套etcd server证书Etcd各节点之间进行通信,要有一套etcd peer证书Kube-APIserver访问Etcd&a…...
基于python开发的IP修改工具
工作中调试设备需要经常修改电脑IP,非常麻烦,这里使用Pythontkinter做了一个IP修改工具 说明: 1.启动程序读取config.json文件2.如果没有该文件则创建,写入当前网卡信息3.通过配置信息进行网卡状态修改4.更新文件状态,删除或修…...
Mybatis源码分析
1. Mybatis整体三层设计 SSM中,Spring、SpringMVC已经在前面文章源码分析总结过了,Mybatis源码相对Spring和SpringMVC而言是的简单的,只有一个项目,项目下分了很多包。从宏观上了解Mybatis的整体框架分为三层,分别是基…...
python树结构包treelib入门及其计算应用
树是计算机科学中重要的数据结构。例如决策树等机器学习算法设计、文件系统索引等。创建treelib包是为了在Python中提供树数据结构的有效实现。 Treelib的主要特点包括: 节点搜索的高效操作。支持常见的树操作,如遍历、插入、删除、节点移动、浅/深复制…...
Rust之自动化测试(三): 测试组合
开发环境 Windows 10Rust 1.73.0 VS Code 1.83.1 项目工程 这里继续沿用上次工程rust-demo 测试组合 正如本章开始时提到的,测试是一个复杂的学科,不同的人使用不同的术语和组织。Rust社区根据两个主要类别来考虑测试:单元测试和集成测试。单元测试很…...
专业管理菜单的增删改、查重
1,点击专业管理菜单------查询所有专业信息列表 ①点击菜单,切换专业组件 ②切换到列表组件后,向后端发送请求到Servlet ③调用DAO层,查询数据库(sql),封装查询到的内容 ④从后端向前端做出…...
vue3插件开发,上传npm
创建插件 在vue3工程下,创建组件vue页: toolset.vue。并设置组件名称。注册全局组件。新建index.js文件。内容如下,可在main.js中引入index.js,注册该组件进行测试。API服务是LLM(大语言模型)开放接口平台:持续接入各种主流的大模型接口,并提供简单、易用、统一的API交互…...
【python】屈小原现在要为学校写校庆贺文(CTGU百年校庆)
题目: """ 题目描述: 屈小原需要为学校的校庆写一篇贺文,共需写下n个字,但他目前只完成了1个字。屈小原可以进行两种操作: 在文档的末尾添加一个字,这样字数就会变为x1。 写下与当前字数相同…...
探索未来的视觉革命:卷积神经网络的崭新时代(二)
💗💗💗欢迎来到我的博客,你将找到有关如何使用技术解决问题的文章,也会找到某个技术的学习路线。无论你是何种职业,我都希望我的博客对你有所帮助。最后不要忘记订阅我的博客以获取最新文章,也欢…...
日语AI面试高效通关秘籍:专业解读与青柚面试智能助攻
在如今就业市场竞争日益激烈的背景下,越来越多的求职者将目光投向了日本及中日双语岗位。但是,一场日语面试往往让许多人感到步履维艰。你是否也曾因为面试官抛出的“刁钻问题”而心生畏惧?面对生疏的日语交流环境,即便提前恶补了…...
简易版抽奖活动的设计技术方案
1.前言 本技术方案旨在设计一套完整且可靠的抽奖活动逻辑,确保抽奖活动能够公平、公正、公开地进行,同时满足高并发访问、数据安全存储与高效处理等需求,为用户提供流畅的抽奖体验,助力业务顺利开展。本方案将涵盖抽奖活动的整体架构设计、核心流程逻辑、关键功能实现以及…...
JVM垃圾回收机制全解析
Java虚拟机(JVM)中的垃圾收集器(Garbage Collector,简称GC)是用于自动管理内存的机制。它负责识别和清除不再被程序使用的对象,从而释放内存空间,避免内存泄漏和内存溢出等问题。垃圾收集器在Ja…...
电脑插入多块移动硬盘后经常出现卡顿和蓝屏
当电脑在插入多块移动硬盘后频繁出现卡顿和蓝屏问题时,可能涉及硬件资源冲突、驱动兼容性、供电不足或系统设置等多方面原因。以下是逐步排查和解决方案: 1. 检查电源供电问题 问题原因:多块移动硬盘同时运行可能导致USB接口供电不足&#x…...
【决胜公务员考试】求职OMG——见面课测验1
2025最新版!!!6.8截至答题,大家注意呀! 博主码字不易点个关注吧,祝期末顺利~~ 1.单选题(2分) 下列说法错误的是:( B ) A.选调生属于公务员系统 B.公务员属于事业编 C.选调生有基层锻炼的要求 D…...
laravel8+vue3.0+element-plus搭建方法
创建 laravel8 项目 composer create-project --prefer-dist laravel/laravel laravel8 8.* 安装 laravel/ui composer require laravel/ui 修改 package.json 文件 "devDependencies": {"vue/compiler-sfc": "^3.0.7","axios": …...
C++ 设计模式 《小明的奶茶加料风波》
👨🎓 模式名称:装饰器模式(Decorator Pattern) 👦 小明最近上线了校园奶茶配送功能,业务火爆,大家都在加料: 有的同学要加波霸 🟤,有的要加椰果…...
2.3 物理层设备
在这个视频中,我们要学习工作在物理层的两种网络设备,分别是中继器和集线器。首先来看中继器。在计算机网络中两个节点之间,需要通过物理传输媒体或者说物理传输介质进行连接。像同轴电缆、双绞线就是典型的传输介质,假设A节点要给…...
node.js的初步学习
那什么是node.js呢? 和JavaScript又是什么关系呢? node.js 提供了 JavaScript的运行环境。当JavaScript作为后端开发语言来说, 需要在node.js的环境上进行当JavaScript作为前端开发语言来说,需要在浏览器的环境上进行 Node.js 可…...
从实验室到产业:IndexTTS 在六大核心场景的落地实践
一、内容创作:重构数字内容生产范式 在短视频创作领域,IndexTTS 的语音克隆技术彻底改变了配音流程。B 站 UP 主通过 5 秒参考音频即可克隆出郭老师音色,生成的 “各位吴彦祖们大家好” 语音相似度达 97%,单条视频播放量突破百万…...
